From b2dc3fa72ed519eb739e41ac25d49eb943bca7a1 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Thu, 21 Mar 2019 13:40:13 +0200
Subject: [PATCH 01/27] Suppport otherName of type hardware module name

Add support of parsing of subject alternative name, of type otherName.
Currently supports only hardware module name, as defined in rfc 4108.
---
 include/mbedtls/oid.h                         |   3 +
 include/mbedtls/x509.h                        |  22 ++
 include/mbedtls/x509_crt.h                    |  61 +++-
 library/x509_crt.c                            | 305 ++++++++++++++++--
 tests/data_files/Makefile                     |   6 +
 tests/data_files/multiple_san.crt             |  12 +
 tests/data_files/server5-othername.crt        |  11 +
 .../server5-unsupported_othername.crt         |  12 +
 tests/data_files/test-ca.opensslconf          |  19 ++
 tests/suites/test_suite_x509parse.data        |  36 ++-
 tests/suites/test_suite_x509parse.function    | 108 +++++++
 11 files changed, 565 insertions(+), 30 deletions(-)
 create mode 100644 tests/data_files/multiple_san.crt
 create mode 100644 tests/data_files/server5-othername.crt
 create mode 100644 tests/data_files/server5-unsupported_othername.crt

diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 55f72c8eb..c516b7aaf 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -214,6 +214,9 @@
  */
 #define MBEDTLS_OID_WISUN_FAN                  MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01"
 
+#define MBEDTLS_OID_ON                          MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */
+#define MBEDTLS_OID_ON_HW_MODULE_NAME           MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */
+
 /*
  * PKCS definition OIDs
  */
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index b63e864e3..054ff2ecc 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -109,6 +109,28 @@
 /* \} name */
 /* \} addtogroup x509_module */
 
+/*
+ * X.509 v3 Subject Alternative Name types.
+ *      otherName                       [0]     OtherName,
+ *      rfc822Name                      [1]     IA5String,
+ *      dNSName                         [2]     IA5String,
+ *      x400Address                     [3]     ORAddress,
+ *      directoryName                   [4]     Name,
+ *      ediPartyName                    [5]     EDIPartyName,
+ *      uniformResourceIdentifier       [6]     IA5String,
+ *      iPAddress                       [7]     OCTET STRING,
+ *      registeredID                    [8]     OBJECT IDENTIFIER
+ */
+#define MBEDTLS_X509_SAN_OTHER_NAME                      0
+#define MBEDTLS_X509_SAN_RFC822_NAME                     1
+#define MBEDTLS_X509_SAN_DNS_NAME                        2
+#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME               3
+#define MBEDTLS_X509_SAN_DIRECTORY_NAME                  4
+#define MBEDTLS_X509_SAN_EDI_PARTY_NAME                  5
+#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER     6
+#define MBEDTLS_X509_SAN_IP_ADDRESS                      7
+#define MBEDTLS_X509_SAN_REGISTERED_ID                   8
+
 /*
  * X.509 v3 Key Usage Extension flags
  * Reminder: update x509_info_key_usage() when adding new flags.
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index a0f32cb30..4a796173f 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -76,7 +76,7 @@ typedef struct mbedtls_x509_crt
     mbedtls_x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
     mbedtls_x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
     mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
-    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName supported). */
+    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName and OtherName supported). */
 
     int ext_types;              /**< Bit string containing detected and parsed extensions */
     int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
@@ -97,6 +97,44 @@ typedef struct mbedtls_x509_crt
 }
 mbedtls_x509_crt;
 
+/*
+ * From RFC 5280 section 4.2.1.6:
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ */
+typedef struct mbedtls_x509_san_other_name
+{
+    mbedtls_x509_buf type_id;                   /**< The type id. */
+    union
+    {
+        /*
+         * From RFC 4108 section 5:
+         * HardwareModuleName ::= SEQUENCE {
+         *                         hwType OBJECT IDENTIFIER,
+         *                         hwSerialNum OCTET STRING }
+         */
+        mbedtls_x509_name hardware_module_name;
+    }
+    value;
+}
+mbedtls_x509_san_other_name;
+
+/*
+ * A structure for holding the parsed Subject Alternative Name, according to type
+ */
+typedef struct mbedtls_x509_subject_alternative_name
+{
+    int type;                              /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
+    union {
+        mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
+        mbedtls_x509_buf   unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
+    }
+    san; /**< A union of the supported SAN types */
+    struct mbedtls_x509_subject_alternative_name *next; /**< The next SAN in the list. */
+}
+mbedtls_x509_subject_alternative_name;
+
 /**
  * Build flag from an algorithm/curve identifier (pk, md, ecp)
  * Since 0 is always XXX_NONE, ignore it.
@@ -347,7 +385,26 @@ int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path );
  */
 int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
 #endif /* MBEDTLS_FS_IO */
-
+/**
+ * \brief          Parses the subject alternative name list of a given certificate;
+ *
+ * \param crt      The X509 certificate to parse.
+ *
+ * \param san      A list holding the parsed certificate.
+ *
+ * \note           Only "dnsName" and "otherName" of type hardware_module_name,
+ *                 as defined in RFC 4180 is supported.
+ *
+ * \note           Any unsupported san type is ignored.
+ *
+ * \note           The function allocates a list of mbedtls_x509_subject_alternative_name
+ *                 and it is the caller's responsibility to free it.
+ *
+ * \return         Zero for success and negative
+ *                 value for any other failure.
+ */
+int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
+                                                 mbedtls_x509_subject_alternative_name **san );
 /**
  * \brief          Returns an informational string about the
  *                 certificate.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 97a06d5f1..f9cbed0a2 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -618,7 +618,8 @@ static int x509_get_ext_key_usage( unsigned char **p,
  *      nameAssigner            [0]     DirectoryString OPTIONAL,
  *      partyName               [1]     DirectoryString }
  *
- * NOTE: we only parse and use dNSName at this point.
+ * NOTE: we only parse and use dNSName at this point,
+ * and otherName of type HwModuleName, as defined in RFC 4108.
  */
 static int x509_get_subject_alt_name( unsigned char **p,
                                       const unsigned char *end,
@@ -657,13 +658,6 @@ static int x509_get_subject_alt_name( unsigned char **p,
                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
         }
 
-        /* Skip everything but DNS name */
-        if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
-        {
-            *p += tag_len;
-            continue;
-        }
-
         /* Allocate and assign next pointer */
         if( cur->buf.p != NULL )
         {
@@ -1435,32 +1429,195 @@ cleanup:
 }
 #endif /* MBEDTLS_FS_IO */
 
+/*
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * HardwareModuleName ::= SEQUENCE {
+ *                           hwType OBJECT IDENTIFIER,
+ *                           hwSerialNum OCTET STRING }
+ *
+ * NOTE: we currently only parse and use otherName of type HwModuleName,
+ * as defined in RFC 4108.
+ */
+static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
+                                mbedtls_x509_san_other_name *other_name )
+{
+    int ret;
+    size_t len;
+    unsigned char *p = subject_alt_name->p;
+    const unsigned char *end = p + subject_alt_name->len;
+    mbedtls_x509_buf cur_oid;
+
+    if( ( subject_alt_name->tag &
+        ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) !=
+        ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) )
+    {
+        /*
+         * The given subject alternative name is not of type "othername".
+         */
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    }
+
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                      MBEDTLS_ASN1_OID ) ) != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    cur_oid.tag = MBEDTLS_ASN1_OID;
+    cur_oid.p = p;
+    cur_oid.len = len;
+
+    /*
+     * Only HwModuleName is currently supported.
+     */
+    if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 )
+    {
+        return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+    }
+
+    if( p + len >= end )
+    {
+        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    p += len;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+       return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
+    other_name->value.hardware_module_name.oid.p = p;
+    other_name->value.hardware_module_name.oid.len = len;
+
+    if( p + len >= end )
+    {
+        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    p += len;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                      MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
+    other_name->value.hardware_module_name.val.p = p;
+    other_name->value.hardware_module_name.val.len = len;
+    other_name->value.hardware_module_name.next = NULL;
+    other_name->value.hardware_module_name.next_merged = 0;
+    p += len;
+    if( p != end )
+    {
+        mbedtls_platform_zeroize( other_name,
+                                  sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    return( 0 );
+}
+
 static int x509_info_subject_alt_name( char **buf, size_t *size,
-                                       const mbedtls_x509_sequence *subject_alt_name )
+                                       const mbedtls_x509_sequence *subject_alt_name,
+                                       const char *prefix )
 {
     size_t i;
+    int ret;
     size_t n = *size;
     char *p = *buf;
     const mbedtls_x509_sequence *cur = subject_alt_name;
-    const char *sep = "";
-    size_t sep_len = 0;
 
     while( cur != NULL )
     {
-        if( cur->buf.len + sep_len >= n )
+        switch( cur->buf.tag &
+                ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) )
         {
-            *p = '\0';
-            return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+            /*
+             * otherName
+             */
+            case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+            {
+                mbedtls_x509_san_other_name other_name;
+
+                ret = x509_get_other_name( &cur->buf, &other_name );
+                if( ret != 0 )
+                {
+                    /*
+                     * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
+                     * then the "otherName" is of an unsupported type. Ignore.
+                     */
+                    if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                        ret = 0;
+                    return( ret );
+                }
+
+                ret = mbedtls_snprintf( p, n, "\n%s    otherName :", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+
+                if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+                             &other_name.value.hardware_module_name.oid ) != 0 )
+                {
+                    ret = mbedtls_snprintf( p, n, "\n%s        hardware module name :", prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+                    ret = mbedtls_snprintf( p, n, "\n%s            hardware type          : ", prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    ret = mbedtls_oid_get_numeric_string( p, n, &other_name.value.hardware_module_name.oid );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    ret = mbedtls_snprintf( p, n, "\n%s            hardware serial number : ", prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    if( other_name.value.hardware_module_name.val.len >= n )
+                    {
+                        *p = '\0';
+                        return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+                    }
+
+                    for( i = 0; i < other_name.value.hardware_module_name.val.len; i++ )
+                    {
+                        *p++ = other_name.value.hardware_module_name.val.p[i];
+                    }
+                    n -= other_name.value.hardware_module_name.val.len;
+
+                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+            }
+            break;
+
+            /*
+             * dNSName
+             */
+            case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+            {
+
+                ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                if( cur->buf.len >= n )
+                {
+                    *p = '\0';
+                    return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+                }
+                n -= cur->buf.len;
+                for( i = 0; i < cur->buf.len; i++ )
+                    *p++ = cur->buf.p[i];
+            }
+            break;
+
+            /*
+             * Type not supported, skip item.
+             */
+            default:
+                break;
         }
 
-        n -= cur->buf.len + sep_len;
-        for( i = 0; i < sep_len; i++ )
-            *p++ = sep[i];
-        for( i = 0; i < cur->buf.len; i++ )
-            *p++ = cur->buf.p[i];
-
-        sep = ", ";
-        sep_len = 2;
 
         cur = cur->next;
     }
@@ -1473,6 +1630,105 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
     return( 0 );
 }
 
+int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
+                                                 mbedtls_x509_subject_alternative_name **san )
+{
+    int ret;
+    const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
+    mbedtls_x509_subject_alternative_name *cur_san = *san, *prev_san = NULL;
+
+    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+    {
+        if( cur_san != NULL )
+        {
+            return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+        }
+
+        while( cur != NULL )
+        {
+            switch( cur->buf.tag &
+                    ( MBEDTLS_ASN1_TAG_CLASS_MASK |
+                      MBEDTLS_ASN1_TAG_VALUE_MASK ) )
+            {
+                /*
+                 * otherName
+                 */
+                case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+                {
+                    mbedtls_x509_san_other_name other_name;
+
+                    ret = x509_get_other_name( &cur->buf, &other_name );
+                    if( ret != 0 )
+                    {
+                        /*
+                         * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
+                         * then the "otherName" is of an unsupported type. Ignore.
+                         */
+                        if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                            ret = 0;
+                        cur = cur->next;
+                        continue;
+                    }
+
+                    cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
+                    if( cur_san == NULL )
+                        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                                MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+                    if( prev_san != NULL )
+                        prev_san->next = cur_san;
+
+                    cur_san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+                    memcpy( &cur_san->san.other_name,
+                            &other_name, sizeof( other_name ) );
+
+                }
+                break;
+
+                /*
+                 * dNSName
+                 */
+                case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+                {
+                    cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
+                    if( cur_san == NULL )
+                        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                                MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+                    if( prev_san != NULL )
+                        prev_san->next = cur_san;
+
+                    memset( cur_san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+                    cur_san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+                    memcpy( &cur_san->san.unstructured_name,
+                            &cur->buf, sizeof( cur->buf ) );
+
+                }
+                break;
+
+                /*
+                 * Type not supported, skip item.
+                 */
+                default:
+                    break;
+            }
+
+            if( *san == NULL )
+                *san = cur_san;
+
+            if( cur_san != NULL )
+            {
+                prev_san = cur_san;
+                cur_san = cur_san->next;
+            }
+
+            cur = cur->next;
+        }/* while( cur != NULL ) */
+    }/* crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME */
+    return( 0 );
+}
+
 #define PRINT_ITEM(i)                           \
     {                                           \
         ret = mbedtls_snprintf( p, n, "%s" i, sep );    \
@@ -1659,11 +1915,12 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
 
     if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
     {
-        ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  : ", prefix );
+        ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  :", prefix );
         MBEDTLS_X509_SAFE_SNPRINTF;
 
         if( ( ret = x509_info_subject_alt_name( &p, &n,
-                                            &crt->subject_alt_names ) ) != 0 )
+                                                &crt->subject_alt_names,
+                                                prefix) ) != 0 )
             return( ret );
     }
 
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 748514db1..6680c808f 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -142,6 +142,12 @@ server5-ss-forgeca.crt: server5.key
 	$(FAKETIME) '2015-09-01 14:08:43' $(OPENSSL) req -x509 -new -subj "/C=UK/O=mbed TLS/CN=mbed TLS Test intermediate CA 3" -set_serial 77 -config $(test_ca_config_file) -extensions noext_ca -days 3650 -sha256 -key $< -out $@
 all_final += server5-ss-forgeca.crt
 
+server5-othername.crt: server5.key
+	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions othername_san -days 3650 -sha256 -key $< -out $@
+
+server5-unsupported_othername.crt: server5.key
+	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS unsupported othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions unsupoported_othername_san -days 3650 -sha256 -key $< -out $@
+
 server10-badsign.crt: server10.crt
 	{ head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@
 all_final += server10-badsign.crt
diff --git a/tests/data_files/multiple_san.crt b/tests/data_files/multiple_san.crt
new file mode 100644
index 000000000..8cdc73061
--- /dev/null
+++ b/tests/data_files/multiple_san.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB2jCCAYCgAwIBAgIBBDAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G
+A1UECgwITWJlZCBUTFMxKDAmBgNVBAMMH01iZWQgVExTIG11bHRpcGxlIG90aGVy
+bmFtZSBTQU4wHhcNMTkwNDIyMTYxMDQ4WhcNMjkwNDE5MTYxMDQ4WjBKMQswCQYD
+VQQGEwJVSzERMA8GA1UECgwITWJlZCBUTFMxKDAmBgNVBAMMH01iZWQgVExTIG11
+bHRpcGxlIG90aGVybmFtZSBTQU4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ3
+zFbZdgkeWnI+x1kt/yBu7nz5BpF00K0UtfdoIllikk7lANgjEf/qL9I0XV0WvYqI
+wmt3DVXNiioO+gHItO3/o1cwVTBTBgNVHREETDBKggtleGFtcGxlLmNvbaAfBggr
+BgEFBQcIBKATMBEGBysGAQQBEQMEBjEyMzQ1NoILZXhhbXBsZS5uZXSCDSouZXhh
+bXBsZS5vcmcwCgYIKoZIzj0EAwIDSAAwRQIhAMZUkp+pcuFQ3WWdgvV4Y+tIXOyS
+L6p0RtEAOi/GgigVAiB50n3rIUKjapYstPp3yOpGZGyRxnc6uRdSiMH5wLA4yw==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server5-othername.crt b/tests/data_files/server5-othername.crt
new file mode 100644
index 000000000..3be1a772c
--- /dev/null
+++ b/tests/data_files/server5-othername.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBnzCCAUWgAwIBAgIBTTAKBggqhkjOPQQDAjBBMQswCQYDVQQGEwJVSzERMA8G
+A1UECgwITWJlZCBUTFMxHzAdBgNVBAMMFk1iZWQgVExTIG90aGVybmFtZSBTQU4w
+HhcNMTkwMzI0MDkwNjAyWhcNMjkwMzIxMDkwNjAyWjBBMQswCQYDVQQGEwJVSzER
+MA8GA1UECgwITWJlZCBUTFMxHzAdBgNVBAMMFk1iZWQgVExTIG90aGVybmFtZSBT
+QU4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ3zFbZdgkeWnI+x1kt/yBu7nz5
+BpF00K0UtfdoIllikk7lANgjEf/qL9I0XV0WvYqIwmt3DVXNiioO+gHItO3/oy4w
+LDAqBgNVHREEIzAhoB8GCCsGAQUFBwgEoBMwEQYHKwYBBAERAwQGMTIzNDU2MAoG
+CCqGSM49BAMCA0gAMEUCIQCijdm1AfArx2p4cLCVciHCTE8UXRiTm8f85k4aNzzf
+sgIgCdmLyfZB9jsSPH3A3O1GATAR3O9OTtEDC+YSc+lvxSw=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server5-unsupported_othername.crt b/tests/data_files/server5-unsupported_othername.crt
new file mode 100644
index 000000000..b46fc2d96
--- /dev/null
+++ b/tests/data_files/server5-unsupported_othername.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVygAwIBAgIBTTAKBggqhkjOPQQDAjBNMQswCQYDVQQGEwJVSzERMA8G
+A1UECgwITWJlZCBUTFMxKzApBgNVBAMMIk1iZWQgVExTIHVuc3VwcG9ydGVkIG90
+aGVybmFtZSBTQU4wHhcNMTkwNTAxMDkxMDM1WhcNMjkwNDI4MDkxMDM1WjBNMQsw
+CQYDVQQGEwJVSzERMA8GA1UECgwITWJlZCBUTFMxKzApBgNVBAMMIk1iZWQgVExT
+IHVuc3VwcG9ydGVkIG90aGVybmFtZSBTQU4wWTATBgcqhkjOPQIBBggqhkjOPQMB
+BwNCAAQ3zFbZdgkeWnI+x1kt/yBu7nz5BpF00K0UtfdoIllikk7lANgjEf/qL9I0
+XV0WvYqIwmt3DVXNiioO+gHItO3/oy0wKzApBgNVHREEIjAgoB4GAyoDBKAXDBVz
+b21lIG90aGVyIGlkZW50aWZpZXIwCgYIKoZIzj0EAwIDSAAwRQIhANkj6n9qHYVi
+FLfb0IRZpIsvvuNCjSgT8yBLVjJYQj3nAiBffQKZ7y/F6rfon6L1GZU0BBja8BLX
+rXp8WpY7Bc8myQ==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca.opensslconf b/tests/data_files/test-ca.opensslconf
index f66b39e3c..d345fe99e 100644
--- a/tests/data_files/test-ca.opensslconf
+++ b/tests/data_files/test-ca.opensslconf
@@ -12,6 +12,25 @@ subjectKeyIdentifier=hash
 authorityKeyIdentifier=keyid:always,issuer:always
 basicConstraints = CA:true
 
+[othername_san]
+subjectAltName=otherName:1.3.6.1.5.5.7.8.4;SEQ:hw_module_name
+
+[unsupoported_othername_san]
+subjectAltName=otherName:1.2.3.4;UTF8:some other identifier
+
+[alt_names]
+DNS.1=example.com
+otherName.1=1.3.6.1.5.5.7.8.4;SEQ:hw_module_name
+DNS.2=example.net
+DNS.3=*.example.org
+
+[multiple_san]
+subjectAltName=@alt_names
+
+[hw_module_name]
+hwtype = OID:1.3.6.1.4.1.17.3
+hwserial = OCT:123456
+
 [noext_ca]
 basicConstraints = CA:true
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index edd3a6fc5..f53ea8232 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -94,6 +94,10 @@ X509 Certificate information EC, SHA512 Digest
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C
 x509_cert_info:"data_files/server5-sha512.crt":"cert. version     \: 3\nserial number     \: 15\nissuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name      \: C=NL, O=PolarSSL, CN=localhost\nissued  on        \: 2013-09-24 16\:21\:27\nexpires on        \: 2023-09-22 16\:21\:27\nsigned using      \: ECDSA with SHA512\nEC key size       \: 256 bits\nbasic constraints \: CA=false\n"
 
+X509 Certificate information EC, SHA256 Digest, hardware module name SAN
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/server5-othername.crt":"cert. version     \: 3\nserial number     \: 4D\nissuer name       \: C=UK, O=Mbed TLS, CN=Mbed TLS othername SAN\nsubject name      \: C=UK, O=Mbed TLS, CN=Mbed TLS othername SAN\nissued  on        \: 2019-03-24 09\:06\:02\nexpires on        \: 2029-03-21 09\:06\:02\nsigned using      \: ECDSA with SHA256\nEC key size       \: 256 bits\nsubject alt name  \:\n    otherName \:\n        hardware module name \:\n            hardware type          \: 1.3.6.1.4.1.17.3\n            hardware serial number \: 123456\n"
+
 X509 Certificate information, NS Cert Type
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
 x509_cert_info:"data_files/server1.cert_type.crt":"cert. version     \: 3\nserial number     \: 01\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nissued  on        \: 2011-02-12 14\:44\:06\nexpires on        \: 2021-02-12 14\:44\:06\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\ncert. type        \: SSL Server\n"
@@ -108,11 +112,15 @@ x509_cert_info:"data_files/keyUsage.decipherOnly.crt":"cert. version     \: 3\ns
 
 X509 Certificate information, Subject Alt Name
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/cert_example_multi.crt":"cert. version     \: 3\nserial number     \: 11\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=www.example.com\nissued  on        \: 2012-05-10 13\:23\:41\nexpires on        \: 2022-05-11 13\:23\:41\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \: example.com, example.net, *.example.org\n"
+x509_cert_info:"data_files/cert_example_multi.crt":"cert. version     \: 3\nserial number     \: 11\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=www.example.com\nissued  on        \: 2012-05-10 13\:23\:41\nexpires on        \: 2022-05-11 13\:23\:41\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    dNSName \: example.com\n    dNSName \: example.net\n    dNSName \: *.example.org\n"
+
+X509 Certificate information, Multiple different Subject Alt Name
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/multiple_san.crt":"cert. version     \: 3\nserial number     \: 04\nissuer name       \: C=UK, O=Mbed TLS, CN=Mbed TLS multiple othername SAN\nsubject name      \: C=UK, O=Mbed TLS, CN=Mbed TLS multiple othername SAN\nissued  on        \: 2019-04-22 16\:10\:48\nexpires on        \: 2029-04-19 16\:10\:48\nsigned using      \: ECDSA with SHA256\nEC key size       \: 256 bits\nsubject alt name  \:\n    dNSName \: example.com\n    otherName \:\n        hardware module name \:\n            hardware type          \: 1.3.6.1.4.1.17.3\n            hardware serial number \: 123456\n    dNSName \: example.net\n    dNSName \: *.example.org\n"
 
 X509 Certificate information, Subject Alt Name + Key Usage
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version     \: 3\nserial number     \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name       \: C=NL\nsubject name      \: C=NL\nissued  on        \: 2014-01-22 10\:04\:33\nexpires on        \: 2024-01-22 10\:04\:33\nsigned using      \: RSA with SHA1\nRSA key size      \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name  \: www.shotokan-braunschweig.de, www.massimo-abate.eu\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
+x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version     \: 3\nserial number     \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name       \: C=NL\nsubject name      \: C=NL\nissued  on        \: 2014-01-22 10\:04\:33\nexpires on        \: 2024-01-22 10\:04\:33\nsigned using      \: RSA with SHA1\nRSA key size      \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    dNSName \: www.shotokan-braunschweig.de\n    dNSName \: www.massimo-abate.eu\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
 
 X509 Certificate information, Key Usage + Extended Key Usage
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
@@ -128,11 +136,31 @@ x509_cert_info:"data_files/server3.crt":"cert. version     \: 3\nserial number
 
 X509 Certificate information Bitstring in subject name
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/bitstring-in-dn.pem":"cert. version     \: 3\nserial number     \: 02\nissuer name       \: CN=Test CA 01, ST=Ecnivorp, C=XX, emailAddress=tca@example.com, O=Test CA Authority\nsubject name      \: C=XX, O=tca, ST=Ecnivorp, OU=TCA, CN=Client, emailAddress=client@example.com, serialNumber=7101012255, uniqueIdentifier=?7101012255\nissued  on        \: 2015-03-11 12\:06\:51\nexpires on        \: 2025-03-08 12\:06\:51\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \: \next key usage     \: TLS Web Client Authentication\n"
+x509_cert_info:"data_files/bitstring-in-dn.pem":"cert. version     \: 3\nserial number     \: 02\nissuer name       \: CN=Test CA 01, ST=Ecnivorp, C=XX, emailAddress=tca@example.com, O=Test CA Authority\nsubject name      \: C=XX, O=tca, ST=Ecnivorp, OU=TCA, CN=Client, emailAddress=client@example.com, serialNumber=7101012255, uniqueIdentifier=?7101012255\nissued  on        \: 2015-03-11 12\:06\:51\nexpires on        \: 2025-03-08 12\:06\:51\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \:\next key usage     \: TLS Web Client Authentication\n"
 
 X509 certificate v1 with extension
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/cert_v1_with_ext.crt":"cert. version     \: 1\nserial number     \: BD\:ED\:44\:C7\:D2\:3E\:C2\:A4\nissuer name       \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nsubject name      \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nissued  on        \: 2013-07-04 16\:17\:02\nexpires on        \: 2014-07-04 16\:17\:02\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nsubject alt name  \: identity-check.org, www.identity-check.org\n"
+x509_cert_info:"data_files/cert_v1_with_ext.crt":"cert. version     \: 1\nserial number     \: BD\:ED\:44\:C7\:D2\:3E\:C2\:A4\nissuer name       \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nsubject name      \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nissued  on        \: 2013-07-04 16\:17\:02\nexpires on        \: 2014-07-04 16\:17\:02\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nsubject alt name  \:\n    dNSName \: identity-check.org\n    dNSName \: www.identity-check.org\n"
+
+X509 SAN parsing otherName
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_parse_san:"data_files/server5-othername.crt":"type \: 0\notherName \: hardware module name \: hardware type \: 1.3.6.1.4.1.17.3, hardware serial number \: 123456\n"
+
+X509 SAN parsing dNSName
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+x509_parse_san:"data_files/cert_example_multi.crt":"type \: 2\ndNSName \: example.com\ntype \: 2\ndNSName \: example.net\ntype \: 2\ndNSName \: *.example.org\n"
+
+X509 SAN parsing  Multiple different types
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_parse_san:"data_files/multiple_san.crt":"type \: 2\ndNSName \: example.com\ntype \: 0\notherName \: hardware module name \: hardware type \: 1.3.6.1.4.1.17.3, hardware serial number \: 123456\ntype \: 2\ndNSName \: example.net\ntype \: 2\ndNSName \: *.example.org\n"
+
+X509 SAN parsing, no subject alt name
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
+x509_parse_san:"data_files/server4.crt":""
+
+X509 SAN parsing, unsupported otherName name
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_parse_san:"data_files/server5-unsupported_othername.crt":""
 
 X509 CRL information #1
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index b11ab849a..beec52cc3 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -219,6 +219,79 @@ int verify_print( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint
 
     return( 0 );
 }
+
+int verify_parse_san( mbedtls_x509_subject_alternative_name *san,
+                      char **buf, size_t *size )
+{
+    int ret;
+    size_t i;
+    char *p = *buf;
+    size_t n = *size;
+
+    ret = mbedtls_snprintf( p, n, "type : %u", san->type );
+    MBEDTLS_X509_SAFE_SNPRINTF;
+
+    switch( san->type )
+    {
+       case( MBEDTLS_X509_SAN_OTHER_NAME ):
+           ret = mbedtls_snprintf( p, n, "\notherName :");
+           MBEDTLS_X509_SAFE_SNPRINTF;
+
+           if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+                    &san->san.other_name.value.hardware_module_name.oid ) != 0 )
+           {
+               ret = mbedtls_snprintf( p, n, " hardware module name :" );
+               MBEDTLS_X509_SAFE_SNPRINTF;
+               ret = mbedtls_snprintf( p, n, " hardware type : " );
+               MBEDTLS_X509_SAFE_SNPRINTF;
+
+               ret = mbedtls_oid_get_numeric_string( p, n,
+                          &san->san.other_name.value.hardware_module_name.oid );
+               MBEDTLS_X509_SAFE_SNPRINTF;
+
+               ret = mbedtls_snprintf( p, n, ", hardware serial number : " );
+               MBEDTLS_X509_SAFE_SNPRINTF;
+
+               if( san->san.other_name.value.hardware_module_name.val.len >= n )
+               {
+                   *p = '\0';
+                   return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+               }
+
+               for( i=0; i < san->san.other_name.value.hardware_module_name.val.len; i++ )
+               {
+                   *p++ = san->san.other_name.value.hardware_module_name.val.p[i];
+               }
+               n -= san->san.other_name.value.hardware_module_name.val.len;
+            }
+        break;/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+        case(  MBEDTLS_X509_SAN_DNS_NAME ):
+            ret = mbedtls_snprintf( p, n, "\ndNSName : " );
+            MBEDTLS_X509_SAFE_SNPRINTF;
+            if( san->san.unstructured_name.len >= n )
+            {
+                *p = '\0';
+                return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+            }
+            n -= san->san.unstructured_name.len;
+            for( i = 0; i < san->san.unstructured_name.len; i++ )
+                *p++ = san->san.unstructured_name.p[i];
+        break;/* MBEDTLS_X509_SAN_DNS_NAME */
+
+        default:
+        /*
+         * Should not happen.
+         */
+        return( -1 );
+    }
+    ret = mbedtls_snprintf( p, n, "\n" );
+    MBEDTLS_X509_SAFE_SNPRINTF;
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 /* END_HEADER */
 
@@ -227,6 +300,41 @@ int verify_print( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
+void x509_parse_san( char * crt_file, char * result_str )
+{
+    mbedtls_x509_crt   crt;
+    mbedtls_x509_subject_alternative_name *cur, *next, *san = NULL;
+    char buf[2000];
+    char *p = buf;
+    size_t n = sizeof( buf );
+
+    mbedtls_x509_crt_init( &crt );
+    memset( buf, 0, 2000 );
+
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_parse_subject_alternative_name( &crt, &san ) == 0 );
+    cur = san;
+    while( cur != NULL )
+    {
+        TEST_ASSERT( verify_parse_san( cur, &p, &n ) == 0 );
+        cur = cur->next;
+    }
+
+    TEST_ASSERT( strcmp( buf, result_str ) == 0 );
+
+exit:
+
+    for( cur = san; cur != NULL; cur = next )
+    {
+        next = cur->next;
+        mbedtls_free( cur );
+    }
+
+    mbedtls_x509_crt_free( &crt );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
 void x509_cert_info( char * crt_file, char * result_str )
 {

From 74d9acc144a398c6df238abd5ba154a9ae798a05 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Thu, 21 Mar 2019 14:00:03 +0200
Subject: [PATCH 02/27] Add support for certificate policies extension

Add support for certificate policies, as defined in rfc 5280.
Currently support only `anyPolicy` policy.
---
 include/mbedtls/x509_crt.h                    |   2 +
 library/x509_crt.c                            | 189 ++++++++++++++++++
 tests/data_files/Makefile                     |  36 ++++
 tests/data_files/test-ca-any_policy.crt       |  19 ++
 tests/data_files/test-ca-any_policy_ec.crt    |  12 ++
 .../test-ca-any_policy_with_qualifier.crt     |  20 ++
 .../test-ca-any_policy_with_qualifier_ec.crt  |  13 ++
 tests/data_files/test-ca-multi_policy.crt     |  19 ++
 tests/data_files/test-ca-multi_policy_ec.crt  |  12 ++
 .../data_files/test-ca-unsupported_policy.crt |  19 ++
 .../test-ca-unsupported_policy_ec.crt         |  12 ++
 tests/data_files/test-ca.opensslconf          |  20 ++
 tests/suites/test_suite_x509parse.data        |  32 +++
 13 files changed, 405 insertions(+)
 create mode 100644 tests/data_files/test-ca-any_policy.crt
 create mode 100644 tests/data_files/test-ca-any_policy_ec.crt
 create mode 100644 tests/data_files/test-ca-any_policy_with_qualifier.crt
 create mode 100644 tests/data_files/test-ca-any_policy_with_qualifier_ec.crt
 create mode 100644 tests/data_files/test-ca-multi_policy.crt
 create mode 100644 tests/data_files/test-ca-multi_policy_ec.crt
 create mode 100644 tests/data_files/test-ca-unsupported_policy.crt
 create mode 100644 tests/data_files/test-ca-unsupported_policy_ec.crt

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 4a796173f..acaafbe9f 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -78,6 +78,8 @@ typedef struct mbedtls_x509_crt
     mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
     mbedtls_x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName and OtherName supported). */
 
+    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate4 policies (Only anyPolicy supported). */
+
     int ext_types;              /**< Bit string containing detected and parsed extensions */
     int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
     int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index f9cbed0a2..f17c8b2ec 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -690,6 +690,139 @@ static int x509_get_subject_alt_name( unsigned char **p,
     return( 0 );
 }
 
+/*
+ * id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }
+ *
+ * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
+ *
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ *
+ * PolicyInformation ::= SEQUENCE {
+ *     policyIdentifier   CertPolicyId,
+ *     policyQualifiers   SEQUENCE SIZE (1..MAX) OF
+ *                             PolicyQualifierInfo OPTIONAL }
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ *      policyQualifierId  PolicyQualifierId,
+ *      qualifier          ANY DEFINED BY policyQualifierId }
+ *
+ * -- policyQualifierIds for Internet policy qualifiers
+ *
+ * id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
+ * id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+ * id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+ *
+ * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+ *
+ * Qualifier ::= CHOICE {
+ *      cPSuri           CPSuri,
+ *      userNotice       UserNotice }
+ *
+ * CPSuri ::= IA5String
+ *
+ * UserNotice ::= SEQUENCE {
+ *      noticeRef        NoticeReference OPTIONAL,
+ *      explicitText     DisplayText OPTIONAL }
+ *
+ * NoticeReference ::= SEQUENCE {
+ *      organization     DisplayText,
+ *      noticeNumbers    SEQUENCE OF INTEGER }
+ *
+ * DisplayText ::= CHOICE {
+ *      ia5String        IA5String      (SIZE (1..200)),
+ *      visibleString    VisibleString  (SIZE (1..200)),
+ *      bmpString        BMPString      (SIZE (1..200)),
+ *      utf8String       UTF8String     (SIZE (1..200)) }
+ *
+ * NOTE: we only parse and use anyPolicy without qualifiers at this point
+ * as defined in RFC 5280.
+ */
+static int x509_get_certificate_policies( unsigned char **p,
+                                          const unsigned char *end,
+                                          mbedtls_x509_sequence *certificate_policies )
+{
+    int ret;
+    size_t len;
+    mbedtls_asn1_buf *buf;
+    mbedtls_asn1_sequence *cur = certificate_policies;
+
+    /* Get main sequence tag */
+    ret = mbedtls_asn1_get_tag( p, end, &len,
+                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+    if( *p + len != end )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    /*
+     * Cannot be an empty sequence.
+     */
+    if( len == 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        mbedtls_x509_buf policy_oid;
+        const unsigned char *policy_end;
+
+        /*
+         * Get the policy sequence
+         */
+        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        policy_end = *p + len;
+
+        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+                                          MBEDTLS_ASN1_OID ) ) != 0 )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+        policy_oid.tag = MBEDTLS_ASN1_OID;
+        policy_oid.len = len;
+        policy_oid.p = *p;
+
+        /* Allocate and assign next pointer */
+        if( cur->buf.p != NULL )
+        {
+            if( cur->next != NULL )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
+
+            cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+            if( cur->next == NULL )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                        MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+            cur = cur->next;
+        }
+
+        buf = &( cur->buf );
+        buf->tag = policy_oid.tag;
+        buf->p = policy_oid.p;
+        buf->len = policy_oid.len;
+        /*
+         * Skip the optional policy qualifiers,
+         * and set the pointer to the end of the policy.
+         */
+        *p = (unsigned char *)policy_end;
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
 /*
  * X.509 v3 extensions
  *
@@ -817,6 +950,13 @@ static int x509_get_crt_ext( unsigned char **p,
                 return( ret );
             break;
 
+        case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
+            /* Parse certificate policies type */
+            if( ( ret = x509_get_certificate_policies( p, end_ext_octet,
+                    &crt->certificate_policies ) ) != 0 )
+                return( ret );
+            break;
+
         default:
             /*
              * If this is a non-critical extension, which the oid layer
@@ -1820,6 +1960,35 @@ static int x509_info_ext_key_usage( char **buf, size_t *size,
     return( 0 );
 }
 
+static int x509_info_cert_policies( char **buf, size_t *size,
+                                    const mbedtls_x509_sequence *certificate_policies )
+{
+    int ret;
+    const char *desc;
+    size_t n = *size;
+    char *p = *buf;
+    const mbedtls_x509_sequence *cur = certificate_policies;
+    const char *sep = "";
+
+    while( cur != NULL )
+    {
+        if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 )
+            desc = "???";
+
+        ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        sep = ", ";
+
+        cur = cur->next;
+    }
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
 /*
  * Return an informational string about the certificate.
  */
@@ -1952,6 +2121,16 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
             return( ret );
     }
 
+    if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES )
+    {
+        ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix );
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if( ( ret = x509_info_cert_policies( &p, &n,
+                                             &crt->certificate_policies ) ) != 0 )
+            return( ret );
+    }
+
     ret = mbedtls_snprintf( p, n, "\n" );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
@@ -3078,6 +3257,16 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
             mbedtls_free( seq_prv );
         }
 
+        seq_cur = cert_cur->certificate_policies.next;
+        while( seq_cur != NULL )
+        {
+            seq_prv = seq_cur;
+            seq_cur = seq_cur->next;
+            mbedtls_platform_zeroize( seq_prv,
+                                      sizeof( mbedtls_x509_sequence ) );
+            mbedtls_free( seq_prv );
+        }
+
         if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
         {
             mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 6680c808f..d139bfa06 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -77,6 +77,42 @@ all_final += test-ca-good-alt.crt
 test_ca_crt_file_ec = test-ca2.crt
 test_ca_key_file_ec = test-ca2.key
 
+test-ca-any_policy.crt: $(test_ca_key_file_rsa) test-ca.req.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_any_policy_ca -key $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 0 -days 3653 -sha256 -in test-ca.req.sha256 -out $@
+all_final += test-ca-any_policy.crt
+
+test-ca-any_policy_ec.crt: $(test_ca_key_file_ec) test-ca.req_ec.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_any_policy_ca -key $(test_ca_key_file_ec) -set_serial 0 -days 3653 -sha256 -in test-ca.req_ec.sha256 -out $@
+all_final += test-ca-any_policy_ec.crt
+
+test-ca-any_policy_with_qualifier.crt: $(test_ca_key_file_rsa) test-ca.req.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_any_policy_qualifier_ca -key $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 0 -days 3653 -sha256 -in test-ca.req.sha256 -out $@
+all_final += test-ca-any_policy_with_qualifier.crt
+
+test-ca-any_policy_with_qualifier_ec.crt: $(test_ca_key_file_ec) test-ca.req_ec.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_any_policy_qualifier_ca -key $(test_ca_key_file_ec) -set_serial 0 -days 3653 -sha256 -in test-ca.req_ec.sha256 -out $@
+all_final += test-ca-any_policy_with_qualifier_ec.crt
+
+test-ca-multi_policy.crt: $(test_ca_key_file_rsa) test-ca.req.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_multi_policy_ca -key $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 0 -days 3653 -sha256 -in test-ca.req.sha256 -out $@
+all_final += test-ca-multi_policy.crt
+
+test-ca-multi_policy_ec.crt: $(test_ca_key_file_ec) test-ca.req_ec.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_multi_policy_ca -key $(test_ca_key_file_ec) -set_serial 0 -days 3653 -sha256 -in test-ca.req_ec.sha256 -out $@
+all_final += test-ca-multi_policy_ec.crt
+
+test-ca-unsupported_policy.crt: $(test_ca_key_file_rsa) test-ca.req.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_unsupported_policy_ca -key $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 0 -days 3653 -sha256 -in test-ca.req.sha256 -out $@
+all_final += test-ca-unsupported_policy.crt
+
+test-ca-unsupported_policy_ec.crt: $(test_ca_key_file_ec) test-ca.req_ec.sha256
+	$(OPENSSL) req -x509 -config $(test_ca_config_file) -extensions v3_unsupported_policy_ca -key $(test_ca_key_file_ec) -set_serial 0 -days 3653 -sha256 -in test-ca.req_ec.sha256 -out $@
+all_final += test-ca-unsupported_policy_ec.crt
+
+test-ca.req_ec.sha256: $(test_ca_key_file_ec)
+	$(MBEDTLS_CERT_REQ) output_file=$@ filename=$(test_ca_key_file_ec) subject_name="C=NL, O=PolarSSL, CN=Polarssl Test EC CA" md=SHA256
+all_intermediate += test-ca.req_ec.sha256
+
 test_ca_crt_cat12 = test-ca_cat12.crt
 $(test_ca_crt_cat12): $(test_ca_crt) $(test_ca_crt_file_ec)
 	cat $(test_ca_crt) $(test_ca_crt_file_ec) > $@
diff --git a/tests/data_files/test-ca-any_policy.crt b/tests/data_files/test-ca-any_policy.crt
new file mode 100644
index 000000000..af87439cf
--- /dev/null
+++ b/tests/data_files/test-ca-any_policy.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFDCCAfygAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMzIxMTY0MDU5WhcNMjkwMzIxMTY0MDU5WjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+IzAhMAwGA1UdEwQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEB
+CwUAA4IBAQCHadUDZiIjJhcrG+rYrpOVgMu548rc5kHLC7zVSVfszfdOJq/TdXQT
+Lbn9i+AAVRYJU2kHWKD2fvgOYIIBeEGFJKohlKZ82irWxt0Ltph31cuygLcpqNq9
+KRQ/dh3S0w9vn1A1ubYGKTzTnZGELTVzMlXZGTRbAOylMu4eWac6LHymE2EBqmOq
+fPCuWdFB62ewQWRa+dRO92Aphh870u43/iLbw7hs4s8hokZP7Ewg6AHb4qjVePdF
+jjxAO6x5VCj/WQRnw7muAy0P3l5AhYXAIUdnkdYca5Ja6LfdEJiVeTdE3IU6UJg+
+gAu9swDhUlEuIlCrOdC3tOPDslsOIgTV
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-any_policy_ec.crt b/tests/data_files/test-ca-any_policy_ec.crt
new file mode 100644
index 000000000..821a92c45
--- /dev/null
+++ b/tests/data_files/test-ca-any_policy_ec.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBzDCCAVGgAwIBAgIBADAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN
+MTkwMzI1MDkwMjQ1WhcNMjkwMzI1MDkwMjQ1WjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATD2is0QTdYL4dW/vyJuilDS07gbsMOV1MzOVjU
+UrSRlTkLI99fFyRiSPwalSnOLC2HwohSgK/Waqsh3bjTHG5YuMrosmmO80GtKcO0
+X3WnR2/VGSlVaZpTOyC0ZhZgMx6jIzAhMAwGA1UdEwQFMAMBAf8wEQYDVR0gBAow
+CDAGBgRVHSAAMAoGCCqGSM49BAMCA2kAMGYCMQDWHgmWMckbGLd7XREnJVAv+XRp
+XANOCbWLDu+Fik6c28S+qR6zGEKKGiPHYeDpjRACMQDnYcFBwlfuAB6td3fteG0P
+AWngOaGHmUFEA6h24b5Z6/GSFD9FK9rVRdxQc4Olz7U=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-any_policy_with_qualifier.crt b/tests/data_files/test-ca-any_policy_with_qualifier.crt
new file mode 100644
index 000000000..a052bc626
--- /dev/null
+++ b/tests/data_files/test-ca-any_policy_with_qualifier.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwNDI4MTMxNDMxWhcNMjkwNDI4MTMxNDMxWjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+QTA/MAwGA1UdEwQFMAMBAf8wLwYDVR0gBCgwJjAkBgRVHSAAMBwwGgYIKwYBBQUH
+AgEWDkNQUyB1cmkgc3RyaW5nMA0GCSqGSIb3DQEBCwUAA4IBAQBo3CLwvTakVDWs
+XUZz3ehGgk39KzmYOb3m9bBfMpOplDfE8Zaj8TDZZsxXpNCXT85GgbrAdr6pONQJ
+Mqd3TzTXCs6tmmIOVDToOj6nKtm2nNSf+1TUuLRgeavgCoicoQZOtW5tAehw/RTE
+4VQXSm+ZWotYwK1jvlHS0LaehUy53GsNxWBJHCc3exD+iyutXTZ89jczIKuWpEIN
+pTdI/EYVD2r6r/IITRnJpGjNXOhGB4zvgFlwv88GeF5lG6Si9YD+swO8JuJP35q6
+7cPA/vtrjoiyM3kXmmN1LZGIfEMKNwEcyVhvl+d6sReomI3HAKOj9IIG7umFKi6t
+axMwzK3Y
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-any_policy_with_qualifier_ec.crt b/tests/data_files/test-ca-any_policy_with_qualifier_ec.crt
new file mode 100644
index 000000000..5e1491da7
--- /dev/null
+++ b/tests/data_files/test-ca-any_policy_with_qualifier_ec.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB6DCCAW+gAwIBAgIBADAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN
+MTkwNDI4MTAxNjA1WhcNMjkwNDI4MTAxNjA1WjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATD2is0QTdYL4dW/vyJuilDS07gbsMOV1MzOVjU
+UrSRlTkLI99fFyRiSPwalSnOLC2HwohSgK/Waqsh3bjTHG5YuMrosmmO80GtKcO0
+X3WnR2/VGSlVaZpTOyC0ZhZgMx6jQTA/MAwGA1UdEwQFMAMBAf8wLwYDVR0gBCgw
+JjAkBgRVHSAAMBwwGgYIKwYBBQUHAgEWDkNQUyB1cmkgc3RyaW5nMAoGCCqGSM49
+BAMCA2cAMGQCMDvi5bBVplU3Gct+iYRmRW9ewty5b+1OX0ggzA+ExXpL1Obo6A16
+a2h1kb7Oy4+BSAIwXZHYb6OEWkOngISfwSZxDiiNXOTwvCu2/oFGC8xTENn0B88m
+2WwPzh4jnvXhNh0w
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-multi_policy.crt b/tests/data_files/test-ca-multi_policy.crt
new file mode 100644
index 000000000..168e99f2e
--- /dev/null
+++ b/tests/data_files/test-ca-multi_policy.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDGzCCAgOgAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwNDI4MTI1OTE5WhcNMjkwNDI4MTI1OTE5WjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+KjAoMAwGA1UdEwQFMAMBAf8wGAYDVR0gBBEwDzAFBgMqAwQwBgYEVR0gADANBgkq
+hkiG9w0BAQsFAAOCAQEAPwOUmjnrcBA7dt5drCakEz9HOpj8gZQd1fyVGv221LCL
+h2W1Ngd2WlcADhPQcTdqNx4Dk+KPiBjPEooE9M7d3K33Qn/dVkmOYiW6E/4wU2tM
+cqFj7rg8Now4lBaEqEmBP+cpv+mYqavPcKy3tz4wn1SnA3MpT1hEazhNe4yInNAY
+4YqRBbWuBGkePjbce6Lf+rTfaA7kJnyuC9SHguQRmWtV3xzNzLUFn+V/jYSqYvYU
+2MjDFgCYCmW0xl5Wo8wMWWAvMbO2mRJ37OLUkSOkxgeEL6OihY1GPkbfxC2qV6mR
+4VjmfclwXumiDAvVLhW8hWjCxg8gc69G7kCkVbljLA==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-multi_policy_ec.crt b/tests/data_files/test-ca-multi_policy_ec.crt
new file mode 100644
index 000000000..70ea2ebbd
--- /dev/null
+++ b/tests/data_files/test-ca-multi_policy_ec.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB0zCCAVigAwIBAgIBADAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN
+MTkwNDI4MTI1OTUxWhcNMjkwNDI4MTI1OTUxWjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATD2is0QTdYL4dW/vyJuilDS07gbsMOV1MzOVjU
+UrSRlTkLI99fFyRiSPwalSnOLC2HwohSgK/Waqsh3bjTHG5YuMrosmmO80GtKcO0
+X3WnR2/VGSlVaZpTOyC0ZhZgMx6jKjAoMAwGA1UdEwQFMAMBAf8wGAYDVR0gBBEw
+DzAFBgMqAwQwBgYEVR0gADAKBggqhkjOPQQDAgNpADBmAjEAqyz2v+6i3xXF4qlr
+o89qxwlpIn9sR0xU+qo9tgcM6Fa7IDdAU1lhweN8MpkJTtrGAjEAmgNI/08M8n6/
+sMM0Xutt5u9EUHb+4y0uyOfYMcEPr+pCUM4GPxBP6RdqI8Wu9OQf
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-unsupported_policy.crt b/tests/data_files/test-ca-unsupported_policy.crt
new file mode 100644
index 000000000..bf47d9538
--- /dev/null
+++ b/tests/data_files/test-ca-unsupported_policy.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAfugAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwNDI4MTMwMDEzWhcNMjkwNDI4MTMwMDEzWjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+IjAgMAwGA1UdEwQFMAMBAf8wEAYDVR0gBAkwBzAFBgMqAwQwDQYJKoZIhvcNAQEL
+BQADggEBAGvARX2orRXDmc2a7nSrbRFkdw/7qbL8Y+wLeM94SsZVgzGcxzRx1KvG
+2H5nBvPKgAzBqWVPU7eDPjrETIfsCxSu+yklBIg5QYRuOcprLtQPkFVfl+WLd31F
+lS1uMgZkahIr57aHoJLYPrEjW4CBHoliT8xfrvVZi4+ym7i/vFqXL7IJ+PIklNF8
+2/b4SAB9hRI5oPw1TV9Q0v2PqMXL/0cp/9Roe+H28Tcrody6jTtEdsU2wbaxhxMd
+YK4Ak1FkhKItumINbtAUnHgBVwO2IivGZgsYulC/9y1uh5NU1HxMzqh04UEMgre+
+9SeEjhwFkq16Njc5Cdt/7iFLeiaHcNU=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-unsupported_policy_ec.crt b/tests/data_files/test-ca-unsupported_policy_ec.crt
new file mode 100644
index 000000000..161e83cc1
--- /dev/null
+++ b/tests/data_files/test-ca-unsupported_policy_ec.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIByjCCAVCgAwIBAgIBADAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN
+MTkwNDI4MTMwMDE5WhcNMjkwNDI4MTMwMDE5WjA+MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATD2is0QTdYL4dW/vyJuilDS07gbsMOV1MzOVjU
+UrSRlTkLI99fFyRiSPwalSnOLC2HwohSgK/Waqsh3bjTHG5YuMrosmmO80GtKcO0
+X3WnR2/VGSlVaZpTOyC0ZhZgMx6jIjAgMAwGA1UdEwQFMAMBAf8wEAYDVR0gBAkw
+BzAFBgMqAwQwCgYIKoZIzj0EAwIDaAAwZQIwKUY3aTL6UR2H1Q1OzIJw7vxUso4P
+2PksCWb62kQeAnhYK85t1VGQiA49iHCXVKuXAjEAq+1qvlmwHX1E99ha/rvxcAYp
+UmxXLmSb53RT0NvhEKnUVGGUp2pBNAVVJOH+G0NI
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca.opensslconf b/tests/data_files/test-ca.opensslconf
index d345fe99e..5f71532ce 100644
--- a/tests/data_files/test-ca.opensslconf
+++ b/tests/data_files/test-ca.opensslconf
@@ -31,6 +31,26 @@ subjectAltName=@alt_names
 hwtype = OID:1.3.6.1.4.1.17.3
 hwserial = OCT:123456
 
+[v3_any_policy_ca]
+basicConstraints = CA:true
+certificatePolicies = 2.5.29.32.0
+
+[v3_any_policy_qualifier_ca]
+basicConstraints = CA:true
+certificatePolicies = @policy_info
+
+[v3_multi_policy_ca]
+basicConstraints = CA:true
+certificatePolicies = 1.2.3.4,2.5.29.32.0
+
+[v3_unsupported_policy_ca]
+basicConstraints = CA:true
+certificatePolicies = 1.2.3.4
+
+[policy_info]
+policyIdentifier = 2.5.29.32.0
+CPS.1 ="CPS uri string"
+
 [noext_ca]
 basicConstraints = CA:true
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index f53ea8232..6fcf80564 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -122,6 +122,38 @@ X509 Certificate information, Subject Alt Name + Key Usage
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
 x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version     \: 3\nserial number     \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name       \: C=NL\nsubject name      \: C=NL\nissued  on        \: 2014-01-22 10\:04\:33\nexpires on        \: 2024-01-22 10\:04\:33\nsigned using      \: RSA with SHA1\nRSA key size      \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    dNSName \: www.shotokan-braunschweig.de\n    dNSName \: www.massimo-abate.eu\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
 
+X509 Certificate information, RSA Certificate Policy any
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-any_policy.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nissued  on        \: 2019-03-21 16\:40\:59\nexpires on        \: 2029-03-21 16\:40\:59\nsigned using      \: RSA with SHA-256\nRSA key size      \: 2048 bits\nbasic constraints \: CA=true\ncertificate policies \: Any Policy\n"
+
+X509 Certificate information, ECDSA Certificate Policy any
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-any_policy_ec.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name      \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nissued  on        \: 2019-03-25 09\:02\:45\nexpires on        \: 2029-03-25 09\:02\:45\nsigned using      \: ECDSA with SHA256\nEC key size       \: 384 bits\nbasic constraints \: CA=true\ncertificate policies \: Any Policy\n"
+
+X509 Certificate information, RSA Certificate Policy any with qualifier
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-any_policy_with_qualifier.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nissued  on        \: 2019-04-28 13\:14\:31\nexpires on        \: 2029-04-28 13\:14\:31\nsigned using      \: RSA with SHA-256\nRSA key size      \: 2048 bits\nbasic constraints \: CA=true\ncertificate policies \: Any Policy\n"
+
+X509 Certificate information, ECDSA Certificate Policy any  with qualifier
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-any_policy_with_qualifier_ec.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name      \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nissued  on        \: 2019-04-28 10\:16\:05\nexpires on        \: 2029-04-28 10\:16\:05\nsigned using      \: ECDSA with SHA256\nEC key size       \: 384 bits\nbasic constraints \: CA=true\ncertificate policies \: Any Policy\n"
+
+X509 Certificate information, RSA Certificate multiple Policies
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-multi_policy.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nissued  on        \: 2019-04-28 12\:59\:19\nexpires on        \: 2029-04-28 12\:59\:19\nsigned using      \: RSA with SHA-256\nRSA key size      \: 2048 bits\nbasic constraints \: CA=true\ncertificate policies \: ???, Any Policy\n"
+
+X509 Certificate information, ECDSA Certificate multiple Policies
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-multi_policy_ec.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name      \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nissued  on        \: 2019-04-28 12\:59\:51\nexpires on        \: 2029-04-28 12\:59\:51\nsigned using      \: ECDSA with SHA256\nEC key size       \: 384 bits\nbasic constraints \: CA=true\ncertificate policies \: ???, Any Policy\n"
+
+X509 Certificate information, RSA Certificate unsupported policy
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-unsupported_policy.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nissued  on        \: 2019-04-28 13\:00\:13\nexpires on        \: 2029-04-28 13\:00\:13\nsigned using      \: RSA with SHA-256\nRSA key size      \: 2048 bits\nbasic constraints \: CA=true\ncertificate policies \: ???\n"
+
+X509 Certificate information, ECDSA Certificate unsupported policy
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/test-ca-unsupported_policy_ec.crt":"cert. version     \: 3\nserial number     \: 00\nissuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name      \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nissued  on        \: 2019-04-28 13\:00\:19\nexpires on        \: 2029-04-28 13\:00\:19\nsigned using      \: ECDSA with SHA256\nEC key size       \: 384 bits\nbasic constraints \: CA=true\ncertificate policies \: ???\n"
+
 X509 Certificate information, Key Usage + Extended Key Usage
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509_cert_info:"data_files/server1.ext_ku.crt":"cert. version     \: 3\nserial number     \: 21\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nissued  on        \: 2014-04-01 14\:44\:43\nexpires on        \: 2024-03-29 14\:44\:43\nsigned using      \: RSA with SHA-256\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\next key usage     \: TLS Web Server Authentication\n"

From 226991e624a1d5e339cf6b7123b46e8c852b7223 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Sun, 24 Mar 2019 13:39:51 +0200
Subject: [PATCH 03/27] Add ChangeLog entry for new extensions change

Add an entry for the new x509 extension parsing support.
---
 ChangeLog | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 58ff14734..ce50950a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -61,6 +61,10 @@ Features
    * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites
      from the default list (enabled by default). See
      https://sweet32.info/SWEET32_CCS16.pdf.
+   * Add support for parsing subject alternative name, of type otherName,
+     HardwareModuleName, as defined in rfc 4108 section 5.
+   * Add support for parsing certificate policies extension, as defined in
+     rfc 5280 section 4.2.1.4. Currently only supports "Any Policy" policy.
 
 API Changes
    * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.

From 3c4734a2a569c538350758bd456bc6e55af1eb64 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 25 Mar 2019 14:05:23 +0200
Subject: [PATCH 04/27] Add Wisun Fan device certificate

Add certificate with Wisun fan device extended key usage,
support parsing it and add tests.
---
 include/mbedtls/oid.h                  |  2 +-
 tests/data_files/Makefile              |  3 +++
 tests/data_files/server5-fan.crt       | 10 ++++++++++
 tests/data_files/test-ca.opensslconf   |  3 +++
 tests/suites/test_suite_x509parse.data |  4 ++++
 5 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 tests/data_files/server5-fan.crt

diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index c516b7aaf..1e96856e2 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -212,7 +212,7 @@
  * { iso(1) identified-organization(3) dod(6) internet(1)
  *                      private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) }
  */
-#define MBEDTLS_OID_WISUN_FAN                  MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01"
+#define MBEDTLS_OID_WISUN_FAN                   MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01"
 
 #define MBEDTLS_OID_ON                          MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */
 #define MBEDTLS_OID_ON_HW_MODULE_NAME           MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index d139bfa06..d1af18ce7 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -184,6 +184,9 @@ server5-othername.crt: server5.key
 server5-unsupported_othername.crt: server5.key
 	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS unsupported othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions unsupoported_othername_san -days 3650 -sha256 -key $< -out $@
 
+server5-fan.crt: server5.key
+	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS FAN" -set_serial 77 -config $(test_ca_config_file) -extensions fan_cert -days 3650 -sha256 -key server5.key -out $@
+
 server10-badsign.crt: server10.crt
 	{ head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@
 all_final += server10-badsign.crt
diff --git a/tests/data_files/server5-fan.crt b/tests/data_files/server5-fan.crt
new file mode 100644
index 000000000..dc1eb380c
--- /dev/null
+++ b/tests/data_files/server5-fan.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBdTCCARugAwIBAgIBTTAKBggqhkjOPQQDAjA3MQswCQYDVQQGEwJVSzERMA8G
+A1UECgwITWJlZCBUTFMxFTATBgNVBAMMDE1iZWQgVExTIEZBTjAeFw0xOTAzMjUw
+OTAzNDZaFw0yOTAzMjIwOTAzNDZaMDcxCzAJBgNVBAYTAlVLMREwDwYDVQQKDAhN
+YmVkIFRMUzEVMBMGA1UEAwwMTWJlZCBUTFMgRkFOMFkwEwYHKoZIzj0CAQYIKoZI
+zj0DAQcDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/
+6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/6MYMBYwFAYDVR0lBA0wCwYJKwYBBAGC
+5CUBMAoGCCqGSM49BAMCA0gAMEUCIQDp/Q5FaVy3YNeJflQKLGycQZoH6V3FQnLq
+ERUCeimLIAIgdyiA4KdHxkpQhC1L1KfmxG8YJqu31FBjmNw00Sv8J9k=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca.opensslconf b/tests/data_files/test-ca.opensslconf
index 5f71532ce..d2c5c0630 100644
--- a/tests/data_files/test-ca.opensslconf
+++ b/tests/data_files/test-ca.opensslconf
@@ -51,6 +51,9 @@ certificatePolicies = 1.2.3.4
 policyIdentifier = 2.5.29.32.0
 CPS.1 ="CPS uri string"
 
+[fan_cert]
+extendedKeyUsage = 1.3.6.1.4.1.45605.1
+
 [noext_ca]
 basicConstraints = CA:true
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 6fcf80564..d3afe1f88 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -98,6 +98,10 @@ X509 Certificate information EC, SHA256 Digest, hardware module name SAN
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
 x509_cert_info:"data_files/server5-othername.crt":"cert. version     \: 3\nserial number     \: 4D\nissuer name       \: C=UK, O=Mbed TLS, CN=Mbed TLS othername SAN\nsubject name      \: C=UK, O=Mbed TLS, CN=Mbed TLS othername SAN\nissued  on        \: 2019-03-24 09\:06\:02\nexpires on        \: 2029-03-21 09\:06\:02\nsigned using      \: ECDSA with SHA256\nEC key size       \: 256 bits\nsubject alt name  \:\n    otherName \:\n        hardware module name \:\n            hardware type          \: 1.3.6.1.4.1.17.3\n            hardware serial number \: 123456\n"
 
+X509 Certificate information EC, SHA256 Digest, Wisun Fan device
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+x509_cert_info:"data_files/server5-fan.crt":"cert. version     \: 3\nserial number     \: 4D\nissuer name       \: C=UK, O=Mbed TLS, CN=Mbed TLS FAN\nsubject name      \: C=UK, O=Mbed TLS, CN=Mbed TLS FAN\nissued  on        \: 2019-03-25 09\:03\:46\nexpires on        \: 2029-03-22 09\:03\:46\nsigned using      \: ECDSA with SHA256\nEC key size       \: 256 bits\next key usage     \: Wi-SUN Alliance Field Area Network (FAN)\n"
+
 X509 Certificate information, NS Cert Type
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
 x509_cert_info:"data_files/server1.cert_type.crt":"cert. version     \: 3\nserial number     \: 01\nissuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name      \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nissued  on        \: 2011-02-12 14\:44\:06\nexpires on        \: 2021-02-12 14\:44\:06\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\ncert. type        \: SSL Server\n"

From 5091bec3ea5b29aa0a745bdd17438178f842175f Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Wed, 8 May 2019 15:23:08 +0100
Subject: [PATCH 05/27] Fix doxygen for new x509 structures

The documentation for some new structures and members was only a C style
comment and wasn't picked up by doxygen. This commit adds the missing
asterisks.
---
 include/mbedtls/x509_crt.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index acaafbe9f..c93fefa22 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -99,7 +99,7 @@ typedef struct mbedtls_x509_crt
 }
 mbedtls_x509_crt;
 
-/*
+/**
  * From RFC 5280 section 4.2.1.6:
  * OtherName ::= SEQUENCE {
  *      type-id    OBJECT IDENTIFIER,
@@ -110,7 +110,7 @@ typedef struct mbedtls_x509_san_other_name
     mbedtls_x509_buf type_id;                   /**< The type id. */
     union
     {
-        /*
+        /**
          * From RFC 4108 section 5:
          * HardwareModuleName ::= SEQUENCE {
          *                         hwType OBJECT IDENTIFIER,
@@ -122,7 +122,7 @@ typedef struct mbedtls_x509_san_other_name
 }
 mbedtls_x509_san_other_name;
 
-/*
+/**
  * A structure for holding the parsed Subject Alternative Name, according to type
  */
 typedef struct mbedtls_x509_subject_alternative_name

From 11b41eb12beffb486f22e6fc34d7b0eed0b0026b Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Wed, 8 May 2019 15:26:49 +0100
Subject: [PATCH 06/27] Fix typos in x509_crt.h

---
 include/mbedtls/x509_crt.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index c93fefa22..ad39400a5 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -386,12 +386,12 @@ int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path );
  *                 if partly successful or a specific X509 or PEM error code
  */
 int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
+
 #endif /* MBEDTLS_FS_IO */
 /**
- * \brief          Parses the subject alternative name list of a given certificate;
+ * \brief          Parses the subject alternative name list of a given certificate.
  *
  * \param crt      The X509 certificate to parse.
- *
  * \param san      A list holding the parsed certificate.
  *
  * \note           Only "dnsName" and "otherName" of type hardware_module_name,

From ab23cd1eae1afe30f11c06cf26034a0c0ee3f006 Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Thu, 9 May 2019 13:53:57 +0100
Subject: [PATCH 07/27] Remove unneeded checks from x509_get_other_name

Lengths are aleady checked in mbedtls_asn1_get_len() which is called in
mbedtls_asn1_get_tag(), therefore it is not necessary to check
the lengths explicitly afterwards.

Also with the previous flow data was left in the output buffer on some
errors.
---
 library/x509_crt.c | 31 +++++++++++++------------------
 1 file changed, 13 insertions(+), 18 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index f17c8b2ec..cfd3b9d13 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1584,7 +1584,7 @@ cleanup:
 static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
                                 mbedtls_x509_san_other_name *other_name )
 {
-    int ret;
+    int ret = 0;
     size_t len;
     unsigned char *p = subject_alt_name->p;
     const unsigned char *end = p + subject_alt_name->len;
@@ -1616,12 +1616,6 @@ static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
     }
 
-    if( p + len >= end )
-    {
-        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
@@ -1638,30 +1632,31 @@ static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
     other_name->value.hardware_module_name.oid.p = p;
     other_name->value.hardware_module_name.oid.len = len;
 
-    if( p + len >= end )
-    {
-        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
                                       MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        goto cleanup;
 
     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
     other_name->value.hardware_module_name.val.p = p;
     other_name->value.hardware_module_name.val.len = len;
     other_name->value.hardware_module_name.next = NULL;
     other_name->value.hardware_module_name.next_merged = 0;
+
     p += len;
     if( p != end )
     {
-        mbedtls_platform_zeroize( other_name,
-                                  sizeof( other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
     }
+
+cleanup:
+
+    if( ret != 0 )
+    {
+        memset( other_name, 0, sizeof( *other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+    }
+
     return( 0 );
 }
 

From 22f605fbab03c36f3ce32f0fdd681dbec480917c Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Fri, 10 May 2019 10:37:17 +0100
Subject: [PATCH 08/27] Print unparseable SubjectAlternativeNames

In x509_info_subject_alt_name() we silently dropped names that we
couldn't parse because they are not supported or are malformed. (Being
malformed might mean damaged file, but can be a sign of incompatibility
between applications.)

This commit adds code notifying the user that there is something, but
we can't parse it.
---
 library/x509_crt.c                     | 34 +++++++++++++++-----------
 tests/suites/test_suite_x509parse.data |  4 +--
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index cfd3b9d13..54b42854b 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1682,21 +1682,27 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
             {
                 mbedtls_x509_san_other_name other_name;
 
-                ret = x509_get_other_name( &cur->buf, &other_name );
-                if( ret != 0 )
-                {
-                    /*
-                     * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
-                     * then the "otherName" is of an unsupported type. Ignore.
-                     */
-                    if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-                        ret = 0;
-                    return( ret );
-                }
+                int parse_ret = x509_get_other_name( &cur->buf, &other_name );
 
                 ret = mbedtls_snprintf( p, n, "\n%s    otherName :", prefix );
                 MBEDTLS_X509_SAFE_SNPRINTF;
 
+                if( parse_ret != 0 )
+                {
+                    if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                    {
+                        ret = mbedtls_snprintf( p, n, " <unsupported>" );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+                    }
+                    else
+                    {
+                        ret = mbedtls_snprintf( p, n, " <malformed>" );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+                    }
+
+                    break;
+                }
+
                 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
                              &other_name.value.hardware_module_name.oid ) != 0 )
                 {
@@ -1732,7 +1738,6 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
              */
             case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
             {
-
                 ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
                 MBEDTLS_X509_SAFE_SNPRINTF;
                 if( cur->buf.len >= n )
@@ -1747,13 +1752,14 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
             break;
 
             /*
-             * Type not supported, skip item.
+             * Type not supported.
              */
             default:
+                ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
                 break;
         }
 
-
         cur = cur->next;
     }
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index d3afe1f88..99dd0833f 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -124,7 +124,7 @@ x509_cert_info:"data_files/multiple_san.crt":"cert. version     \: 3\nserial num
 
 X509 Certificate information, Subject Alt Name + Key Usage
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version     \: 3\nserial number     \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name       \: C=NL\nsubject name      \: C=NL\nissued  on        \: 2014-01-22 10\:04\:33\nexpires on        \: 2024-01-22 10\:04\:33\nsigned using      \: RSA with SHA1\nRSA key size      \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    dNSName \: www.shotokan-braunschweig.de\n    dNSName \: www.massimo-abate.eu\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
+x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version     \: 3\nserial number     \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name       \: C=NL\nsubject name      \: C=NL\nissued  on        \: 2014-01-22 10\:04\:33\nexpires on        \: 2024-01-22 10\:04\:33\nsigned using      \: RSA with SHA1\nRSA key size      \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    dNSName \: www.shotokan-braunschweig.de\n    dNSName \: www.massimo-abate.eu\n    <unsupported>\n    <unsupported>\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
 
 X509 Certificate information, RSA Certificate Policy any
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
@@ -172,7 +172,7 @@ x509_cert_info:"data_files/server3.crt":"cert. version     \: 3\nserial number
 
 X509 Certificate information Bitstring in subject name
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/bitstring-in-dn.pem":"cert. version     \: 3\nserial number     \: 02\nissuer name       \: CN=Test CA 01, ST=Ecnivorp, C=XX, emailAddress=tca@example.com, O=Test CA Authority\nsubject name      \: C=XX, O=tca, ST=Ecnivorp, OU=TCA, CN=Client, emailAddress=client@example.com, serialNumber=7101012255, uniqueIdentifier=?7101012255\nissued  on        \: 2015-03-11 12\:06\:51\nexpires on        \: 2025-03-08 12\:06\:51\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \:\next key usage     \: TLS Web Client Authentication\n"
+x509_cert_info:"data_files/bitstring-in-dn.pem":"cert. version     \: 3\nserial number     \: 02\nissuer name       \: CN=Test CA 01, ST=Ecnivorp, C=XX, emailAddress=tca@example.com, O=Test CA Authority\nsubject name      \: C=XX, O=tca, ST=Ecnivorp, OU=TCA, CN=Client, emailAddress=client@example.com, serialNumber=7101012255, uniqueIdentifier=?7101012255\nissued  on        \: 2015-03-11 12\:06\:51\nexpires on        \: 2025-03-08 12\:06\:51\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name  \:\n    <unsupported>\next key usage     \: TLS Web Client Authentication\n"
 
 X509 certificate v1 with extension
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_SHA1_C

From 2f0ec1e3bf4a02d64251826231284044972f7f4f Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Fri, 10 May 2019 11:06:31 +0100
Subject: [PATCH 09/27] Tidy up style in x509_info_subject_alt_name

---
 library/x509_crt.c | 122 ++++++++++++++++++++++++++-------------------
 1 file changed, 70 insertions(+), 52 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 54b42854b..a01b53c3c 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1661,7 +1661,8 @@ cleanup:
 }
 
 static int x509_info_subject_alt_name( char **buf, size_t *size,
-                                       const mbedtls_x509_sequence *subject_alt_name,
+                                       const mbedtls_x509_sequence
+                                                    *subject_alt_name,
                                        const char *prefix )
 {
     size_t i;
@@ -1679,77 +1680,94 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
              * otherName
              */
             case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
-            {
-                mbedtls_x509_san_other_name other_name;
-
-                int parse_ret = x509_get_other_name( &cur->buf, &other_name );
-
-                ret = mbedtls_snprintf( p, n, "\n%s    otherName :", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-
-                if( parse_ret != 0 )
                 {
-                    if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                    mbedtls_x509_san_other_name other_name;
+
+                    int parse_ret = x509_get_other_name( &cur->buf,
+                                                         &other_name );
+
+                    ret = mbedtls_snprintf( p, n, "\n%s    otherName :",
+                                            prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    if( parse_ret != 0 )
                     {
-                        ret = mbedtls_snprintf( p, n, " <unsupported>" );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
-                    }
-                    else
-                    {
-                        ret = mbedtls_snprintf( p, n, " <malformed>" );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
+                        if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                        {
+                            ret = mbedtls_snprintf( p, n, " <unsupported>" );
+                            MBEDTLS_X509_SAFE_SNPRINTF;
+                        }
+                        else
+                        {
+                            ret = mbedtls_snprintf( p, n, " <malformed>" );
+                            MBEDTLS_X509_SAFE_SNPRINTF;
+                        }
+
+                        break;
                     }
 
-                    break;
+                    if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+                                 &other_name.value.hardware_module_name.oid )
+                        != 0 )
+                    {
+                        ret = mbedtls_snprintf( p, n, "\n%s        "
+                                                    "hardware module name :",
+                                                prefix );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+                        ret = mbedtls_snprintf( p, n,
+                                                "\n%s            "
+                                                    "hardware type          : ",
+                                                prefix );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+
+                        ret = mbedtls_oid_get_numeric_string( p, n,
+                                &other_name.value.hardware_module_name.oid );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+
+                        ret = mbedtls_snprintf( p, n,
+                                                "\n%s            "
+                                                    "hardware serial number : ",
+                                                prefix );
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+
+                        if( other_name.value.hardware_module_name.val.len >= n )
+                        {
+                            *p = '\0';
+                            return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+                        }
+
+                        for( i = 0;
+                             i < other_name.value.hardware_module_name.val.len;
+                             i++ )
+                        {
+                            *p++ =
+                                other_name.value.hardware_module_name.val.p[i];
+                        }
+                        n -= other_name.value.hardware_module_name.val.len;
+
+                    }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+
                 }
-
-                if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
-                             &other_name.value.hardware_module_name.oid ) != 0 )
-                {
-                    ret = mbedtls_snprintf( p, n, "\n%s        hardware module name :", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-                    ret = mbedtls_snprintf( p, n, "\n%s            hardware type          : ", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    ret = mbedtls_oid_get_numeric_string( p, n, &other_name.value.hardware_module_name.oid );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    ret = mbedtls_snprintf( p, n, "\n%s            hardware serial number : ", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    if( other_name.value.hardware_module_name.val.len >= n )
-                    {
-                        *p = '\0';
-                        return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
-                    }
-
-                    for( i = 0; i < other_name.value.hardware_module_name.val.len; i++ )
-                    {
-                        *p++ = other_name.value.hardware_module_name.val.p[i];
-                    }
-                    n -= other_name.value.hardware_module_name.val.len;
-
-                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
-            }
-            break;
+                break;
 
             /*
              * dNSName
              */
             case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
-            {
                 ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
                 MBEDTLS_X509_SAFE_SNPRINTF;
+
                 if( cur->buf.len >= n )
                 {
                     *p = '\0';
                     return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
                 }
+
                 n -= cur->buf.len;
                 for( i = 0; i < cur->buf.len; i++ )
                     *p++ = cur->buf.p[i];
-            }
-            break;
+
+                break;
 
             /*
              * Type not supported.

From 6c379b4b8091ede8d28becc6bf36c7a7c59c3b37 Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Fri, 10 May 2019 14:17:16 +0100
Subject: [PATCH 10/27] Propogate error when parsing SubjectAltNames

The previous behaviour of mbedtls_x509_parse_subject_alternative_name()
was to silently ignore errors coming from x509_get_other_name(). The
current commit fixes it and returns with an error.
---
 library/x509_crt.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index a01b53c3c..047e4e6e2 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1823,8 +1823,9 @@ int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
                          * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
                          * then the "otherName" is of an unsupported type. Ignore.
                          */
-                        if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-                            ret = 0;
+                        if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                            return MBEDTLS_ERR_X509_INVALID_FORMAT;
+
                         cur = cur->next;
                         continue;
                     }

From 293c3dae6dce53b03b5149f097009c147644e0e3 Mon Sep 17 00:00:00 2001
From: Janos Follath <janos.follath@arm.com>
Date: Fri, 10 May 2019 15:53:03 +0100
Subject: [PATCH 11/27] Remove redundant memset()

The preceding calloc() already zeroizes that memory area, therfore the
memset() is not necessary. Compilers are likely to optimize this out,
but it still can be confusing to readers.
---
 library/x509_crt.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 047e4e6e2..f58b15694 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1858,7 +1858,6 @@ int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
                     if( prev_san != NULL )
                         prev_san->next = cur_san;
 
-                    memset( cur_san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
                     cur_san->type = MBEDTLS_X509_SAN_DNS_NAME;
 
                     memcpy( &cur_san->san.unstructured_name,

From 26cfd1361dd7e92aff4fd7cb6a951c1b0181c629 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 13 May 2019 15:48:38 +0300
Subject: [PATCH 12/27] Rephrase changeLog entries

Rephrase the changeLog entries for clarity and capitalize RFC.
---
 ChangeLog | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ce50950a3..f942ebbf5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -61,10 +61,11 @@ Features
    * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites
      from the default list (enabled by default). See
      https://sweet32.info/SWEET32_CCS16.pdf.
-   * Add support for parsing subject alternative name, of type otherName,
-     HardwareModuleName, as defined in rfc 4108 section 5.
+   * Add support for parsing otherName entries in the Subject Alternative Name
+     X.509 certificate extension, as defined in RFC 4108 section 5.
    * Add support for parsing certificate policies extension, as defined in
-     rfc 5280 section 4.2.1.4. Currently only supports "Any Policy" policy.
+     RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is
+     supported.
 
 API Changes
    * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.

From 78c3040347b5bdcbbaeeeafe9cfb587e8a9eccad Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 13 May 2019 15:49:53 +0300
Subject: [PATCH 13/27] Rephrase x509_crt extension member description

Rephrase doxygen comments for subject alternative name
and certificate policies.
---
 include/mbedtls/x509_crt.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index ad39400a5..dbfaf9c08 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -76,9 +76,9 @@ typedef struct mbedtls_x509_crt
     mbedtls_x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
     mbedtls_x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
     mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
-    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName and OtherName supported). */
+    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
 
-    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate4 policies (Only anyPolicy supported). */
+    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy supported). */
 
     int ext_types;              /**< Bit string containing detected and parsed extensions */
     int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */

From 0806379e3e359d5d6f67e354767812dfc848c0e8 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 13 May 2019 16:38:39 +0300
Subject: [PATCH 14/27] Add length checking in certificate policy parsing

Change the extension parsing to `policy_end` and verify that
the policy and qualifiers length don't exceed the end of the extension.
---
 library/x509_crt.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index f58b15694..977772676 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -779,7 +779,7 @@ static int x509_get_certificate_policies( unsigned char **p,
 
         policy_end = *p + len;
 
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+        if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
                                           MBEDTLS_ASN1_OID ) ) != 0 )
             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
 
@@ -806,11 +806,27 @@ static int x509_get_certificate_policies( unsigned char **p,
         buf->tag = policy_oid.tag;
         buf->p = policy_oid.p;
         buf->len = policy_oid.len;
-        /*
-         * Skip the optional policy qualifiers,
-         * and set the pointer to the end of the policy.
-         */
-        *p = (unsigned char *)policy_end;
+
+        *p += len;
+
+       /*
+        * If there is an optional qualifier, then *p < policy_end
+        * Check the Qualifier len to verify it doesn't exceed policy_end.
+        */
+        if( *p < policy_end )
+        {
+            if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
+                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            /*
+             * Skip the optional policy qualifiers.
+             */
+            *p += len;
+        }
+
+        if( *p != policy_end )
+            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
     }
 
     /* Set final sequence entry's next pointer to NULL */

From 890819a597bd7a67f0b8185a4409733504f792b3 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 13 May 2019 19:03:04 +0300
Subject: [PATCH 15/27] Change mbedtls_x509_subject_alternative_name

Make `mbedtls_x509_subject_alternative_name` to be a single item
rather than a list. Adapt the subject alternative name parsing function,
to receive a signle `mbedtls_x509_buf` item from the subject_alt_names
sequence of the certificate.
---
 include/mbedtls/x509_crt.h                 |  34 ++-
 library/x509_crt.c                         | 284 ++++++++-------------
 tests/suites/test_suite_x509parse.function |  29 ++-
 3 files changed, 151 insertions(+), 196 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index dbfaf9c08..b321c4233 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -107,6 +107,11 @@ mbedtls_x509_crt;
  */
 typedef struct mbedtls_x509_san_other_name
 {
+    /**
+     * The type_id is an OID as deifned in RFC 5280.
+     * To check the value of the type id, you should use
+     * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
+     */
     mbedtls_x509_buf type_id;                   /**< The type id. */
     union
     {
@@ -133,7 +138,6 @@ typedef struct mbedtls_x509_subject_alternative_name
         mbedtls_x509_buf   unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
     }
     san; /**< A union of the supported SAN types */
-    struct mbedtls_x509_subject_alternative_name *next; /**< The next SAN in the list. */
 }
 mbedtls_x509_subject_alternative_name;
 
@@ -389,24 +393,30 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
 
 #endif /* MBEDTLS_FS_IO */
 /**
- * \brief          Parses the subject alternative name list of a given certificate.
+ * \brief          Parses a subject alternative name item
+ *                 to an identified structure;
  *
- * \param crt      The X509 certificate to parse.
- * \param san      A list holding the parsed certificate.
+ * \param san_buf  The buffer holding the raw data item of the subject
+ *                 alternative name.
+ * \param san      The target structure to populate with the parsed presentation
+ *                 of the subject alternative name encoded in \p san_raw.
  *
  * \note           Only "dnsName" and "otherName" of type hardware_module_name,
  *                 as defined in RFC 4180 is supported.
  *
- * \note           Any unsupported san type is ignored.
+ * \note           This function should be called on a single raw data of
+ *                 subject alternative name. For example, after successfult
+ *                 certificate parsing, one must iterate on every item in the
+ *                 \p crt->subject_alt_names sequence, and send it as parameter
+ *                 to this function.
  *
- * \note           The function allocates a list of mbedtls_x509_subject_alternative_name
- *                 and it is the caller's responsibility to free it.
- *
- * \return         Zero for success and negative
- *                 value for any other failure.
+ * \return         \c 0 on success
+ * \return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
+ *                 SAN type
+ * \return         Negative value for any other failure.
  */
-int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
-                                                 mbedtls_x509_subject_alternative_name **san );
+int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
+                                         mbedtls_x509_subject_alternative_name *san );
 /**
  * \brief          Returns an informational string about the
  *                 certificate.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 977772676..cce230bd2 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1632,6 +1632,12 @@ static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
     }
 
+    if( p + len >= end )
+    {
+        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
@@ -1648,31 +1654,30 @@ static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
     other_name->value.hardware_module_name.oid.p = p;
     other_name->value.hardware_module_name.oid.len = len;
 
+    if( p + len >= end )
+    {
+        mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
                                       MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        goto cleanup;
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
 
     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
     other_name->value.hardware_module_name.val.p = p;
     other_name->value.hardware_module_name.val.len = len;
     other_name->value.hardware_module_name.next = NULL;
     other_name->value.hardware_module_name.next_merged = 0;
-
     p += len;
     if( p != end )
     {
-        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+        mbedtls_platform_zeroize( other_name,
+                                  sizeof( other_name ) );
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
     }
-
-cleanup:
-
-    if( ret != 0 )
-    {
-        memset( other_name, 0, sizeof( *other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-    }
-
     return( 0 );
 }
 
@@ -1686,107 +1691,91 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
     size_t n = *size;
     char *p = *buf;
     const mbedtls_x509_sequence *cur = subject_alt_name;
+    mbedtls_x509_subject_alternative_name san;
+    int parse_ret;
 
     while( cur != NULL )
     {
-        switch( cur->buf.tag &
-                ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) )
+        memset( &san, 0, sizeof( san ) );
+        parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
+        if( parse_ret != 0 )
+        {
+            if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+            {
+                ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+            }
+            else
+            {
+                ret = mbedtls_snprintf( p, n, "\n%s    <malformed>", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+            }
+            cur = cur->next;
+            continue;
+        }
+
+        switch( san.type )
         {
             /*
              * otherName
              */
-            case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+            case( MBEDTLS_X509_SAN_OTHER_NAME ):
+            {
+                mbedtls_x509_san_other_name *other_name = &san.san.other_name;
+
+                ret = mbedtls_snprintf( p, n, "\n%s    otherName :", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+
+                if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+                                     &other_name->value.hardware_module_name.oid ) != 0 )
                 {
-                    mbedtls_x509_san_other_name other_name;
-
-                    int parse_ret = x509_get_other_name( &cur->buf,
-                                                         &other_name );
-
-                    ret = mbedtls_snprintf( p, n, "\n%s    otherName :",
-                                            prefix );
+                    ret = mbedtls_snprintf( p, n, "\n%s        hardware module name :", prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+                    ret = mbedtls_snprintf( p, n, "\n%s            hardware type          : ", prefix );
                     MBEDTLS_X509_SAFE_SNPRINTF;
 
-                    if( parse_ret != 0 )
-                    {
-                        if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-                        {
-                            ret = mbedtls_snprintf( p, n, " <unsupported>" );
-                            MBEDTLS_X509_SAFE_SNPRINTF;
-                        }
-                        else
-                        {
-                            ret = mbedtls_snprintf( p, n, " <malformed>" );
-                            MBEDTLS_X509_SAFE_SNPRINTF;
-                        }
+                    ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
 
-                        break;
+                    ret = mbedtls_snprintf( p, n, "\n%s            hardware serial number : ", prefix );
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    if( other_name->value.hardware_module_name.val.len >= n )
+                    {
+                        *p = '\0';
+                        return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
                     }
 
-                    if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
-                                 &other_name.value.hardware_module_name.oid )
-                        != 0 )
+                    for( i = 0; i < other_name->value.hardware_module_name.val.len; i++ )
                     {
-                        ret = mbedtls_snprintf( p, n, "\n%s        "
-                                                    "hardware module name :",
-                                                prefix );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
-                        ret = mbedtls_snprintf( p, n,
-                                                "\n%s            "
-                                                    "hardware type          : ",
-                                                prefix );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
+                        *p++ = other_name->value.hardware_module_name.val.p[i];
+                    }
+                    n -= other_name->value.hardware_module_name.val.len;
 
-                        ret = mbedtls_oid_get_numeric_string( p, n,
-                                &other_name.value.hardware_module_name.oid );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
-
-                        ret = mbedtls_snprintf( p, n,
-                                                "\n%s            "
-                                                    "hardware serial number : ",
-                                                prefix );
-                        MBEDTLS_X509_SAFE_SNPRINTF;
-
-                        if( other_name.value.hardware_module_name.val.len >= n )
-                        {
-                            *p = '\0';
-                            return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
-                        }
-
-                        for( i = 0;
-                             i < other_name.value.hardware_module_name.val.len;
-                             i++ )
-                        {
-                            *p++ =
-                                other_name.value.hardware_module_name.val.p[i];
-                        }
-                        n -= other_name.value.hardware_module_name.val.len;
-
-                    }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
-
-                }
-                break;
+                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+            }
+            break;
 
             /*
              * dNSName
              */
-            case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+            case( MBEDTLS_X509_SAN_DNS_NAME ):
+            {
                 ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
                 MBEDTLS_X509_SAFE_SNPRINTF;
-
-                if( cur->buf.len >= n )
+                if( san.san.unstructured_name.len >= n )
                 {
                     *p = '\0';
                     return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
                 }
-
-                n -= cur->buf.len;
-                for( i = 0; i < cur->buf.len; i++ )
-                    *p++ = cur->buf.p[i];
-
-                break;
+                n -= san.san.unstructured_name.len;
+                for( i = 0; i < san.san.unstructured_name.len; i++ )
+                    *p++ = san.san.unstructured_name.p[i];
+            }
+            break;
 
             /*
-             * Type not supported.
+             * Type not supported, skip item.
              */
             default:
                 ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
@@ -1805,102 +1794,53 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
     return( 0 );
 }
 
-int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
-                                                 mbedtls_x509_subject_alternative_name **san )
+int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
+                                         mbedtls_x509_subject_alternative_name *san )
 {
     int ret;
-    const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
-    mbedtls_x509_subject_alternative_name *cur_san = *san, *prev_san = NULL;
-
-    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+    switch( san_buf->tag &
+            ( MBEDTLS_ASN1_TAG_CLASS_MASK |
+              MBEDTLS_ASN1_TAG_VALUE_MASK ) )
     {
-        if( cur_san != NULL )
+        /*
+         * otherName
+         */
+        case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
         {
-            return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+            mbedtls_x509_san_other_name other_name;
+
+            ret = x509_get_other_name( san_buf, &other_name );
+            if( ret != 0 )
+                return( ret );
+
+            memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+            san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+            memcpy( &san->san.other_name,
+                    &other_name, sizeof( other_name ) );
+
         }
+        break;
 
-        while( cur != NULL )
+        /*
+         * dNSName
+         */
+        case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
         {
-            switch( cur->buf.tag &
-                    ( MBEDTLS_ASN1_TAG_CLASS_MASK |
-                      MBEDTLS_ASN1_TAG_VALUE_MASK ) )
-            {
-                /*
-                 * otherName
-                 */
-                case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
-                {
-                    mbedtls_x509_san_other_name other_name;
+            memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+            san->type = MBEDTLS_X509_SAN_DNS_NAME;
 
-                    ret = x509_get_other_name( &cur->buf, &other_name );
-                    if( ret != 0 )
-                    {
-                        /*
-                         * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
-                         * then the "otherName" is of an unsupported type. Ignore.
-                         */
-                        if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-                            return MBEDTLS_ERR_X509_INVALID_FORMAT;
+            memcpy( &san->san.unstructured_name,
+                    san_buf, sizeof( *san_buf ) );
 
-                        cur = cur->next;
-                        continue;
-                    }
+        }
+        break;
 
-                    cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
-                    if( cur_san == NULL )
-                        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                                MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
-                    if( prev_san != NULL )
-                        prev_san->next = cur_san;
-
-                    cur_san->type = MBEDTLS_X509_SAN_OTHER_NAME;
-                    memcpy( &cur_san->san.other_name,
-                            &other_name, sizeof( other_name ) );
-
-                }
-                break;
-
-                /*
-                 * dNSName
-                 */
-                case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
-                {
-                    cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
-                    if( cur_san == NULL )
-                        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                                MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
-                    if( prev_san != NULL )
-                        prev_san->next = cur_san;
-
-                    cur_san->type = MBEDTLS_X509_SAN_DNS_NAME;
-
-                    memcpy( &cur_san->san.unstructured_name,
-                            &cur->buf, sizeof( cur->buf ) );
-
-                }
-                break;
-
-                /*
-                 * Type not supported, skip item.
-                 */
-                default:
-                    break;
-            }
-
-            if( *san == NULL )
-                *san = cur_san;
-
-            if( cur_san != NULL )
-            {
-                prev_san = cur_san;
-                cur_san = cur_san->next;
-            }
-
-            cur = cur->next;
-        }/* while( cur != NULL ) */
-    }/* crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME */
+        /*
+         * Type not supported
+         */
+        default:
+            return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+    }
     return( 0 );
 }
 
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index beec52cc3..b4e980210 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -303,8 +303,10 @@ int verify_parse_san( mbedtls_x509_subject_alternative_name *san,
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
 void x509_parse_san( char * crt_file, char * result_str )
 {
+    int ret;
     mbedtls_x509_crt   crt;
-    mbedtls_x509_subject_alternative_name *cur, *next, *san = NULL;
+    mbedtls_x509_subject_alternative_name san;
+    mbedtls_x509_sequence *cur = NULL;
     char buf[2000];
     char *p = buf;
     size_t n = sizeof( buf );
@@ -313,24 +315,27 @@ void x509_parse_san( char * crt_file, char * result_str )
     memset( buf, 0, 2000 );
 
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
-    TEST_ASSERT( mbedtls_x509_parse_subject_alternative_name( &crt, &san ) == 0 );
-    cur = san;
-    while( cur != NULL )
+
+    if( crt.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
     {
-        TEST_ASSERT( verify_parse_san( cur, &p, &n ) == 0 );
-        cur = cur->next;
+        cur = &crt.subject_alt_names;
+        while( cur != NULL )
+        {
+            ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
+            TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+            /*
+             * If san type not supported, ignore.
+             */
+            if( ret == 0)
+                TEST_ASSERT( verify_parse_san( &san, &p, &n ) == 0 );
+            cur = cur->next;
+        }
     }
 
     TEST_ASSERT( strcmp( buf, result_str ) == 0 );
 
 exit:
 
-    for( cur = san; cur != NULL; cur = next )
-    {
-        next = cur->next;
-        mbedtls_free( cur );
-    }
-
     mbedtls_x509_crt_free( &crt );
 }
 /* END_CASE */

From f05f594acbd405104150f47b349e423cc1ba0241 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 13 May 2019 19:11:31 +0300
Subject: [PATCH 16/27] change the type of hardware_module_name member

Change the type of `hardware_module_name` struct from
`mbedtls_x509_name` to a unique struct, to distinguish it from the
named data type.
---
 include/mbedtls/x509_crt.h | 7 ++++++-
 library/x509_crt.c         | 2 --
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index b321c4233..81a2de2be 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -121,7 +121,12 @@ typedef struct mbedtls_x509_san_other_name
          *                         hwType OBJECT IDENTIFIER,
          *                         hwSerialNum OCTET STRING }
          */
-        mbedtls_x509_name hardware_module_name;
+        struct
+        {
+            mbedtls_x509_buf oid;               /**< The object identifier. */
+            mbedtls_x509_buf val;               /**< The named value. */
+        }
+        hardware_module_name;
     }
     value;
 }
diff --git a/library/x509_crt.c b/library/x509_crt.c
index cce230bd2..9bc869652 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1668,8 +1668,6 @@ static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
     other_name->value.hardware_module_name.val.p = p;
     other_name->value.hardware_module_name.val.len = len;
-    other_name->value.hardware_module_name.next = NULL;
-    other_name->value.hardware_module_name.next_merged = 0;
     p += len;
     if( p != end )
     {

From cc45cd177f89883ff54f1c54bbfc8f03a7cf8ef6 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Wed, 15 May 2019 10:20:09 +0300
Subject: [PATCH 17/27] Update SAN parsing documentation

1) Fix typo in `mbedtls_x509_parse_subject_alt_name()` documentation.
2) Add a not in `mbedtls_x509_parse_subject_alt_name()` documentation,
stating that the lifetime of the target structure is restricted
by the lifetime ofthe parsed certificate.
---
 include/mbedtls/x509_crt.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 81a2de2be..a5deb95e0 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -410,11 +410,15 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
  *                 as defined in RFC 4180 is supported.
  *
  * \note           This function should be called on a single raw data of
- *                 subject alternative name. For example, after successfult
+ *                 subject alternative name. For example, after successful
  *                 certificate parsing, one must iterate on every item in the
  *                 \p crt->subject_alt_names sequence, and send it as parameter
  *                 to this function.
  *
+ * \note           The target structure contains pointers to the raw data of the
+ *                 parsed certificate, and its lifetime is restricted by the
+ *                 lifetime of the certificate.
+ *
  * \return         \c 0 on success
  * \return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
  *                 SAN type

From 8b0c3c91e63fee5d62c965f10cc35a760d5fea7f Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Wed, 15 May 2019 12:20:00 +0300
Subject: [PATCH 18/27] Fail in case critical crt policy not supported

In case the certificate policy is not of type `AnyPolicy`
set the returned error code to `MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE`
and continue parsing. If the extension is critical, return error anyway,
unless `MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION` is configured.
Fail parsing on any other error.
---
 library/x509_crt.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 9bc869652..3b68f01aa 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -743,7 +743,7 @@ static int x509_get_certificate_policies( unsigned char **p,
                                           const unsigned char *end,
                                           mbedtls_x509_sequence *certificate_policies )
 {
-    int ret;
+    int ret, parse_ret = 0;
     size_t len;
     mbedtls_asn1_buf *buf;
     mbedtls_asn1_sequence *cur = certificate_policies;
@@ -787,6 +787,19 @@ static int x509_get_certificate_policies( unsigned char **p,
         policy_oid.len = len;
         policy_oid.p = *p;
 
+        /*
+         * Only AnyPolicy is currently supported when enforcing policy.
+         */
+        if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 )
+        {
+            /*
+             * Set the parsing return code but continue parsing, in case this
+             * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+             * is configured.
+             */
+            parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+        }
+
         /* Allocate and assign next pointer */
         if( cur->buf.p != NULL )
         {
@@ -836,7 +849,7 @@ static int x509_get_certificate_policies( unsigned char **p,
         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
 
-    return( 0 );
+    return( parse_ret );
 }
 
 /*
@@ -970,7 +983,21 @@ static int x509_get_crt_ext( unsigned char **p,
             /* Parse certificate policies type */
             if( ( ret = x509_get_certificate_policies( p, end_ext_octet,
                     &crt->certificate_policies ) ) != 0 )
-                return( ret );
+            {
+#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+                if( is_critical )
+                    return( ret );
+                else
+#endif
+                /*
+                 * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, the we cannot
+                 * interpret or enforce the policy. However, it is up to the user
+                 * to choose how to enforce the policies,
+                 * unless the extension is critical.
+                 */
+                if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+                    return( ret );
+            }
             break;
 
         default:

From 2e06a9fb24871d3c5473f2a4f0b2e67eaca133e6 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Wed, 15 May 2019 15:14:46 +0300
Subject: [PATCH 19/27] Fix ChangeLog entry

Move the ChangeLog entries to correct location, and
mention sppecifically the support for hardware module name othername.
---
 ChangeLog | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f942ebbf5..f6763fc2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,12 @@ Features
      Contributed by Jack Lloyd and Fortanix Inc.
    * Add the Wi-SUN Field Area Network (FAN) device extended key usage.
    * Add the oid certificate policy x509 extension.
+   * Add support for parsing otherName entries in the Subject Alternative Name
+     X.509 certificate extension, specifically type hardware module name,
+     as defined in RFC 4108 section 5.
+   * Add support for parsing certificate policies extension, as defined in
+     RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is
+     supported.
 
 Bugfix
    * Fix private key DER output in the key_app_writer example. File contents
@@ -61,11 +67,6 @@ Features
    * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites
      from the default list (enabled by default). See
      https://sweet32.info/SWEET32_CCS16.pdf.
-   * Add support for parsing otherName entries in the Subject Alternative Name
-     X.509 certificate extension, as defined in RFC 4108 section 5.
-   * Add support for parsing certificate policies extension, as defined in
-     RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is
-     supported.
 
 API Changes
    * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.

From c8b5f3f520b97dc1580f09b2850012bda184de5d Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Wed, 15 May 2019 15:15:55 +0300
Subject: [PATCH 20/27] Documentation fixes

Rephrase documentation of the SAN to make it clearer.
---
 include/mbedtls/x509_crt.h | 18 +++++++++---------
 library/x509_crt.c         |  4 ++--
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index a5deb95e0..cd3be09e0 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -78,7 +78,7 @@ typedef struct mbedtls_x509_crt
     mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
     mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
 
-    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy supported). */
+    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */
 
     int ext_types;              /**< Bit string containing detected and parsed extensions */
     int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
@@ -398,31 +398,31 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
 
 #endif /* MBEDTLS_FS_IO */
 /**
- * \brief          Parses a subject alternative name item
- *                 to an identified structure;
+ * \brief          This function parses an item in the SubjectAlternativeNames
+ *                 extension.
  *
  * \param san_buf  The buffer holding the raw data item of the subject
  *                 alternative name.
  * \param san      The target structure to populate with the parsed presentation
  *                 of the subject alternative name encoded in \p san_raw.
  *
- * \note           Only "dnsName" and "otherName" of type hardware_module_name,
+ * \note           Only "dnsName" and "otherName" of type hardware_module_name
  *                 as defined in RFC 4180 is supported.
  *
  * \note           This function should be called on a single raw data of
  *                 subject alternative name. For example, after successful
  *                 certificate parsing, one must iterate on every item in the
- *                 \p crt->subject_alt_names sequence, and send it as parameter
- *                 to this function.
+ *                 \p crt->subject_alt_names sequence, and pass it to
+ *                 this function.
  *
- * \note           The target structure contains pointers to the raw data of the
+ * \warning        The target structure contains pointers to the raw data of the
  *                 parsed certificate, and its lifetime is restricted by the
  *                 lifetime of the certificate.
  *
  * \return         \c 0 on success
  * \return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
- *                 SAN type
- * \return         Negative value for any other failure.
+ *                 SAN type.
+ * \return         Another negative value for any other failure.
  */
 int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
                                          mbedtls_x509_subject_alternative_name *san );
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 3b68f01aa..701b0142d 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -618,8 +618,8 @@ static int x509_get_ext_key_usage( unsigned char **p,
  *      nameAssigner            [0]     DirectoryString OPTIONAL,
  *      partyName               [1]     DirectoryString }
  *
- * NOTE: we only parse and use dNSName at this point,
- * and otherName of type HwModuleName, as defined in RFC 4108.
+ * NOTE: we list all types, but only use dNSName and otherName
+ * of type HwModuleName, as defined in RFC 4108, at this point.
  */
 static int x509_get_subject_alt_name( unsigned char **p,
                                       const unsigned char *end,

From dbbd96652ceff314a45f23be40b3820dbd540347 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Wed, 15 May 2019 15:46:03 +0300
Subject: [PATCH 21/27] Check that SAN is not malformed when parsing

Add a call to `mbedtls_x509_parse_subject_alt_name()` during
certificate parsing, to verify the certificate is not malformed.
---
 library/x509_crt.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 701b0142d..754a65fdf 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -642,6 +642,9 @@ static int x509_get_subject_alt_name( unsigned char **p,
 
     while( *p < end )
     {
+        mbedtls_x509_subject_alternative_name dummy_san_buf;
+        memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) );
+
         if( ( end - *p ) < 1 )
             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
                     MBEDTLS_ERR_ASN1_OUT_OF_DATA );
@@ -658,6 +661,29 @@ static int x509_get_subject_alt_name( unsigned char **p,
                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
         }
 
+        /*
+         * Check that the SAN are structured correct.
+         */
+        ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf );
+        /*
+         * In case the extension is malformed, return an error,
+         * and clear the allocated sequences.
+         */
+        if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+        {
+            mbedtls_x509_sequence *seq_cur = subject_alt_name->next;
+            mbedtls_x509_sequence *seq_prv;
+            while( seq_cur != NULL )
+            {
+                seq_prv = seq_cur;
+                seq_cur = seq_cur->next;
+                mbedtls_platform_zeroize( seq_prv,
+                                          sizeof( mbedtls_x509_sequence ) );
+                mbedtls_free( seq_prv );
+            }
+            return( ret );
+        }
+
         /* Allocate and assign next pointer */
         if( cur->buf.p != NULL )
         {

From e269537b807ce066cc31fe10f5c8d975f19c8362 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Thu, 16 May 2019 11:52:57 +0300
Subject: [PATCH 22/27] Add ChangeLog entry about listing all SAN

Add a ChangeLog entry that indicates that all SAN types are
now listed in the corresponding certificate field.
---
 ChangeLog | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index f6763fc2c..959904a33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,8 @@ Features
    * Add support for parsing certificate policies extension, as defined in
      RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is
      supported.
+   * List all SAN types in the subject_alt_names field of the certificate.
+     Resolves #459.
 
 Bugfix
    * Fix private key DER output in the key_app_writer example. File contents

From a29139177596aab29ea605c1f7e4fe482e63c343 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Thu, 16 May 2019 16:17:38 +0300
Subject: [PATCH 23/27] Fix minor issues

1. Typo fix.
2. Change byte by byte coipy to `memcpy`.
3. Remove parenthesis in switch cases.
---
 library/x509_crt.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 754a65fdf..8200374cd 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1016,9 +1016,9 @@ static int x509_get_crt_ext( unsigned char **p,
                 else
 #endif
                 /*
-                 * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, the we cannot
-                 * interpret or enforce the policy. However, it is up to the user
-                 * to choose how to enforce the policies,
+                 * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
+                 * cannot interpret or enforce the policy. However, it is up to
+                 * the user to choose how to enforce the policies,
                  * unless the extension is critical.
                  */
                 if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
@@ -1737,7 +1737,6 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
                                                     *subject_alt_name,
                                        const char *prefix )
 {
-    size_t i;
     int ret;
     size_t n = *size;
     char *p = *buf;
@@ -1770,7 +1769,7 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
             /*
              * otherName
              */
-            case( MBEDTLS_X509_SAN_OTHER_NAME ):
+            case MBEDTLS_X509_SAN_OTHER_NAME:
             {
                 mbedtls_x509_san_other_name *other_name = &san.san.other_name;
 
@@ -1797,10 +1796,10 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
                         return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
                     }
 
-                    for( i = 0; i < other_name->value.hardware_module_name.val.len; i++ )
-                    {
-                        *p++ = other_name->value.hardware_module_name.val.p[i];
-                    }
+                    memcpy( p, other_name->value.hardware_module_name.val.p,
+                            other_name->value.hardware_module_name.val.len );
+                    p += other_name->value.hardware_module_name.val.len;
+
                     n -= other_name->value.hardware_module_name.val.len;
 
                 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
@@ -1810,7 +1809,7 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
             /*
              * dNSName
              */
-            case( MBEDTLS_X509_SAN_DNS_NAME ):
+            case MBEDTLS_X509_SAN_DNS_NAME:
             {
                 ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
                 MBEDTLS_X509_SAFE_SNPRINTF;
@@ -1819,9 +1818,10 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
                     *p = '\0';
                     return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
                 }
+
+                memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len );
+                p += san.san.unstructured_name.len;
                 n -= san.san.unstructured_name.len;
-                for( i = 0; i < san.san.unstructured_name.len; i++ )
-                    *p++ = san.san.unstructured_name.p[i];
             }
             break;
 

From 11818f2c172c995d072760c0eb5b77327dc78c52 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Thu, 16 May 2019 18:17:02 +0300
Subject: [PATCH 24/27] Add some negative test cases

Add some invalid certificate tests for certifiate policies extension.
---
 tests/suites/test_suite_x509parse.data | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 99dd0833f..e331d6184 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1198,6 +1198,18 @@ X509 Certificate ASN1 (TBSCertificate v3, first ext invalid tag)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
 x509parse_crt:"30819030818da0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba3043002310000":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
+X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, bool len missing)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d2001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data missing)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d20042801010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data not oid)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a302a0603551d200101FF0420301EA01C06082B06010505070804A010300E06082B060104010901030402022201010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, bool len missing)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
 x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d1301010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA

From 8a59d6b964add89108482c8235980cbdc23fd042 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Sun, 19 May 2019 12:32:15 +0300
Subject: [PATCH 25/27] Update test data

Update the test data for the negative certificate policies
extension tests with correct lengths, to test the correct behaviour.
Add another test.
---
 tests/suites/test_suite_x509parse.data | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index e331d6184..e0ab4050b 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1200,15 +1200,19 @@ x509parse_crt:"30819030818da0030201028204deadbeef300d06092a864886f70d01010205003
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, bool len missing)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d2001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300730050603551d2001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data missing)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d20042801010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30080603551d2004010001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data not oid)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a302a0603551d200101FF0420301EA01C06082B06010505070804A010300E06082B060104010901030402022201010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30270603551d200420301EA01C06082B06010505070804A010300E06082B060104010901030402022201010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, qualifier not complete)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a301F0603551d2004183020301F0603551D200418301630140604551D2000300C300A06082B0601050507020101010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, bool len missing)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C

From 76a9c4a81fd61c48a7551b505623b5e5662a4eb5 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 20 May 2019 11:58:59 +0300
Subject: [PATCH 26/27] Fix test data

Fix test data to test what it actually intends to test.
---
 tests/suites/test_suite_x509parse.data | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index e0ab4050b..ab3880a05 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1204,11 +1204,11 @@ x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d01010205003
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data missing)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30080603551d2004010001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30b300930070603551d20040001010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, data not oid)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C
-x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30270603551d200420301EA01C06082B06010505070804A010300E06082B060104010901030402022201010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"3081bc3081b9a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba32e302c30290603551d2004223020301EA01C06082B06010505070804A010300E06082B060104010901030402022201010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext CertificatePolicies tag, qualifier not complete)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD2_C

From 6aeae9e962b665c826fc349538eb61b90c1f69c0 Mon Sep 17 00:00:00 2001
From: Ron Eldor <Ron.Eldor@arm.com>
Date: Mon, 20 May 2019 12:00:36 +0300
Subject: [PATCH 27/27] Style fix

Add whitespace before parenthesis.
---
 library/x509_crt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/x509_crt.c b/library/x509_crt.c
index 8200374cd..708dbf771 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -2115,7 +2115,7 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
 
         if( ( ret = x509_info_subject_alt_name( &p, &n,
                                                 &crt->subject_alt_names,
-                                                prefix) ) != 0 )
+                                                prefix ) ) != 0 )
             return( ret );
     }