Merge remote-tracking branch 'origin/pr/2410' into development

* origin/pr/2410:
  Update change log
  Document the default value for the maximum fragment length
  Improve clarity of mbedtls_ssl_conf_max_frag_len documentation
  Reword ssl_conf_max_frag_len documentation
  Fix typos and miswording in the mbedtls_ssl_conf_max_frag_len documentation comment
  Reword ssl_conf_max_frag_len documentation to clarify its necessity
diff --git a/.gitignore b/.gitignore
index f40064d..789f57e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,20 @@
+# Random seed file created by test scripts and sample programs
+seedfile
+
+# CMake build artifacts:
 CMakeCache.txt
 CMakeFiles
 CTestTestfile.cmake
 cmake_install.cmake
 Testing
+# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those:
+*.dir/
+# MSVC files generated by CMake:
+/*.sln
+/*.vcxproj
+/*.filters
+
+# Test coverage build artifacts:
 Coverage
 *.gcno
 *.gcda
@@ -10,11 +22,6 @@
 # generated by scripts/memory.sh
 massif-*
 
-# MSVC files generated by CMake:
-/*.sln
-/*.vcxproj
-/*.filters
-
 # MSVC build artifacts:
 *.exe
 *.pdb
@@ -24,5 +31,13 @@
 # Python build artifacts:
 *.pyc
 
-# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those:
-*.dir/
+# Generated documentation:
+/apidoc
+
+# Editor navigation files:
+/GPATH
+/GRTAGS
+/GSYMS
+/GTAGS
+/TAGS
+/tags
diff --git a/.globalrc b/.globalrc
new file mode 100644
index 0000000..01b2ea5
--- /dev/null
+++ b/.globalrc
@@ -0,0 +1,3 @@
+default:\
+    :langmap=c\:.c.h.function:\
+
diff --git a/ChangeLog b/ChangeLog
index 813908c..3de7639 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,19 @@
      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.
+   * It is now possible to perform RSA PKCS v1.5 signatures with RIPEMD-160 digest.
+     Contributed by Jack Lloyd and Fortanix Inc.
+   * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes,
+     and the used tls-prf.
+   * Add public API for tls-prf function, according to requested enum.
+   * 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.
+   * 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
@@ -34,6 +47,11 @@
    * Add a check for MBEDTLS_X509_CRL_PARSE_C in ssl_server2, guarding the crl
      sni entry parameter. Reported by inestlerode in #560.
 
+API Changes
+   * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes,
+     and the used tls-prf.
+   * Add public API for tls-prf function, according to requested enum.
+
 Changes
    * Server's RSA certificate in certs.c was SHA-1 signed. In the default
      mbedTLS configuration only SHA-2 signed certificates are accepted.
diff --git a/Makefile b/Makefile
index a5b8b61..3833185 100644
--- a/Makefile
+++ b/Makefile
@@ -138,3 +138,12 @@
 apidoc_clean:
 	rm -rf apidoc
 endif
+
+## Editor navigation files
+C_SOURCE_FILES = $(wildcard include/*/*.h library/*.[hc] programs/*/*.[hc] tests/suites/*.function)
+tags: $(C_SOURCE_FILES)
+	ctags -o $@ $(C_SOURCE_FILES)
+TAGS: $(C_SOURCE_FILES)
+	etags -o $@ $(C_SOURCE_FILES)
+GPATH GRTAGS GSYMS GTAGS: $(C_SOURCE_FILES)
+	ls $(C_SOURCE_FILES) | gtags -f - --gtagsconf .globalrc
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 55f72c8..17cdba7 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -212,7 +212,10 @@
  * { 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 } */
 
 /*
  * PKCS definition OIDs
@@ -259,6 +262,8 @@
 
 #define MBEDTLS_OID_DIGEST_ALG_SHA512           MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
 
+#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160        MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */
+
 #define MBEDTLS_OID_HMAC_SHA1                   MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
 
 #define MBEDTLS_OID_HMAC_SHA224                 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 4b48302..208b6c6 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -450,6 +450,18 @@
 }
 mbedtls_ssl_states;
 
+/*
+ * The tls_prf function types.
+ */
+typedef enum
+{
+   MBEDTLS_SSL_TLS_PRF_NONE,
+   MBEDTLS_SSL_TLS_PRF_SSL3,
+   MBEDTLS_SSL_TLS_PRF_TLS1,
+   MBEDTLS_SSL_TLS_PRF_SHA384,
+   MBEDTLS_SSL_TLS_PRF_SHA256
+}
+mbedtls_tls_prf_types;
 /**
  * \brief          Callback type: send data on the network.
  *
@@ -920,6 +932,11 @@
     /** Callback to export key block and master secret                      */
     int (*f_export_keys)( void *, const unsigned char *,
             const unsigned char *, size_t, size_t, size_t );
+    /** Callback to export key block, master secret,
+     *  tls_prf and random bytes. Should replace f_export_keys    */
+    int (*f_export_keys_ext)( void *, const unsigned char *,
+                const unsigned char *, size_t, size_t, size_t,
+                unsigned char[32], unsigned char[32], mbedtls_tls_prf_types );
     void *p_export_keys;            /*!< context for key export callback    */
 #endif
 
@@ -1624,6 +1641,41 @@
                                 size_t maclen,
                                 size_t keylen,
                                 size_t ivlen );
+
+/**
+ * \brief           Callback type: Export key block, master secret,
+ *                                 handshake randbytes and the tls_prf function
+ *                                 used to derive keys.
+ *
+ * \note            This is required for certain uses of TLS, e.g. EAP-TLS
+ *                  (RFC 5216) and Thread. The key pointers are ephemeral and
+ *                  therefore must not be stored. The master secret and keys
+ *                  should not be used directly except as an input to a key
+ *                  derivation function.
+ *
+ * \param p_expkey  Context for the callback.
+ * \param ms        Pointer to master secret (fixed length: 48 bytes).
+ * \param kb            Pointer to key block, see RFC 5246 section 6.3.
+ *                      (variable length: 2 * maclen + 2 * keylen + 2 * ivlen).
+ * \param maclen        MAC length.
+ * \param keylen        Key length.
+ * \param ivlen         IV length.
+ * \param client_random The client random bytes.
+ * \param server_random The server random bytes.
+ * \param tls_prf_type The tls_prf enum type.
+ *
+ * \return          0 if successful, or
+ *                  a specific MBEDTLS_ERR_XXX code.
+ */
+typedef int mbedtls_ssl_export_keys_ext_t( void *p_expkey,
+                                           const unsigned char *ms,
+                                           const unsigned char *kb,
+                                           size_t maclen,
+                                           size_t keylen,
+                                           size_t ivlen,
+                                           unsigned char client_random[32],
+                                           unsigned char server_random[32],
+                                           mbedtls_tls_prf_types tls_prf_type );
 #endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 /**
@@ -1689,6 +1741,20 @@
 void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
         mbedtls_ssl_export_keys_t *f_export_keys,
         void *p_export_keys );
+
+/**
+ * \brief           Configure extended key export callback.
+ *                  (Default: none.)
+ *
+ * \note            See \c mbedtls_ssl_export_keys_ext_t.
+ *
+ * \param conf      SSL configuration context
+ * \param f_export_keys_ext Callback for exporting keys
+ * \param p_export_keys     Context for the callback
+ */
+void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf,
+        mbedtls_ssl_export_keys_ext_t *f_export_keys_ext,
+        void *p_export_keys );
 #endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
@@ -3493,6 +3559,27 @@
  */
 void mbedtls_ssl_session_free( mbedtls_ssl_session *session );
 
+/**
+ * \brief          TLS-PRF function for key derivation.
+ *
+ * \param prf      The tls_prf type funtion type to be used.
+ * \param secret   Secret for the key derivation function.
+ * \param slen     Length of the secret.
+ * \param label    String label for the key derivation function,
+ *                 terminated with null character.
+ * \param random   Random bytes.
+ * \param rlen     Length of the random bytes buffer.
+ * \param dstbuf   The buffer holding the derived key.
+ * \param dlen     Length of the output buffer.
+ *
+ * \return         0 on sucess. An SSL specific error on failure.
+ */
+int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
+                          const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index ac4d96d..9c4be53 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -276,6 +276,10 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
           MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
 
+typedef int  mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen,
+                                     const char *label,
+                                     const unsigned char *random, size_t rlen,
+                                     unsigned char *dstbuf, size_t dlen );
 /*
  * This structure contains the parameters only needed during handshake.
  */
@@ -425,9 +429,7 @@
     void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
     void (*calc_verify)(mbedtls_ssl_context *, unsigned char *);
     void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
-    int  (*tls_prf)(const unsigned char *, size_t, const char *,
-                    const unsigned char *, size_t,
-                    unsigned char *, size_t);
+    mbedtls_ssl_tls_prf_cb *tls_prf;
 
     mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
 
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index b63e864..054ff2e 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -110,6 +110,28 @@
 /* \} 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 a0f32cb..cd3be09 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -76,7 +76,9 @@
     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 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 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. */
@@ -98,6 +100,53 @@
 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
+{
+    /**
+     * 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
+    {
+        /**
+         * From RFC 4108 section 5:
+         * HardwareModuleName ::= SEQUENCE {
+         *                         hwType OBJECT IDENTIFIER,
+         *                         hwSerialNum OCTET STRING }
+         */
+        struct
+        {
+            mbedtls_x509_buf oid;               /**< The object identifier. */
+            mbedtls_x509_buf val;               /**< The named value. */
+        }
+        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 */
+}
+mbedtls_x509_subject_alternative_name;
+
+/**
  * Build flag from an algorithm/curve identifier (pk, md, ecp)
  * Since 0 is always XXX_NONE, ignore it.
  */
@@ -346,8 +395,37 @@
  *                 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 */
 
+#endif /* MBEDTLS_FS_IO */
+/**
+ * \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
+ *                 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 pass it to
+ *                 this function.
+ *
+ * \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         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 );
 /**
  * \brief          Returns an informational string about the
  *                 certificate.
diff --git a/library/oid.c b/library/oid.c
index 9f40941..27c455e 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -627,6 +627,12 @@
         MBEDTLS_MD_SHA512,
     },
 #endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_RIPEMD160_C)
+    {
+        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ),       "id-ripemd160",       "RIPEMD-160" },
+        MBEDTLS_MD_RIPEMD160,
+    },
+#endif /* MBEDTLS_RIPEMD160_C */
     {
         { NULL, 0, NULL, NULL },
         MBEDTLS_MD_NONE,
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index da42ed7..d25dffd 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -425,7 +425,8 @@
     size_t nb, hs;
     size_t i, j, k;
     const unsigned char *S1, *S2;
-    unsigned char tmp[128];
+    unsigned char *tmp;
+    size_t tmp_len = 0;
     unsigned char h_i[20];
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
@@ -433,8 +434,13 @@
 
     mbedtls_md_init( &md_ctx );
 
-    if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    tmp_len = 20 + strlen( label ) + rlen;
+    tmp = mbedtls_calloc( 1, tmp_len );
+    if( tmp == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
 
     hs = ( slen + 1 ) / 2;
     S1 = secret;
@@ -449,10 +455,15 @@
      * First compute P_md5(secret,label+random)[0..dlen]
      */
     if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    {
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto exit;
+    }
 
     if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-        return( ret );
+    {
+        goto exit;
+    }
 
     mbedtls_md_hmac_starts( &md_ctx, S1, hs );
     mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
@@ -480,10 +491,15 @@
      * XOR out with P_sha1(secret,label+random)[0..dlen]
      */
     if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    {
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto exit;
+    }
 
     if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-        return( ret );
+    {
+        goto exit;
+    }
 
     mbedtls_md_hmac_starts( &md_ctx, S2, hs );
     mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
@@ -505,12 +521,14 @@
             dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
     }
 
+exit:
     mbedtls_md_free( &md_ctx );
 
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( tmp, tmp_len );
     mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
 
-    return( 0 );
+    mbedtls_free( tmp );
+    return( ret );
 }
 #endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */
 
@@ -593,7 +611,8 @@
 {
     size_t nb;
     size_t i, j, k, md_len;
-    unsigned char tmp[128];
+    unsigned char *tmp;
+    size_t tmp_len = 0;
     unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
@@ -606,8 +625,13 @@
 
     md_len = mbedtls_md_get_size( md_info );
 
-    if( sizeof( tmp ) < md_len + strlen( label ) + rlen )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    tmp_len = md_len + strlen( label ) + rlen;
+    tmp = mbedtls_calloc( 1, tmp_len );
+    if( tmp == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
 
     nb = strlen( label );
     memcpy( tmp + md_len, label, nb );
@@ -618,7 +642,7 @@
      * Compute P_<hash>(secret, label + random)[0..dlen]
      */
     if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-        return( ret );
+        goto exit;
 
     mbedtls_md_hmac_starts( &md_ctx, secret, slen );
     mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb );
@@ -640,12 +664,15 @@
             dstbuf[i + j]  = h_i[j];
     }
 
+exit:
     mbedtls_md_free( &md_ctx );
 
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( tmp, tmp_len );
     mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
 
-    return( 0 );
+    mbedtls_free( tmp );
+
+    return( ret );
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_SHA256_C)
@@ -724,6 +751,83 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
           MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf )
+{
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+    if( tls_prf == ssl3_prf )
+    {
+        return( MBEDTLS_SSL_TLS_PRF_SSL3 );
+    }
+    else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+    if( tls_prf == tls1_prf )
+    {
+        return( MBEDTLS_SSL_TLS_PRF_TLS1 );
+    }
+    else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SHA512_C)
+    if( tls_prf == tls_prf_sha384 )
+    {
+        return( MBEDTLS_SSL_TLS_PRF_SHA384 );
+    }
+    else
+#endif
+#if defined(MBEDTLS_SHA256_C)
+    if( tls_prf == tls_prf_sha256 )
+    {
+        return( MBEDTLS_SSL_TLS_PRF_SHA256 );
+    }
+    else
+#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    return( MBEDTLS_SSL_TLS_PRF_NONE );
+}
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
+int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
+                          const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen )
+{
+    mbedtls_ssl_tls_prf_cb *tls_prf = NULL;
+
+    switch( prf )
+    {
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+        case MBEDTLS_SSL_TLS_PRF_SSL3:
+            tls_prf = ssl3_prf;
+        break;
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+        case MBEDTLS_SSL_TLS_PRF_TLS1:
+            tls_prf = tls1_prf;
+        break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_SSL_TLS_PRF_SHA384:
+            tls_prf = tls_prf_sha384;
+        break;
+#endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_SSL_TLS_PRF_SHA256:
+            tls_prf = tls_prf_sha256;
+        break;
+#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    default:
+        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) );
+}
+
 int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
@@ -988,9 +1092,6 @@
     MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
     MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
 
-    mbedtls_platform_zeroize( handshake->randbytes,
-                              sizeof( handshake->randbytes ) );
-
     /*
      * Determine the appropriate key, IV and MAC length.
      */
@@ -1036,7 +1137,7 @@
             ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
-            return( ret );
+            goto end;
         }
 
         /* Get MAC length */
@@ -1106,7 +1207,8 @@
 #endif
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+                goto end;
             }
         }
     }
@@ -1168,7 +1270,8 @@
 #endif /* MBEDTLS_SSL_SRV_C */
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto end;
     }
 
 #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
@@ -1178,7 +1281,8 @@
         if( mac_key_len > sizeof( transform->mac_enc ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+            goto end;
         }
 
         memcpy( transform->mac_enc, mac_enc, mac_key_len );
@@ -1202,7 +1306,8 @@
 #endif
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto end;
     }
 #endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
 
@@ -1220,7 +1325,8 @@
                                         mac_key_len ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+            ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            goto end;
         }
     }
 #else
@@ -1236,6 +1342,17 @@
                                   mac_key_len, keylen,
                                   iv_copy_len );
     }
+
+    if( ssl->conf->f_export_keys_ext != NULL )
+    {
+        ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys,
+                                      session->master, keyblk,
+                                      mac_key_len, keylen,
+                                      iv_copy_len,
+                                      handshake->randbytes + 32,
+                                      handshake->randbytes,
+                                      tls_prf_get_type( handshake->tls_prf ) );
+    }
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -1253,7 +1370,7 @@
         if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            return( ret );
+            goto end;
         }
 
         if( ret == 0 )
@@ -1279,7 +1396,7 @@
                                  cipher_info ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
-        return( ret );
+        goto end;
     }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -1296,7 +1413,7 @@
         if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            return( ret );
+            goto end;
         }
 
         if( ret == 0 )
@@ -1322,7 +1439,7 @@
                                  cipher_info ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
-        return( ret );
+        goto end;
     }
 
     if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1,
@@ -1330,7 +1447,7 @@
                                MBEDTLS_ENCRYPT ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
-        return( ret );
+        goto end;
     }
 
     if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2,
@@ -1338,7 +1455,7 @@
                                MBEDTLS_DECRYPT ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
-        return( ret );
+        goto end;
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1348,19 +1465,18 @@
                                              MBEDTLS_PADDING_NONE ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
-            return( ret );
+            goto end;
         }
 
         if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec,
                                              MBEDTLS_PADDING_NONE ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
-            return( ret );
+            goto end;
         }
     }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-    mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     // Initialize compression
@@ -1375,7 +1491,8 @@
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
                                     MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
-                return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+                ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+                goto end;
             }
         }
 
@@ -1389,14 +1506,18 @@
             inflateInit( &transform->ctx_inflate ) != Z_OK )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
-            return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
+            ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED;
+            goto end;
         }
     }
 #endif /* MBEDTLS_ZLIB_SUPPORT */
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
-
-    return( 0 );
+end:
+    mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
+    mbedtls_platform_zeroize( handshake->randbytes,
+                              sizeof( handshake->randbytes ) );
+    return( ret );
 }
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
@@ -8620,6 +8741,14 @@
     conf->f_export_keys = f_export_keys;
     conf->p_export_keys = p_export_keys;
 }
+
+void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf,
+        mbedtls_ssl_export_keys_ext_t *f_export_keys_ext,
+        void *p_export_keys )
+{
+    conf->f_export_keys_ext = f_export_keys_ext;
+    conf->p_export_keys = p_export_keys;
+}
 #endif
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 97a06d5..708dbf7 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -618,7 +618,8 @@
  *      nameAssigner            [0]     DirectoryString OPTIONAL,
  *      partyName               [1]     DirectoryString }
  *
- * NOTE: we only parse and use dNSName at this point.
+ * 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,
@@ -641,6 +642,9 @@
 
     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 );
@@ -657,11 +661,27 @@
                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
         }
 
-        /* Skip everything but DNS name */
-        if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
+        /*
+         * 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 )
         {
-            *p += tag_len;
-            continue;
+            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 */
@@ -697,6 +717,168 @@
 }
 
 /*
+ * 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, parse_ret = 0;
+    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, policy_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;
+
+        /*
+         * 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 )
+        {
+            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;
+
+        *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 */
+    cur->next = NULL;
+
+    if( *p != end )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( parse_ret );
+}
+
+/*
  * X.509 v3 extensions
  *
  */
@@ -823,6 +1005,27 @@
                 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 )
+            {
+#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+                if( is_critical )
+                    return( ret );
+                else
+#endif
+                /*
+                 * 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 )
+                    return( ret );
+            }
+            break;
+
         default:
             /*
              * If this is a non-critical extension, which the oid layer
@@ -1435,32 +1638,201 @@
 }
 #endif /* MBEDTLS_FS_IO */
 
-static int x509_info_subject_alt_name( char **buf, size_t *size,
-                                       const mbedtls_x509_sequence *subject_alt_name )
+/*
+ * 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 )
 {
-    size_t i;
+    int ret = 0;
+    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;
+    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 char *prefix )
+{
+    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;
+    mbedtls_x509_subject_alternative_name san;
+    int parse_ret;
 
     while( cur != NULL )
     {
-        if( cur->buf.len + sep_len >= n )
+        memset( &san, 0, sizeof( san ) );
+        parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
+        if( parse_ret != 0 )
         {
-            *p = '\0';
-            return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+            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;
         }
 
-        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];
+        switch( san.type )
+        {
+            /*
+             * otherName
+             */
+            case MBEDTLS_X509_SAN_OTHER_NAME:
+            {
+                mbedtls_x509_san_other_name *other_name = &san.san.other_name;
 
-        sep = ", ";
-        sep_len = 2;
+                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 );
+                    }
+
+                    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 */
+            }
+            break;
+
+            /*
+             * dNSName
+             */
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            {
+                ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                if( san.san.unstructured_name.len >= n )
+                {
+                    *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;
+            }
+            break;
+
+            /*
+             * Type not supported, skip item.
+             */
+            default:
+                ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                break;
+        }
 
         cur = cur->next;
     }
@@ -1473,6 +1845,56 @@
     return( 0 );
 }
 
+int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
+                                         mbedtls_x509_subject_alternative_name *san )
+{
+    int ret;
+    switch( san_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( 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;
+
+        /*
+         * dNSName
+         */
+        case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+        {
+            memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+            san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+            memcpy( &san->san.unstructured_name,
+                    san_buf, sizeof( *san_buf ) );
+
+        }
+        break;
+
+        /*
+         * Type not supported
+         */
+        default:
+            return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+    }
+    return( 0 );
+}
+
 #define PRINT_ITEM(i)                           \
     {                                           \
         ret = mbedtls_snprintf( p, n, "%s" i, sep );    \
@@ -1564,6 +1986,35 @@
     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.
  */
@@ -1659,11 +2110,12 @@
 
     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 );
     }
 
@@ -1695,6 +2147,16 @@
             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;
 
@@ -2821,6 +3283,16 @@
             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/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 2cddfb4..62f2c57 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -126,7 +126,7 @@
 #define DFL_EXTENDED_MS         -1
 #define DFL_ETM                 -1
 #define DFL_CA_CALLBACK         0
-
+#define DFL_EAP_TLS             0
 
 #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
 #define GET_REQUEST_END "\r\n\r\n"
@@ -204,6 +204,13 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+#define USAGE_EAP_TLS                                       \
+    "    eap_tls=%%d          default: 0 (disabled)\n"
+#else
+#define USAGE_EAP_TLS ""
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
 #define USAGE_TRUNC_HMAC                                    \
     "    trunc_hmac=%%d       default: library default\n"
@@ -348,6 +355,7 @@
     "    reco_delay=%%d       default: 0 seconds\n"         \
     "    reconnect_hard=%%d   default: 0 (disabled)\n"      \
     USAGE_TICKETS                                           \
+    USAGE_EAP_TLS                                           \
     USAGE_MAX_FRAG_LEN                                      \
     USAGE_TRUNC_HMAC                                        \
     USAGE_CONTEXT_CRT_CB                                    \
@@ -448,10 +456,47 @@
     int extended_ms;            /* negotiate extended master secret?        */
     int etm;                    /* negotiate encrypt then mac?              */
     int context_crt_cb;         /* use context-specific CRT verify callback */
+    int eap_tls;                /* derive EAP-TLS keying material?          */
 } opt;
 
 int query_config( const char *config );
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+typedef struct eap_tls_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} eap_tls_keys;
+
+static int eap_tls_key_derivation ( void *p_expkey,
+                                    const unsigned char *ms,
+                                    const unsigned char *kb,
+                                    size_t maclen,
+                                    size_t keylen,
+                                    size_t ivlen,
+                                    unsigned char client_random[32],
+                                    unsigned char server_random[32],
+                                    mbedtls_tls_prf_types tls_prf_type )
+{
+    eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf("exported maclen is %u\n", (unsigned)maclen);
+        mbedtls_printf("exported keylen is %u\n", (unsigned)keylen);
+        mbedtls_printf("exported ivlen is %u\n", (unsigned)ivlen);
+    }
+    return( 0 );
+}
+#endif
+
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
                       const char *str )
@@ -713,6 +758,12 @@
 #endif
     char *p, *q;
     const int *list;
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    unsigned char eap_tls_keymaterial[16];
+    unsigned char eap_tls_iv[8];
+    const char* eap_tls_label = "client EAP encryption";
+    eap_tls_keys eap_tls_keying;
+#endif
 
     /*
      * Make sure memory references are valid.
@@ -818,6 +869,7 @@
     opt.extended_ms         = DFL_EXTENDED_MS;
     opt.etm                 = DFL_ETM;
     opt.dgram_packing       = DFL_DGRAM_PACKING;
+    opt.eap_tls             = DFL_EAP_TLS;
 
     for( i = 1; i < argc; i++ )
     {
@@ -1176,6 +1228,12 @@
         {
             return query_config( q );
         }
+        else if( strcmp( p, "eap_tls" ) == 0 )
+        {
+            opt.eap_tls = atoi( q );
+            if( opt.eap_tls < 0 || opt.eap_tls > 1 )
+                goto usage;
+        }
         else
             goto usage;
     }
@@ -1652,6 +1710,12 @@
         mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm );
 #endif
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    if( opt.eap_tls != 0 )
+        mbedtls_ssl_conf_export_keys_ext_cb( &conf, eap_tls_key_derivation,
+                                             &eap_tls_keying );
+#endif
+
 #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
     if( opt.recsplit != DFL_RECSPLIT )
         mbedtls_ssl_conf_cbc_record_splitting( &conf, opt.recsplit
@@ -1917,6 +1981,57 @@
     }
 #endif
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    if( opt.eap_tls != 0  )
+    {
+        size_t j = 0;
+
+        if( ( ret = mbedtls_ssl_tls_prf( eap_tls_keying.tls_prf_type,
+                                         eap_tls_keying.master_secret,
+                                         sizeof( eap_tls_keying.master_secret ),
+                                         eap_tls_label,
+                                         eap_tls_keying.randbytes,
+                                         sizeof( eap_tls_keying.randbytes ),
+                                         eap_tls_keymaterial,
+                                         sizeof( eap_tls_keymaterial ) ) )
+                                         != 0 )
+        {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                            -ret );
+            goto exit;
+        }
+
+        mbedtls_printf( "    EAP-TLS key material is:" );
+        for( j = 0; j < sizeof( eap_tls_keymaterial ); j++ )
+        {
+            if( j % 8 == 0 )
+                mbedtls_printf("\n    ");
+            mbedtls_printf("%02x ", eap_tls_keymaterial[j] );
+        }
+        mbedtls_printf("\n");
+
+        if( ( ret = mbedtls_ssl_tls_prf( eap_tls_keying.tls_prf_type, NULL, 0,
+                                         eap_tls_label,
+                                         eap_tls_keying.randbytes,
+                                         sizeof( eap_tls_keying.randbytes ),
+                                         eap_tls_iv,
+                                         sizeof( eap_tls_iv ) ) ) != 0 )
+         {
+             mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                             -ret );
+             goto exit;
+         }
+
+        mbedtls_printf( "    EAP-TLS IV is:" );
+        for( j = 0; j < sizeof( eap_tls_iv ); j++ )
+        {
+            if( j % 8 == 0 )
+                mbedtls_printf("\n    ");
+            mbedtls_printf("%02x ", eap_tls_iv[j] );
+        }
+        mbedtls_printf("\n");
+    }
+#endif
     if( opt.reconnect != 0 )
     {
         mbedtls_printf("  . Saving session for reuse..." );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 5ee90ac..807f880 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -168,6 +168,7 @@
 #define DFL_EXTENDED_MS         -1
 #define DFL_ETM                 -1
 #define DFL_CA_CALLBACK         0
+#define DFL_EAP_TLS             0
 
 #define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
     "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n"  \
@@ -281,6 +282,13 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+#define USAGE_EAP_TLS                                       \
+    "    eap_tls=%%d          default: 0 (disabled)\n"
+#else
+#define USAGE_EAP_TLS ""
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
 #if defined(MBEDTLS_SSL_CACHE_C)
 #define USAGE_CACHE                                             \
     "    cache_max=%%d        default: cache default (50)\n"    \
@@ -442,6 +450,7 @@
     "    exchanges=%%d        default: 1\n"                 \
     "\n"                                                    \
     USAGE_TICKETS                                           \
+    USAGE_EAP_TLS                                           \
     USAGE_CACHE                                             \
     USAGE_MAX_FRAG_LEN                                      \
     USAGE_TRUNC_HMAC                                        \
@@ -563,10 +572,47 @@
     int dtls_mtu;               /* UDP Maximum tranport unit for DTLS       */
     int dgram_packing;          /* allow/forbid datagram packing            */
     int badmac_limit;           /* Limit of records with bad MAC            */
+    int eap_tls;                /* derive EAP-TLS keying material?          */
 } opt;
 
 int query_config( const char *config );
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+typedef struct eap_tls_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} eap_tls_keys;
+
+static int eap_tls_key_derivation ( void *p_expkey,
+                                    const unsigned char *ms,
+                                    const unsigned char *kb,
+                                    size_t maclen,
+                                    size_t keylen,
+                                    size_t ivlen,
+                                    unsigned char client_random[32],
+                                    unsigned char server_random[32],
+                                    mbedtls_tls_prf_types tls_prf_type )
+{
+    eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf("exported maclen is %u\n", (unsigned)maclen);
+        mbedtls_printf("exported keylen is %u\n", (unsigned)keylen);
+        mbedtls_printf("exported ivlen is %u\n", (unsigned)ivlen);
+    }
+    return( 0 );
+}
+#endif
+
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
                       const char *str )
@@ -1444,6 +1490,12 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status;
 #endif
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    unsigned char eap_tls_keymaterial[16];
+    unsigned char eap_tls_iv[8];
+    const char* eap_tls_label = "client EAP encryption";
+    eap_tls_keys eap_tls_keying;
+#endif
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1585,6 +1637,7 @@
     opt.badmac_limit        = DFL_BADMAC_LIMIT;
     opt.extended_ms         = DFL_EXTENDED_MS;
     opt.etm                 = DFL_ETM;
+    opt.eap_tls             = DFL_EAP_TLS;
 
     for( i = 1; i < argc; i++ )
     {
@@ -1975,6 +2028,12 @@
         {
             return query_config( q );
         }
+        else if( strcmp( p, "eap_tls" ) == 0 )
+        {
+            opt.eap_tls = atoi( q );
+            if( opt.eap_tls < 0 || opt.eap_tls > 1 )
+                goto usage;
+        }
         else
             goto usage;
     }
@@ -2537,6 +2596,12 @@
         mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm );
 #endif
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    if( opt.eap_tls != 0 )
+        mbedtls_ssl_conf_export_keys_ext_cb( &conf, eap_tls_key_derivation,
+                                             &eap_tls_keying );
+#endif
+
 #if defined(MBEDTLS_SSL_ALPN)
     if( opt.alpn_string != NULL )
         if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 )
@@ -3117,6 +3182,57 @@
     }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+    if( opt.eap_tls != 0 )
+    {
+        size_t j = 0;
+
+        if( ( ret = mbedtls_ssl_tls_prf( eap_tls_keying.tls_prf_type,
+                                         eap_tls_keying.master_secret,
+                                         sizeof( eap_tls_keying.master_secret ),
+                                         eap_tls_label,
+                                         eap_tls_keying.randbytes,
+                                         sizeof( eap_tls_keying.randbytes ),
+                                         eap_tls_keymaterial,
+                                         sizeof( eap_tls_keymaterial ) ) )
+                                         != 0 )
+        {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                            -ret );
+            goto exit;
+        }
+
+        mbedtls_printf( "    EAP-TLS key material is:" );
+        for( j = 0; j < sizeof( eap_tls_keymaterial ); j++ )
+        {
+            if( j % 8 == 0 )
+                mbedtls_printf("\n    ");
+            mbedtls_printf("%02x ", eap_tls_keymaterial[j] );
+        }
+        mbedtls_printf("\n");
+
+        if( ( ret = mbedtls_ssl_tls_prf( eap_tls_keying.tls_prf_type, NULL, 0,
+                                         eap_tls_label,
+                                         eap_tls_keying.randbytes,
+                                         sizeof( eap_tls_keying.randbytes ),
+                                         eap_tls_iv,
+                                         sizeof( eap_tls_iv ) ) ) != 0 )
+         {
+             mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                             -ret );
+             goto exit;
+         }
+
+        mbedtls_printf( "    EAP-TLS IV is:" );
+        for( j = 0; j < sizeof( eap_tls_iv ); j++ )
+        {
+            if( j % 8 == 0 )
+                mbedtls_printf("\n    ");
+            mbedtls_printf("%02x ", eap_tls_iv[j] );
+        }
+        mbedtls_printf("\n");
+    }
+#endif
     if( opt.exchanges == 0 )
         goto close_notify;
 
diff --git a/scripts/abi_check.py b/scripts/abi_check.py
index f837f7a..30c3fe5 100755
--- a/scripts/abi_check.py
+++ b/scripts/abi_check.py
@@ -148,7 +148,8 @@
         my_environment = os.environ.copy()
         my_environment["CFLAGS"] = "-g -Og"
         my_environment["SHARED"] = "1"
-        my_environment["USE_CRYPTO_SUBMODULE"] = "1"
+        if os.path.exists(os.path.join(git_worktree_path, "crypto")):
+            my_environment["USE_CRYPTO_SUBMODULE"] = "1"
         make_output = subprocess.check_output(
             [self.make_command, "lib"],
             env=my_environment,
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 748514d..d1af18c 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -77,6 +77,42 @@
 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) > $@
@@ -142,6 +178,15 @@
 	$(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 $@
+
+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/multiple_san.crt b/tests/data_files/multiple_san.crt
new file mode 100644
index 0000000..8cdc730
--- /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-fan.crt b/tests/data_files/server5-fan.crt
new file mode 100644
index 0000000..dc1eb38
--- /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/server5-othername.crt b/tests/data_files/server5-othername.crt
new file mode 100644
index 0000000..3be1a77
--- /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 0000000..b46fc2d
--- /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-any_policy.crt b/tests/data_files/test-ca-any_policy.crt
new file mode 100644
index 0000000..af87439
--- /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 0000000..821a92c
--- /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 0000000..a052bc6
--- /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 0000000..5e1491d
--- /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 0000000..168e99f
--- /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 0000000..70ea2eb
--- /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 0000000..bf47d95
--- /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 0000000..161e83c
--- /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 f66b39e..d2c5c06 100644
--- a/tests/data_files/test-ca.opensslconf
+++ b/tests/data_files/test-ca.opensslconf
@@ -12,6 +12,48 @@
 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
+
+[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"
+
+[fan_cert]
+extendedKeyUsage = 1.3.6.1.4.1.45605.1
+
 [noext_ca]
 basicConstraints = CA:true
 
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 08d4be3..cef87bc 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -7939,6 +7939,18 @@
             -s "Extra-header:" \
             -c "Extra-header:"
 
+requires_config_enabled MBEDTLS_SSL_EXPORT_KEYS
+run_test    "export keys functionality" \
+            "$P_SRV eap_tls=1 debug_level=3" \
+            "$P_CLI eap_tls=1 debug_level=3" \
+            0 \
+            -s "exported maclen is " \
+            -s "exported keylen is " \
+            -s "exported ivlen is "  \
+            -c "exported maclen is " \
+            -c "exported keylen is " \
+            -c "exported ivlen is "
+
 # Final report
 
 echo "------------------------------------------------------------------------"
diff --git a/tests/suites/test_suite_oid.data b/tests/suites/test_suite_oid.data
index 3d5d9db..3261935 100644
--- a/tests/suites/test_suite_oid.data
+++ b/tests/suites/test_suite_oid.data
@@ -57,3 +57,35 @@
 
 OID get x509 extension - wrong oid - id-ce
 oid_get_x509_extension:"551D":0
+
+OID hash id - id-md5
+depends_on:MBEDTLS_MD5_C
+oid_get_md_alg_id:"2A864886f70d0205":MBEDTLS_MD_MD5
+
+OID hash id - id-sha1
+depends_on:MBEDTLS_SHA1_C
+oid_get_md_alg_id:"2b0e03021a":MBEDTLS_MD_SHA1
+
+OID hash id - id-sha224
+depends_on:MBEDTLS_SHA256_C
+oid_get_md_alg_id:"608648016503040204":MBEDTLS_MD_SHA224
+
+OID hash id - id-sha256
+depends_on:MBEDTLS_SHA256_C
+oid_get_md_alg_id:"608648016503040201":MBEDTLS_MD_SHA256
+
+OID hash id - id-sha384
+depends_on:MBEDTLS_SHA512_C
+oid_get_md_alg_id:"608648016503040202":MBEDTLS_MD_SHA384
+
+OID hash id - id-sha512
+depends_on:MBEDTLS_SHA512_C
+oid_get_md_alg_id:"608648016503040203":MBEDTLS_MD_SHA512
+
+OID hash id - id-ripemd160
+depends_on:MBEDTLS_RIPEMD160_C
+oid_get_md_alg_id:"2b24030201":MBEDTLS_MD_RIPEMD160
+
+OID hash id - invalid oid
+oid_get_md_alg_id:"2B864886f70d0204":-1
+
diff --git a/tests/suites/test_suite_oid.function b/tests/suites/test_suite_oid.function
index cb8abe6..9e8d437 100644
--- a/tests/suites/test_suite_oid.function
+++ b/tests/suites/test_suite_oid.function
@@ -28,6 +28,7 @@
     }
     else
     {
+        TEST_ASSERT( ret == 0 );
         TEST_ASSERT( strcmp( ( char* )desc, result_str ) == 0 );
     }
 }
@@ -51,6 +52,7 @@
     }
     else
     {
+        TEST_ASSERT( ret == 0 );
         TEST_ASSERT( strcmp( ( char * )desc, result_str ) == 0 );
     }
 }
@@ -74,7 +76,34 @@
     }
     else
     {
+        TEST_ASSERT( ret == 0 );
         TEST_ASSERT( ext_type == exp_type );
     }
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void oid_get_md_alg_id( data_t *oid, int exp_md_id )
+{
+    mbedtls_asn1_buf md_oid = { 0, 0, NULL };
+    int ret;
+    mbedtls_md_type_t md_id = 0;
+
+    md_oid.tag = MBEDTLS_ASN1_OID;
+    md_oid.p = oid->x;
+    md_oid.len = oid->len;
+
+    ret = mbedtls_oid_get_md_alg( &md_oid, &md_id );
+
+    if( exp_md_id < 0 )
+    {
+        TEST_ASSERT( ret == MBEDTLS_ERR_OID_NOT_FOUND );
+        TEST_ASSERT( md_id == 0);
+    }
+    else
+    {
+        TEST_ASSERT( ret == 0 );
+        TEST_ASSERT( (mbedtls_md_type_t)exp_md_id == md_id );
+    }
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index 953b1ff..20789e6 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -258,6 +258,14 @@
 depends_on:MBEDTLS_PKCS1_V15
 mbedtls_rsa_pkcs1_verify:"59779fd2a39e56640c4fc1e67b60aeffcecd78aed7ad2bdfa464e93d04198d48466b8da7445f25bfa19db2844edd5c8f539cf772cc132b483169d390db28a43bc4ee0f038f6568ffc87447746cb72fefac2d6d90ee3143a915ac4688028805905a68eb8f8a96674b093c495eddd8704461eaa2b345efbb2ad6930acd8023f870":MBEDTLS_RSA_PKCS_V15:255:2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"3bcf673c3b27f6e2ece4bb97c7a37161e6c6ee7419ef366efc3cfee0f15f415ff6d9d4390937386c6fec1771acba73f24ec6b0469ea8b88083f0b4e1b6069d7bf286e67cf94182a548663137e82a6e09c35de2c27779da0503f1f5bedfebadf2a875f17763a0564df4a6d945a5a3e46bc90fb692af3a55106aafc6b577587456ff8d49cfd5c299d7a2b776dbe4c1ae777b0f64aa3bab27689af32d6cc76157c7dc6900a3469e18a7d9b6bfe4951d1105a08864575e4f4ec05b3e053f9b7a2d5653ae085e50a63380d6bdd6f58ab378d7e0a2be708c559849891317089ab04c82d8bc589ea088b90b11dea5cf85856ff7e609cc1adb1d403beead4c126ff29021":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
+RSA PKCS1 Sign #10 (RIPEMD160, 2048 bits RSA)
+depends_on:MBEDTLS_RIPEMD160_C:MBEDTLS_PKCS1_V15
+mbedtls_rsa_pkcs1_sign:"616263":MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_RIPEMD160:2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"aa2d9f88334d61bed74317ba549b1463600a9219801240cca5c11b9cdda29373172a28151313fb2cf73bb68af167e4ec645b6f065028802afbcfbc10e6c2c824e3c4d50c7181193b93734832170f0c5d3dd9ba5808f0e2a5c16b3d0df90defefef8e8fde5906962d42a2f0d62d7f81977f367f436f10c8b1183ccf6676953f7219445938f725d0cb62efbabf092de531642863b381e2694f2bf544ff6a4fefa7b37cdbf6292dbedcacf6e57d6f206ce5df0fd2771f9f64818f59a0ab7a5f003b368dc3eb51ab9409a0ec4e43f45281ee9a560664de88965ab207e256303d9dcb8233ed6ad0a5ad7f81e2f8c7a196dc81e2c8b6dde8a77fb6cfd1e5477ece9df8":0
+
+RSA PKCS1 Verify #10 (RIPEMD160, 2048 bits RSA)
+depends_on:MBEDTLS_RIPEMD160_C:MBEDTLS_PKCS1_V15
+mbedtls_rsa_pkcs1_verify:"616263":MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_RIPEMD160:2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"aa2d9f88334d61bed74317ba549b1463600a9219801240cca5c11b9cdda29373172a28151313fb2cf73bb68af167e4ec645b6f065028802afbcfbc10e6c2c824e3c4d50c7181193b93734832170f0c5d3dd9ba5808f0e2a5c16b3d0df90defefef8e8fde5906962d42a2f0d62d7f81977f367f436f10c8b1183ccf6676953f7219445938f725d0cb62efbabf092de531642863b381e2694f2bf544ff6a4fefa7b37cdbf6292dbedcacf6e57d6f206ce5df0fd2771f9f64818f59a0ab7a5f003b368dc3eb51ab9409a0ec4e43f45281ee9a560664de88965ab207e256303d9dcb8233ed6ad0a5ad7f81e2f8c7a196dc81e2c8b6dde8a77fb6cfd1e5477ece9df8":0
+
 RSA PKCS1 Encrypt #1
 depends_on:MBEDTLS_PKCS1_V15
 mbedtls_rsa_pkcs1_encrypt:"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_RSA_PKCS_V15:2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"b0c0b193ba4a5b4502bfacd1a9c2697da5510f3e3ab7274cf404418afd2c62c89b98d83bbc21c8c1bf1afe6d8bf40425e053e9c03e03a3be0edbe1eda073fade1cc286cc0305a493d98fe795634c3cad7feb513edb742d66d910c87d07f6b0055c3488bb262b5fd1ce8747af64801fb39d2d3a3e57086ffe55ab8d0a2ca86975629a0f85767a4990c532a7c2dab1647997ebb234d0b28a0008bfebfc905e7ba5b30b60566a5e0190417465efdbf549934b8f0c5c9f36b7c5b6373a47ae553ced0608a161b1b70dfa509375cf7a3598223a6d7b7a1d1a06ac74d345a9bb7c0e44c8388858a4f1d8115f2bd769ffa69020385fa286302c80e950f9e2751308666c":0
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 2b3517d..fd81ffe 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -5633,3 +5633,42 @@
 Record crypt, little space, NULL cipher, SSL3, MD5, short tag, EtM
 depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SSL_PROTO_SSL3:MBEDTLS_MD5_C:MBEDTLS_SSL_ENCRYPT_THEN_MAC
 ssl_crypt_record_small:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_MD5:1:1:MBEDTLS_SSL_MINOR_VERSION_0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_NONE
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_NONE:"":"":"test tls_prf label":"":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SSL3
+depends_on:MBEDTLS_SSL_PROTO_SSL3
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SSL3:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"3ff3d192aa599255339def5a9723444a":0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_TLS1 TLS 1.0 enabled
+depends_on:MBEDTLS_SSL_PROTO_TLS1
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_TLS1:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"8defca540d41d4c79d390027295bb4e6":0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_TLS1 TLS 1.1 enabled
+depends_on:MBEDTLS_SSL_PROTO_TLS1_1
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_TLS1:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"8defca540d41d4c79d390027295bb4e6":0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA384
+depends_on:MBEDTLS_SHA512_C:MBEDTLS_SSL_PROTO_TLS1_2
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA384:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"a4206a36eef93f496611c2b7806625c3":0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_SSL_PROTO_TLS1_2
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":0
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SSL3 not enabled
+depends_on:!MBEDTLS_SSL_PROTO_SSL3
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SSL3:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"3ff3d192aa599255339def5a9723444a":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_TLS1 TLS 1.X not enabled
+depends_on:!MBEDTLS_SSL_PROTO_TLS1:!MBEDTLS_SSL_PROTO_TLS1_1
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_TLS1:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"8defca540d41d4c79d390027295bb4e6":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA384 SHA-512 not enabled
+depends_on:!MBEDTLS_SHA512_C
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA384:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"a4206a36eef93f496611c2b7806625c3":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
+
+SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256 SHA-256 not enabled
+depends_on:!MBEDTLS_SHA256_C
+ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 05ecd8a..ecf186e 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -541,3 +541,32 @@
     mbedtls_free( buf );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void ssl_tls_prf( int type, data_t * secret, data_t * random,
+                  char *label, data_t *result_hex_str, int exp_ret )
+{
+    unsigned char *output;
+
+    output = mbedtls_calloc( 1, result_hex_str->len );
+    if( output == NULL )
+        goto exit;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    TEST_ASSERT( psa_crypto_init() == 0 );
+#endif
+
+    TEST_ASSERT( mbedtls_ssl_tls_prf( type, secret->x, secret->len,
+                                      label, random->x, random->len,
+                                      output, result_hex_str->len ) == exp_ret );
+
+    if( exp_ret == 0 )
+    {
+        TEST_ASSERT( hexcmp( output, result_hex_str->x,
+                     result_hex_str->len, result_hex_str->len ) == 0 );
+    }
+exit:
+
+    mbedtls_free( output );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index edd3a6f..ab3880a 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -94,6 +94,14 @@
 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 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"
@@ -108,11 +116,47 @@
 
 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\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
+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
@@ -128,11 +172,31 @@
 
 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
-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
@@ -1134,6 +1198,22 @@
 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:"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:"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:"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
+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
 x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d1301010100":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_OUT_OF_DATA
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index b11ab84..b4e9802 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -219,6 +219,79 @@
 
     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 */
 
@@ -228,6 +301,46 @@
  */
 
 /* 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 san;
+    mbedtls_x509_sequence *cur = 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 );
+
+    if( crt.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+    {
+        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:
+
+    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 )
 {
     mbedtls_x509_crt   crt;