Merge pull request #6121 from daverodgman/pr277

cert_write - add a way to set extended key usages - rebase
diff --git a/ChangeLog.d/cert_write-set-extended-key-usages.txt b/ChangeLog.d/cert_write-set-extended-key-usages.txt
new file mode 100644
index 0000000..18b7b04
--- /dev/null
+++ b/ChangeLog.d/cert_write-set-extended-key-usages.txt
@@ -0,0 +1,6 @@
+Features
+   * cert_write: support for setting extended key usage attributes. A
+     corresponding new public API call has been added in the library,
+     mbedtls_x509write_crt_set_ext_key_usage().
+   * cert_write: support for writing certificate files in either PEM
+     or DER format.
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 6c09b3a..d2b7648 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -1146,6 +1146,19 @@
                                          unsigned int key_usage );
 
 /**
+ * \brief           Set the Extended Key Usage Extension
+ *                  (e.g. MBEDTLS_OID_SERVER_AUTH)
+ *
+ * \param ctx       CRT context to use
+ * \param exts      extended key usage extensions to set, a sequence of
+ *                  MBEDTLS_ASN1_OID objects
+ *
+ * \return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED
+ */
+int mbedtls_x509write_crt_set_ext_key_usage( mbedtls_x509write_cert *ctx,
+                                             const mbedtls_asn1_sequence *exts );
+
+/**
  * \brief           Set the Netscape Cert Type flags
  *                  (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)
  *
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 52942a9..254c4b2 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -296,6 +296,43 @@
     return( 0 );
 }
 
+int mbedtls_x509write_crt_set_ext_key_usage( mbedtls_x509write_cert *ctx,
+                                             const mbedtls_asn1_sequence *exts )
+{
+    unsigned char buf[256];
+    unsigned char *c = buf + sizeof(buf);
+    int ret;
+    size_t len = 0;
+    const mbedtls_asn1_sequence *last_ext = NULL;
+    const mbedtls_asn1_sequence *ext;
+
+    memset( buf, 0, sizeof(buf) );
+
+    /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */
+    if( exts == NULL )
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+    /* Iterate over exts backwards, so we write them out in the requested order */
+    while( last_ext != exts )
+    {
+        for( ext = exts; ext->next != last_ext; ext = ext->next ) {}
+        if( ext->buf.tag != MBEDTLS_ASN1_OID )
+            return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( &c, buf, ext->buf.p, ext->buf.len ) );
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, ext->buf.len ) );
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OID ) );
+        last_ext = ext;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+
+    return mbedtls_x509write_crt_set_extension( ctx,
+                         MBEDTLS_OID_EXTENDED_KEY_USAGE,
+                         MBEDTLS_OID_SIZE( MBEDTLS_OID_EXTENDED_KEY_USAGE ),
+                         1, c, len );
+}
+
 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
                                     unsigned char ns_cert_type )
 {
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index c93ff1e..f9366fe 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -38,6 +38,7 @@
 
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/oid.h"
 #include "mbedtls/entropy.h"
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/md.h"
@@ -47,6 +48,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#define SET_OID(x, oid) \
+    do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char*)oid; } while( 0 )
+
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
 #define USAGE_CSR                                                           \
     "    request_file=%%s         default: (empty)\n"                           \
@@ -56,6 +60,9 @@
 #define USAGE_CSR ""
 #endif /* MBEDTLS_X509_CSR_PARSE_C */
 
+#define FORMAT_PEM              0
+#define FORMAT_DER              1
+
 #define DFL_ISSUER_CRT          ""
 #define DFL_REQUEST_FILE        ""
 #define DFL_SUBJECT_KEY         "subject.key"
@@ -71,13 +78,16 @@
 #define DFL_SELFSIGN            0
 #define DFL_IS_CA               0
 #define DFL_MAX_PATHLEN         -1
+#define DFL_SIG_ALG             MBEDTLS_MD_SHA256
 #define DFL_KEY_USAGE           0
+#define DFL_EXT_KEY_USAGE       NULL
 #define DFL_NS_CERT_TYPE        0
 #define DFL_VERSION             3
 #define DFL_AUTH_IDENT          1
 #define DFL_SUBJ_IDENT          1
 #define DFL_CONSTRAINTS         1
 #define DFL_DIGEST              MBEDTLS_MD_SHA256
+#define DFL_FORMAT              FORMAT_PEM
 
 #define USAGE \
     "\n usage: cert_write param=<>...\n"                \
@@ -129,6 +139,14 @@
     "                            key_cert_sign\n"  \
     "                            crl_sign\n"              \
     "                            (Considered for v3 only)\n"\
+    "    ext_key_usage=%%s        default: (empty)\n"      \
+    "                            Comma-separated-list of values:\n"     \
+    "                            serverAuth\n"             \
+    "                            clientAuth\n"             \
+    "                            codeSigning\n"            \
+    "                            emailProtection\n"        \
+    "                            timeStamping\n"           \
+    "                            OCSPSigning\n"            \
     "    ns_cert_type=%%s         default: (empty)\n"       \
     "                            Comma-separated-list of values:\n"     \
     "                            ssl_client\n"            \
@@ -138,6 +156,7 @@
     "                            ssl_ca\n"                \
     "                            email_ca\n"              \
     "                            object_signing_ca\n"     \
+    "   format=pem|der           default: pem\n"         \
     "\n"
 
 
@@ -167,7 +186,9 @@
     int version;                /* CRT version                          */
     mbedtls_md_type_t md;       /* Hash used for signing                */
     unsigned char key_usage;    /* key usage flags                      */
+    mbedtls_asn1_sequence *ext_key_usage; /* extended key usages        */
     unsigned char ns_cert_type; /* NS cert type                         */
+    int format;                 /* format                               */
 } opt;
 
 int write_certificate( mbedtls_x509write_cert *crt, const char *output_file,
@@ -177,19 +198,33 @@
     int ret;
     FILE *f;
     unsigned char output_buf[4096];
+    unsigned char *output_start;
     size_t len = 0;
 
     memset( output_buf, 0, 4096 );
-    if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096,
-                                           f_rng, p_rng ) ) < 0 )
-        return( ret );
+    if ( opt.format == FORMAT_DER )
+    {
+        ret = mbedtls_x509write_crt_der( crt, output_buf, 4096,
+                                           f_rng, p_rng );
+        if( ret < 0 )
+            return( ret );
 
-    len = strlen( (char *) output_buf );
+        len = ret;
+        output_start = output_buf + 4096 - len;
+    } else {
+        ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096,
+                                           f_rng, p_rng );
+        if( ret < 0 )
+            return( ret );
+
+        len = strlen( (char *) output_buf );
+        output_start = output_buf;
+    }
 
     if( ( f = fopen( output_file, "w" ) ) == NULL )
         return( -1 );
 
-    if( fwrite( output_buf, 1, len, f ) != len )
+    if( fwrite( output_start, 1, len, f ) != len )
     {
         fclose( f );
         return( -1 );
@@ -218,6 +253,7 @@
 #endif
     mbedtls_x509write_cert crt;
     mbedtls_mpi serial;
+    mbedtls_asn1_sequence *ext_key_usage;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
     const char *pers = "crt example app";
@@ -235,7 +271,7 @@
     mbedtls_x509_csr_init( &csr );
 #endif
     mbedtls_x509_crt_init( &issuer_crt );
-    memset( buf, 0, 1024 );
+    memset( buf, 0, sizeof(buf) );
 
     if( argc == 0 )
     {
@@ -260,12 +296,14 @@
     opt.is_ca               = DFL_IS_CA;
     opt.max_pathlen         = DFL_MAX_PATHLEN;
     opt.key_usage           = DFL_KEY_USAGE;
+    opt.ext_key_usage       = DFL_EXT_KEY_USAGE;
     opt.ns_cert_type        = DFL_NS_CERT_TYPE;
     opt.version             = DFL_VERSION - 1;
     opt.md                  = DFL_DIGEST;
     opt.subject_identifier   = DFL_SUBJ_IDENT;
     opt.authority_identifier = DFL_AUTH_IDENT;
     opt.basic_constraints    = DFL_CONSTRAINTS;
+    opt.format              = DFL_FORMAT;
 
     for( i = 1; i < argc; i++ )
     {
@@ -417,6 +455,41 @@
                 q = r;
             }
         }
+        else if( strcmp( p, "ext_key_usage" ) == 0 )
+        {
+            mbedtls_asn1_sequence **tail = &opt.ext_key_usage;
+
+            while( q != NULL )
+            {
+                if( ( r = strchr( q, ',' ) ) != NULL )
+                    *r++ = '\0';
+
+                ext_key_usage = mbedtls_calloc( 1, sizeof(mbedtls_asn1_sequence) );
+                ext_key_usage->buf.tag = MBEDTLS_ASN1_OID;
+                if( strcmp( q, "serverAuth" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_SERVER_AUTH );
+                else if( strcmp( q, "clientAuth" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_CLIENT_AUTH );
+                else if( strcmp( q, "codeSigning" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_CODE_SIGNING );
+                else if( strcmp( q, "emailProtection" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_EMAIL_PROTECTION );
+                else if( strcmp( q, "timeStamping" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_TIME_STAMPING );
+                else if( strcmp( q, "OCSPSigning" ) == 0 )
+                    SET_OID( ext_key_usage->buf, MBEDTLS_OID_OCSP_SIGNING );
+                else
+                {
+                    mbedtls_printf( "Invalid argument for option %s\n", p );
+                    goto usage;
+                }
+
+                *tail = ext_key_usage;
+                tail = &ext_key_usage->next;
+
+                q = r;
+            }
+        }
         else if( strcmp( p, "ns_cert_type" ) == 0 )
         {
             while( q != NULL )
@@ -447,6 +520,16 @@
                 q = r;
             }
         }
+        else if( strcmp( p, "format" ) == 0 )
+        {
+            if      ( strcmp(q, "der" ) == 0 ) opt.format = FORMAT_DER;
+            else if ( strcmp(q, "pem" ) == 0 ) opt.format = FORMAT_PEM;
+            else
+            {
+                mbedtls_printf( "Invalid argument for option %s\n", p );
+                goto usage;
+            }
+        }
         else
             goto usage;
     }
@@ -463,7 +546,7 @@
                                (const unsigned char *) pers,
                                strlen( pers ) ) ) != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d - %s\n",
                         ret, buf );
         goto exit;
@@ -478,7 +561,7 @@
 
     if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_mpi_read_string "
                         "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -498,7 +581,7 @@
 
         if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -508,7 +591,7 @@
                                  &issuer_crt.subject );
         if( ret < 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509_dn_gets "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -532,7 +615,7 @@
 
         if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509_csr_parse_file "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -542,7 +625,7 @@
                                  &csr.subject );
         if( ret < 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509_dn_gets "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -567,7 +650,7 @@
                 opt.subject_pwd, mbedtls_ctr_drbg_random, &ctr_drbg );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -583,7 +666,7 @@
             opt.issuer_pwd, mbedtls_ctr_drbg_random, &ctr_drbg );
     if( ret != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile "
                         "returned -x%02x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -618,7 +701,7 @@
      */
     if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_subject_name "
                         "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -626,7 +709,7 @@
 
     if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_issuer_name "
                         "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -641,7 +724,7 @@
     ret = mbedtls_x509write_crt_set_serial( &crt, &serial );
     if( ret != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_serial "
                         "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -650,7 +733,7 @@
     ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
     if( ret != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_validity "
                         "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
         goto exit;
@@ -668,7 +751,7 @@
                                                            opt.max_pathlen );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  x509write_crt_set_basic_contraints "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -687,7 +770,7 @@
         ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_subject"
                             "_key_identifier returned -0x%04x - %s\n\n",
                             (unsigned int) -ret, buf );
@@ -706,7 +789,7 @@
         ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_authority_"
                             "key_identifier returned -0x%04x - %s\n\n",
                             (unsigned int) -ret, buf );
@@ -726,7 +809,7 @@
         ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_key_usage "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -735,6 +818,22 @@
         mbedtls_printf( " ok\n" );
     }
 
+    if( opt.ext_key_usage )
+    {
+        mbedtls_printf( "  . Adding the Extended Key Usage extension ..." );
+        fflush( stdout );
+
+        ret = mbedtls_x509write_crt_set_ext_key_usage( &crt, opt.ext_key_usage );
+        if( ret != 0 )
+        {
+            mbedtls_strerror( ret, buf, sizeof(buf) );
+            mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_ext_key_usage returned -0x%02x - %s\n\n", (unsigned int) -ret, buf );
+            goto exit;
+        }
+
+        mbedtls_printf( " ok\n" );
+    }
+
     if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
         opt.ns_cert_type != 0 )
     {
@@ -744,7 +843,7 @@
         ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_strerror( ret, buf, sizeof(buf) );
             mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_ns_cert_type "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
@@ -762,7 +861,7 @@
     if( ( ret = write_certificate( &crt, opt.output_file,
                                    mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
     {
-        mbedtls_strerror( ret, buf, 1024 );
+        mbedtls_strerror( ret, buf, sizeof(buf) );
         mbedtls_printf( " failed\n  !  write_certificate -0x%04x - %s\n\n",
                         (unsigned int) -ret, buf );
         goto exit;
diff --git a/tests/data_files/server1.key_ext_usage.crt b/tests/data_files/server1.key_ext_usage.crt
new file mode 100644
index 0000000..bbe2c35
--- /dev/null
+++ b/tests/data_files/server1.key_ext_usage.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDVzCCAj+gAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/
+uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD
+d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf
+CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
+lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
+bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
+o2UwYzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf
+BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zAWBgNVHSUBAf8EDDAKBggr
+BgEFBQcDATANBgkqhkiG9w0BAQUFAAOCAQEAegtCN4EObE69RjW1hKUEQ/InrIsf
+poKIgJCh3sck+FYKjcsMhRPBztnZaqjvkLnmCcq0Yv7uUDThHsNuu+NbeVr4flZL
+gUoSSdHXYrJ8qDYez6oGoxttoZ33sqD3LQfzWZhDoTyjGUHTiWaA6KidCsWzkhKY
+aNXF7O8dHO7k06I2UWt7SKbBm1dPj8OM4285kkQ7KCpG27ABtHePkp9aG66O/ktD
+GbZs0AaYpeVnB9v1vSp6xInDCWydDFbmEE0mzAQr285UU07QEpnU1W/2qZHfLxnQ
+GiDpR5pxoKXkskj2VuHPZPqbIkv9v2+bjeyXHDRSL7Rj087xhD5uXKb9fw==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server1.key_ext_usages.crt b/tests/data_files/server1.key_ext_usages.crt
new file mode 100644
index 0000000..0c3d963
--- /dev/null
+++ b/tests/data_files/server1.key_ext_usages.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/
+uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD
+d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf
+CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
+lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
+bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
+o28wbTAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf
+BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zAgBgNVHSUBAf8EFjAUBggr
+BgEFBQcDAwYIKwYBBQUHAwgwDQYJKoZIhvcNAQEFBQADggEBADIT9M10vT5yzMSR
+GaaImXjyTRIBK683Vxnq5jqAJ75KzNUC52aiCOfd9/hAMkq3Pj+r6tIsH+jsl5PL
+E4iv8GVDlbjA57icTD30XbolL4YPUvZYclxVopfRhTiDa5KJ1lYkUwWAE/Glj66Q
+WO7Hihl+GYXap2e7dBZ7hGHdv6J1gRfA1OW6iB23Wl4xb0Y1CGc16yJZwuFbtbwM
+w8z8a0XNd2UQTYesYlIvVpVcx2atgkbZwehPWGNCLGngz60fultj7JdLuUHi+r0z
+DtjbSPsHDZDAer6ZxjaA4hkcnppacFttC+deD8bQ8+2JjHF6Gb/MBnaYIbOZOBgC
+8CPIBjk=
+-----END CERTIFICATE-----
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 1844e5c..8411557 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -56,87 +56,95 @@
 
 Certificate write check Server1 SHA1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 1970
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not after 2050
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 1970, not after 2050
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 2050, not after 2059
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20500210144406":"20590210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20500210144406":"20590210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:1:-1:"data_files/server1.key_usage.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":0:0:"data_files/test-ca.crt"
+
+Certificate write check Server1 SHA1, one ext_key_usage
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"serverAuth":0:0:1:-1:"data_files/server1.key_ext_usage.crt":0:0:"data_files/test-ca.crt"
+
+Certificate write check Server1 SHA1, two ext_key_usages
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"codeSigning,timeStamping":0:0:1:-1:"data_files/server1.key_ext_usages.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.ca.crt":0:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":0:1:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.ca_noauthid.crt":1:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.ca_noauthid.crt":1:1:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:1:-1:"data_files/server1.key_usage.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.ca.crt":2:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":2:1:"data_files/test-ca.crt"
 
 Certificate write check Server5 ECDSA
 depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:0:0:1:-1:"data_files/server5.crt":0:0:"data_files/test-ca2.crt"
+x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"data_files/server5.crt":0:0:"data_files/test-ca2.crt"
 
 Certificate write check Server5 ECDSA, Opaque
 depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:0:0:1:-1:"":2:0:"data_files/test-ca2.crt"
+x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"":2:0:"data_files/test-ca2.crt"
 
 X509 String to Names #1
 mbedtls_x509_string_to_names:"C=NL,O=Offspark\, Inc., OU=PolarSSL":"C=NL, O=Offspark\, Inc., OU=PolarSSL":0
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 5caf143..aa54072 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -241,6 +241,7 @@
                      char *issuer_pwd, char *issuer_name,
                      char *serial_str, char *not_before, char *not_after,
                      int md_type, int key_usage, int set_key_usage,
+                     char *ext_key_usage,
                      int cert_type, int set_cert_type, int auth_ident,
                      int ver, char *cert_check_file, int pk_wrap, int is_ca,
                      char *cert_verify_file )
@@ -349,6 +350,31 @@
             TEST_ASSERT( mbedtls_x509write_crt_set_key_usage( &crt, key_usage ) == 0 );
         if( set_cert_type != 0 )
             TEST_ASSERT( mbedtls_x509write_crt_set_ns_cert_type( &crt, cert_type ) == 0 );
+        if( strcmp( ext_key_usage, "NULL" ) != 0 )
+        {
+            mbedtls_asn1_sequence exts[2];
+            memset( exts, 0, sizeof(exts) );
+
+#define SET_OID(x, oid)                \
+    do {                               \
+        x.len = MBEDTLS_OID_SIZE(oid); \
+        x.p   = (unsigned char*)oid;   \
+        x.tag = MBEDTLS_ASN1_OID;      \
+    }                                  \
+    while( 0 )
+
+            if( strcmp( ext_key_usage, "serverAuth" ) == 0 )
+            {
+                SET_OID( exts[0].buf, MBEDTLS_OID_SERVER_AUTH );
+            }
+            else if( strcmp( ext_key_usage, "codeSigning,timeStamping" ) == 0 )
+            {
+                SET_OID( exts[0].buf, MBEDTLS_OID_CODE_SIGNING );
+                exts[0].next = &exts[1];
+                SET_OID( exts[1].buf, MBEDTLS_OID_TIME_STAMPING );
+            }
+            TEST_ASSERT( mbedtls_x509write_crt_set_ext_key_usage( &crt, exts ) == 0 );
+        }
     }
 
     ret = mbedtls_x509write_crt_pem( &crt, buf, sizeof( buf ),