Merge pull request #611 from mpg/baremetal-proposed

Baremetal proposed
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 010dffc..18851db 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -50,7 +50,7 @@
 
  2. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted.
 
- 3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be addtional test cases or quality improvements such as changes to build or test scripts.
+ 3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts.
 
 It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
 
diff --git a/ChangeLog b/ChangeLog
index 49c3acf..3e85f3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,41 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
-= mbed TLS 2.x.x branch released xxxx-xx-xx
+= mbed TLS x.x.x branch released xxxx-xx-xx
+
+Features
+   * Add new configuration option MBEDTLS_SSL_NO_SESSION_CACHE that enables
+     code size savings in configurations where cache-based session resumption is
+     not used.
+   * Add new configuration option MBEDTLS_SSL_NO_SESSION_RESUMPTION that
+     enables code size savings in configurations where no form of session
+     resumption is used.
+
+Bugfix
+   * Fix to allow building test suites with any warning that detects unused
+     functions. Fixes #1628.
+   * Fix typo in net_would_block(). Fixes #528 reported by github-monoculture.
+   * Remove redundant include file in timing.c. Fixes #2640 reported by irwir.
+   * Fix Visual Studio Release x64 build configuration by inheriting
+     PlatformToolset from the project configuration. Fixes #1430 reported by
+     irwir.
+   * Enable Suite B with subset of ECP curves. Make sure the code compiles even
+     if some curves are not defined. Fixes #1591 reported by dbedev.
+
+Changes
+   * Make it easier to define MBEDTLS_PARAM_FAILED as assert (which config.h
+     suggests). #2671
+   * Make `make clean` clean all programs always. Fixes #1862.
+
+API Changes
+   * Add a new compile-time option `MBEDTLS_X509_ON_DEMAND_PARSING`,
+     disabled by default, which allows to parse and cache X.509 CRTs
+     on demand only, at the benefit of lower RAM usage. Enabling
+     this option breaks the structure API of X.509 in that most
+     fields of `mbedtls_x509_crt` are removed, but it keeps the
+     X.509 function API. See the API changes section as well as
+     the documentation in `config.h` for more information.
+
+= mbed TLS 2.16.2 branch released 2019-06-11
 
 Security
    * Make mbedtls_ecdh_get_params return an error if the second key
@@ -462,7 +497,7 @@
      1.2, that allowed a local attacker, able to execute code on the local
      machine as well as manipulate network packets, to partially recover the
      plaintext of messages under some conditions by using a cache attack
-     targetting an internal MD/SHA buffer. With TLS or if
+     targeting an internal MD/SHA buffer. With TLS or if
      mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if
      the same secret (for example a HTTP Cookie) has been repeatedly sent over
      connections manipulated by the attacker. Connections using GCM or CCM
@@ -1348,7 +1383,7 @@
    * Fix potential build failures related to the 'apidoc' target, introduced
      in the previous patch release. Found by Robert Scheck. #390 #391
    * Fix issue in Makefile that prevented building using armar. #386
-   * Fix memory leak that occured only when ECJPAKE was enabled and ECDHE and
+   * Fix memory leak that occurred only when ECJPAKE was enabled and ECDHE and
      ECDSA was disabled in config.h . The leak didn't occur by default.
    * Fix an issue that caused valid certificates to be rejected whenever an
      expired or not yet valid certificate was parsed before a valid certificate
@@ -1590,7 +1625,7 @@
      You now need to link to all of them if you use TLS for example.
    * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace.
      Some names have been further changed to make them more consistent.
-     Migration helpers scripts/rename.pl and include/mbedlts/compat-1.3.h are
+     Migration helpers scripts/rename.pl and include/mbedtls/compat-1.3.h are
      provided. Full list of renamings in scripts/data_files/rename-1.3-2.0.txt
    * Renamings of fields inside structures, not covered by the previous list:
      mbedtls_cipher_info_t.key_length -> key_bitlen
@@ -1645,7 +1680,7 @@
    * net_accept() gained new arguments for the size of the client_ip buffer.
    * In the threading layer, mbedtls_mutex_init() and mbedtls_mutex_free() now
      return void.
-   * ecdsa_write_signature() gained an addtional md_alg argument and
+   * ecdsa_write_signature() gained an additional md_alg argument and
      ecdsa_write_signature_det() was deprecated.
    * pk_sign() no longer accepts md_alg == POLARSSL_MD_NONE with ECDSA.
    * Last argument of x509_crt_check_key_usage() and
@@ -3180,7 +3215,7 @@
       not swapped on PadLock; also fixed compilation on older versions
       of gcc (bug reported by David Barrett)
     * Correctly handle the case in padlock_xcryptcbc() when input or
-      ouput data is non-aligned by falling back to the software
+      output data is non-aligned by falling back to the software
       implementation, as VIA Nehemiah cannot handle non-aligned buffers
     * Fixed a memory leak in x509parse_crt() which was reported by Greg
       Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to
diff --git a/README.md b/README.md
index 94ea84b..62dd4e2 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@
 
 Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.
 
-Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overriden from the command line.
+Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line.
 
 Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
 
diff --git a/configs/baremetal.h b/configs/baremetal.h
index 330b513..7ff7b07 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -71,6 +71,8 @@
 #define MBEDTLS_SSL_TLS_C
 #define MBEDTLS_SSL_PROTO_TLS1_2
 #define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#define MBEDTLS_SSL_NO_SESSION_CACHE
+#define MBEDTLS_SSL_NO_SESSION_RESUMPTION
 #define MBEDTLS_SSL_COOKIE_C
 #define MBEDTLS_SSL_PROTO_DTLS
 #define MBEDTLS_SSL_PROTO_NO_TLS
@@ -80,6 +82,17 @@
 #define MBEDTLS_SSL_DTLS_CONNECTION_ID
 
 /* Compile-time fixed parts of the SSL configuration */
+#define MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED
+#define MBEDTLS_SSL_CONF_READ_TIMEOUT 0
+#define MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN 1000
+#define MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX 16000
+#define MBEDTLS_SSL_CONF_CID_LEN 2
+#define MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID MBEDTLS_SSL_UNEXPECTED_CID_IGNORE
+#define MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION \
+    MBEDTLS_SSL_SECURE_RENEGOTIATION
+#define MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
+#define MBEDTLS_SSL_CONF_BADMAC_LIMIT 0
+#define MBEDTLS_SSL_CONF_ANTI_REPLAY MBEDTLS_SSL_ANTI_REPLAY_ENABLED
 #define MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET \
     MBEDTLS_SSL_EXTENDED_MS_ENABLED
 #define MBEDTLS_SSL_CONF_ENFORCE_EXTENDED_MASTER_SECRET \
@@ -91,6 +104,8 @@
 #define MBEDTLS_X509_CHECK_KEY_USAGE
 #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
 #define MBEDTLS_X509_REMOVE_INFO
+#define MBEDTLS_X509_ON_DEMAND_PARSING
+#define MBEDTLS_X509_ALWAYS_FLUSH
 #define MBEDTLS_ASN1_PARSE_C
 
 /* X.509 CSR writing */
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 6345ddc..3336f0f 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.16.1 source code documentation
+ * @mainpage mbed TLS v2.16.2 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index e5d2dda..d19c231 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.16.1"
+PROJECT_NAME           = "mbed TLS v2.16.2"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index 96c1c9a..94990fe 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -89,6 +89,18 @@
 #define MBEDTLS_ASN1_CONSTRUCTED             0x20
 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC        0x80
 
+/* Slightly smaller way to check if tag is a string tag
+ * compared to canonical implementation. */
+#define MBEDTLS_ASN1_IS_STRING_TAG( tag )                                     \
+    ( ( tag ) < 32u && (                                                      \
+        ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING )       |     \
+                                ( 1u << MBEDTLS_ASN1_UTF8_STRING )      |     \
+                                ( 1u << MBEDTLS_ASN1_T61_STRING )       |     \
+                                ( 1u << MBEDTLS_ASN1_IA5_STRING )       |     \
+                                ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) |     \
+                                ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) |     \
+                                ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) )
+
 /*
  * Bit masks for each of the components of an ASN.1 tag as specified in
  * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
@@ -119,6 +131,10 @@
         ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) ||                \
           memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
 
+#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len)                  \
+        ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) ||                 \
+          memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 )
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -260,20 +276,97 @@
                              size_t *len );
 
 /**
- * \brief       Parses and splits an ASN.1 "SEQUENCE OF <tag>"
- *              Updated the pointer to immediately behind the full sequence tag.
+ * \brief          Free a heap-allocated linked list presentation of
+ *                 an ASN.1 sequence, including the first element.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param cur   First variable in the chain to fill
- * \param tag   Type of sequence
+ * \param seq      The address of the first sequence component. This may
+ *                 be \c NULL, in which case this functions returns
+ *                 immediately.
+ */
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq );
+
+/**
+ * \brief       This function parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ *              and updates the source buffer pointer to immediately behind
+ *              the full sequence.
+ *
+ * \param p     The address of the pointer to the beginning of the
+ *              ASN.1 SEQUENCE OF structure, including ASN.1 tag+length header.
+ *              On success, `*p` is advanced to point to the first byte
+ *              following the parsed ASN.1 sequence.
+ * \param end   The end of the ASN.1 input buffer starting at \p p. This is
+ *              used for bounds checking.
+ * \param cur   The address at which to store the first entry in the parsed
+ *              sequence. Further entries are heap-allocated and referenced
+ *              from \p cur.
+ * \param tag   The common tag of the entries in the ASN.1 sequence.
+ *
+ * \note        Ownership for the heap-allocated elements \c cur->next,
+ *              \c cur->next->next, ..., is passed to the caller. It
+ *              is hence the caller's responsibility to free them when
+ *              no longer needed, and mbedtls_asn1_sequence_free() can
+ *              be used for that, passing \c cur->next as the \c seq
+ *              argument (or \p cur if \p cur itself was heap-allocated
+ *              by the caller).
  *
  * \return      0 if successful or a specific ASN.1 error code.
  */
 int mbedtls_asn1_get_sequence_of( unsigned char **p,
                           const unsigned char *end,
                           mbedtls_asn1_sequence *cur,
-                          int tag);
+                          int tag );
+
+/**
+ * \brief                Traverse an ASN.1 SEQUENCE container and
+ *                       call a callback for each entry.
+ *
+ * \warning              This function is still experimental and may change
+ *                       at any time.
+ *
+ * \param p              The address of the pointer to the beginning of
+ *                       the ASN.1 SEQUENCE header. This is updated to
+ *                       point to the end of the ASN.1 SEQUENCE container
+ *                       on a successful invocation.
+ * \param end            The end of the ASN.1 SEQUENCE container.
+ * \param tag_must_mask  A mask to be applied to the ASN.1 tags found within
+ *                       the SEQUENCE before comparing to \p tag_must_value.
+ * \param tag_must_val   The required value of each ASN.1 tag found in the
+ *                       SEQUENCE, after masking with \p tag_must_mask.
+ *                       Mismatching tags lead to an error.
+ *                       For example, a value of \c 0 for both \p tag_must_mask
+ *                       and \p tag_must_val means that every tag is allowed,
+ *                       while a value of \c 0xFF for \p tag_must_mask means
+ *                       that \p tag_must_val is the only allowed tag.
+ * \param tag_may_mask   A mask to be applied to the ASN.1 tags found within
+ *                       the SEQUENCE before comparing to \p tag_may_value.
+ * \param tag_may_val    The desired value of each ASN.1 tag found in the
+ *                       SEQUENCE, after masking with \p tag_may_mask.
+ *                       Mismatching tags will be silently ignored.
+ *                       For example, a value of \c 0 for \p tag_may_mask and
+ *                       \p tag_may_val means that any tag will be considered,
+ *                       while a value of \c 0xFF for \p tag_may_mask means
+ *                       that all tags with value different from \p tag_may_val
+ *                       will be ignored.
+ * \param cb             The callback to trigger for each component
+ *                       in the ASN.1 SEQUENCE. If the callback returns
+ *                       a non-zero value, the function stops immediately,
+ *                       forwarding the callback's return value.
+ * \param ctx            The context to be passed to the callback \p cb.
+ *
+ * \return               \c 0 if successful the entire ASN.1 SEQUENCE
+ *                       was traversed without parsing or callback errors.
+ * \return               A negative ASN.1 error code on a parsing failure.
+ * \return               A non-zero error code forwarded from the callback
+ *                       \p cb in case the latter returns a non-zero value.
+ */
+int mbedtls_asn1_traverse_sequence_of(
+    unsigned char **p,
+    const unsigned char *end,
+    uint8_t tag_must_mask, uint8_t tag_must_val,
+    uint8_t tag_may_mask, uint8_t tag_may_val,
+    int (*cb)( void *ctx, int tag,
+               unsigned char* start, size_t len ),
+    void *ctx );
 
 #if defined(MBEDTLS_BIGNUM_C)
 /**
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 88f4701..764fba4 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -631,6 +631,20 @@
 #error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)"
 #endif
 
+#if (  defined(MBEDTLS_SSL_CONF_CID_LEN) &&                     \
+      !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID) ) ||     \
+    ( !defined(MBEDTLS_SSL_CONF_CID_LEN) &&                     \
+       defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID) )
+#error "MBEDTLS_SSL_CONF_CID_LEN and MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID must be defined simultaneously"
+#endif
+
+#if (  defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN) &&       \
+      !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX) ) ||    \
+    ( !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN) &&       \
+       defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX) )
+#error "MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN and MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX must be defined simultaneously"
+#endif
+
 #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) &&                              \
     ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
 #error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT  defined, but not all prerequisites"
@@ -671,6 +685,16 @@
 #error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) &&  \
+    defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+#error "MBEDTLS_SSL_SESSION_TICKETS cannot be defined with MBEDTLS_SSL_NO_SESSION_RESUMPTION"
+#endif
+
+#if !defined(MBEDTLS_SSL_NO_SESSION_CACHE) &&  \
+    defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+#error "MBEDTLS_SSL_NO_SESSION_CACHE needs to be defined with MBEDTLS_SSL_NO_SESSION_RESUMPTION"
+#endif
+
 #if defined(MBEDTLS_THREADING_PTHREAD)
 #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
 #error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites"
@@ -738,7 +762,7 @@
 /*
  * Avoid warning from -pedantic. This is a convenient place for this
  * workaround since this is included by every single file before the
- * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units.
+ * #if defined(MBEDTLS_xxx_C) that results in empty translation units.
  */
 typedef int mbedtls_iso_c_forbids_empty_translation_units;
 
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 2116521..95dd4cd 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -139,7 +139,7 @@
  *
  * System has time.h, time(), and an implementation for
  * mbedtls_platform_gmtime_r() (see below).
- * The time needs to be correct (not necesarily very accurate, but at least
+ * The time needs to be correct (not necessarily very accurate, but at least
  * the date should be correct). This is used to verify the validity period of
  * X.509 certificates.
  *
@@ -276,28 +276,52 @@
  * For example, when a function accepts as input a pointer to a buffer that may
  * contain untrusted data, and its documentation mentions that this pointer
  * must not be NULL:
- * - the pointer is checked to be non-NULL only if this option is enabled
- * - the content of the buffer is always validated
+ * - The pointer is checked to be non-NULL only if this option is enabled.
+ * - The content of the buffer is always validated.
  *
  * When this flag is defined, if a library function receives a parameter that
- * is invalid, it will:
- * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a
- *   call to the function mbedtls_param_failed()
- * - immediately return (with a specific error code unless the function
- *   returns void and can't communicate an error).
+ * is invalid:
+ * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED().
+ * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function
+ *   will immediately return. If the function returns an Mbed TLS error code,
+ *   the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA.
  *
- * When defining this flag, you also need to:
- * - either provide a definition of the function mbedtls_param_failed() in
- *   your application (see platform_util.h for its prototype) as the library
- *   calls that function, but does not provide a default definition for it,
- * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED()
- *   below if the above mechanism is not flexible enough to suit your needs.
- *   See the documentation of this macro later in this file.
+ * When defining this flag, you also need to arrange a definition for
+ * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods:
+ * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a
+ *   function mbedtls_param_failed(), but the library does not define this
+ *   function. If you do not make any other arrangements, you must provide
+ *   the function mbedtls_param_failed() in your application.
+ *   See `platform_util.h` for its prototype.
+ * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the
+ *   library defines #MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`.
+ *   You can still supply an alternative definition of
+ *   MBEDTLS_PARAM_FAILED(), which may call `assert`.
+ * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h`
+ *   or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`,
+ *   the library will call the macro that you defined and will not supply
+ *   its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`,
+ *   you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source
+ *   files include `<assert.h>`.
  *
  * Uncomment to enable validation of application-controlled parameters.
  */
 //#define MBEDTLS_CHECK_PARAMS
 
+/**
+ * \def MBEDTLS_CHECK_PARAMS_ASSERT
+ *
+ * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to
+ * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined.
+ *
+ * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to
+ * calling a function mbedtls_param_failed(). See the documentation of
+ * #MBEDTLS_CHECK_PARAMS for details.
+ *
+ * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`.
+ */
+//#define MBEDTLS_CHECK_PARAMS_ASSERT
+
 /* \} name SECTION: System support */
 
 /**
@@ -401,7 +425,7 @@
  * \note Because of a signature change, the core AES encryption and decryption routines are
  *       currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt,
  *       respectively. When setting up alternative implementations, these functions should
- *       be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
+ *       be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
  *       must stay untouched.
  *
  * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
@@ -1278,8 +1302,8 @@
  * which allows to identify DTLS connections across changes
  * in the underlying transport.
  *
- * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`,
- * `mbedtls_ssl_get_peer_cid()` and `mbedtls_ssl_conf_cid()`.
+ * Setting this option enables the SSL APIs mbedtls_ssl_set_cid(),
+ * mbedtls_ssl_get_peer_cid() and mbedtls_ssl_conf_cid().
  * See the corresponding documentation for more information.
  *
  * \warning The Connection ID extension is still in draft state.
@@ -1658,17 +1682,70 @@
  * \def MBEDTLS_SSL_SESSION_TICKETS
  *
  * Enable support for RFC 5077 session tickets in SSL.
- * Client-side, provides full support for session tickets (maintainance of a
+ * Client-side, provides full support for session tickets (maintenance of a
  * session store remains the responsibility of the application, though).
  * Server-side, you also need to provide callbacks for writing and parsing
  * tickets, including authenticated encryption and key management. Example
  * callbacks are provided by MBEDTLS_SSL_TICKET_C.
  *
- * Comment this macro to disable support for SSL session tickets
+ * Requires: !MBEDTLS_SSL_NO_SESSION_RESUMPTION
+ *
+ * Comment this macro to disable support for SSL session tickets.
  */
 #define MBEDTLS_SSL_SESSION_TICKETS
 
 /**
+ * \def MBEDTLS_SSL_NO_SESSION_CACHE
+ *
+ * Disable support for cache based session resumption. This is useful to
+ * reduce code size in configurations where cache-based session resumption is
+ * not used.
+ *
+ * This option is only about the server-side support of the session caches.
+ * Client will only need !MBEDTLS_SSL_NO_SESSION_RESUMPTION to support
+ * cache based session resumption.
+ *
+ * Server-side, you also need to provide callbacks for storing and reading
+ * sessions from cache. Example callbacks are provided by MBEDTLS_SSL_CACHE_C.
+ *
+ * If MBEDTLS_SSL_NO_SESSION_RESUMPTION is defined, this needs to be defined
+ * as well.
+ *
+ * Uncomment this macro to disable support for SSL session cache.
+ */
+//#define MBEDTLS_SSL_NO_SESSION_CACHE
+
+/**
+ * \def MBEDTLS_SSL_NO_SESSION_RESUMPTION
+ *
+ * Disable support for session resumption. This is useful to reduce code size
+ * in configurations where no form of session resumption is used.
+ *
+ * \note Session resumption is part of the TLS standard, disabling this
+ * option means that the full implementation of the standard is no longer
+ * used. This shouldn't cause any interoperability issues as the standard
+ * mandates that peers who want to resume a session need to be prepared to
+ * fall back to a full handshake.
+ *
+ * When this flag is enabled, following needs to be true:
+ *     MBEDTLS_SSL_NO_SESSION_CACHE enabled
+ *     MBEDTLS_SSL_SESSION_TICKETS disabled
+ *
+ * Client-side, this is enough to enable support for cache-based session
+ * resumption (as defined by the TLS standard); for ticket-based resumption
+ * you'll also need to enable MBEDTLS_SSL_SESSION_TICKETS.
+ *
+ * Server-side, this option is only useful in conjunction with at least
+ * one of !MBEDTLS_SSL_NO_SESSION_CACHE or MBEDTLS_SSL_SESSION_TICKETS.
+ * Each one of these additionally requires an implementation of the cache
+ * or tickets, examples of which are provided by MBEDTLS_SSL_CACHE_C
+ * and MBEDTLS_SSL_TICKET_C respectively.
+ *
+ * Uncomment this macro to disable support for SSL session resumption.
+ */
+//#define MBEDTLS_SSL_NO_SESSION_RESUMPTION
+
+/**
  * \def MBEDTLS_SSL_EXPORT_KEYS
  *
  * Enable support for exporting key block and master secret.
@@ -1758,6 +1835,54 @@
 #define MBEDTLS_VERSION_FEATURES
 
 /**
+ * \def MBEDTLS_X509_ON_DEMAND_PARSING
+ *
+ * Save RAM by reducing mbedtls_x509_crt to a pointer
+ * to the raw CRT data and parsing CRTs on demand only.
+ *
+ * \warning This option changes the API by removing most of
+ *          the structure fields of mbedtls_x509_crt.
+ *
+ * \warning This option and its corresponding X.509 API are currently
+ *          under development and may change at any time.
+ *
+ * Regardless of whether this option is enabled or not, direct access of
+ * structure fields of `mbedtls_x509_crt` should be replaced by calls to
+ * one of the following functions:
+ * - mbedtls_x509_crt_get_frame(), to obtain a CRT frame giving
+ *   access to several basic CRT fields (such as the CRT version),
+ *   as well as pointers to the raw ASN.1 data of more complex fields
+ *   (such as the issuer).
+ * - mbedtls_x509_crt_get_pk(), to obtain a public key context
+ *   for the public key contained in the certificate.
+ * - mbedtls_x509_crt_get_issuer(), to obtain the issuer name.
+ * - mbedtls_x509_crt_get_subject(), to obtain the subject name.
+ * - mbedtls_x509_crt_get_subject_alt_names(), to obtain the
+ *   alternative names from the subject alternative names extension.
+ * - mbedtls_x509_crt_get_ext_key_usage(), to obtain the state of
+ *   the extended key usage extension.
+ *
+ * Uncomment this to enable on-demand CRT parsing to save RAM.
+ */
+//#define MBEDTLS_X509_ON_DEMAND_PARSING
+
+/**
+ * \def MBEDTLS_X509_ALWAYS_FLUSH
+ *
+ * Save RAM by having Mbed TLS always flush caches for parsed X.509
+ * structures after use: This means, firstly, that caches of X.509
+ * structures used by an API call are flushed when the call returns,
+ * but it also encompasses immediate flushing of caches when Mbed TLS uses
+ * multiple structures in succession, thereby reducing the peak RAM usage.
+ * Setting this option leads to minimal RAM usage of the X.509 module at
+ * the cost of performance penalties when using X.509 structures multiple
+ * times (such as trusted CRTs on systems serving many connections).
+ *
+ * Uncomment this to always flush caches for unused X.509 structures.
+ */
+#define MBEDTLS_X509_ALWAYS_FLUSH
+
+/**
  * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
  *
  * If set, the X509 parser will not break-off when parsing an X509 certificate
@@ -1835,7 +1960,7 @@
  *
  * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
  * CRIME attack. Before enabling this option, you should examine with care if
- * CRIME or similar exploits may be a applicable to your use case.
+ * CRIME or similar exploits may be applicable to your use case.
  *
  * \note Currently compression can't be used with DTLS.
  *
@@ -3163,7 +3288,7 @@
 //#define MBEDTLS_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
 //#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
-/* Note: your snprintf must correclty zero-terminate the buffer! */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
 //#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS       0 /**< Default exit value to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE       1 /**< Default exit value to use, can be undefined */
@@ -3180,20 +3305,23 @@
 //#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
 //#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
 //#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
-/* Note: your snprintf must correclty zero-terminate the buffer! */
+/* Note: your snprintf must correctly zero-terminate the buffer! */
 //#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
 //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
 //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
 
 /**
  * \brief       This macro is invoked by the library when an invalid parameter
- *              is detected that is only checked with MBEDTLS_CHECK_PARAMS
+ *              is detected that is only checked with #MBEDTLS_CHECK_PARAMS
  *              (see the documentation of that option for context).
  *
- *              When you leave this undefined here, a default definition is
- *              provided that invokes the function mbedtls_param_failed(),
- *              which is declared in platform_util.h for the benefit of the
- *              library, but that you need to define in your application.
+ *              When you leave this undefined here, the library provides
+ *              a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT
+ *              is defined, the default definition is `assert(cond)`,
+ *              otherwise the default definition calls a function
+ *              mbedtls_param_failed(). This function is declared in
+ *              `platform_util.h` for the benefit of the library, but
+ *              you need to define in your application.
  *
  *              When you define this here, this replaces the default
  *              definition in platform_util.h (which no longer declares the
@@ -3202,6 +3330,9 @@
  *              particular, that all the necessary declarations are visible
  *              from within the library - you can ensure that by providing
  *              them in this file next to the macro definition).
+ *              If you define this macro to call `assert`, also define
+ *              #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files
+ *              include `<assert.h>`.
  *
  *              Note that you may define this macro to expand to nothing, in
  *              which case you don't have to worry about declarations or
@@ -3450,6 +3581,26 @@
  * \{
  */
 
+//#define MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION
+
+//#define MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
+
+/* Timeout */
+//#define MBEDTLS_SSL_CONF_READ_TIMEOUT 0
+
+/* Endpoint (Client/Server) */
+//#define MBEDTLS_SSL_CONF_ENDPOINT MBEDTLS_SSL_IS_CLIENT
+
+//#define MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED
+
+/* DTLS-specific settings */
+//#define MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN
+//#define MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX
+//#define MBEDTLS_SSL_CONF_ANTI_REPLAY MBEDTLS_SSL_ANTI_REPLAY_ENABLED
+//#define MBEDTLS_SSL_CONF_BADMAC_LIMIT 0
+//#define MBEDTLS_SSL_CONF_CID_LEN 0
+//#define MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID MBEDTLS_SSL_UNEXPECTED_CID_IGNORE
+
 /* ExtendedMasterSecret extension
  * The following two options must be set/unset simultaneously. */
 //#define MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MS_ENABLED
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 7eae32b..f1289cb 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -82,7 +82,7 @@
  */
 typedef struct mbedtls_hmac_drbg_context
 {
-    /* Working state: the key K is not stored explicitely,
+    /* Working state: the key K is not stored explicitly,
      * but is implied by the HMAC context */
     mbedtls_md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
     unsigned char V[MBEDTLS_MD_MAX_SIZE];  /*!< V in the spec          */
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index dba6d45..09d0965 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -43,6 +43,12 @@
 
 #if defined(MBEDTLS_CHECK_PARAMS)
 
+#if defined(MBEDTLS_CHECK_PARAMS_ASSERT)
+/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert
+ * (which is what our config.h suggests). */
+#include <assert.h>
+#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */
+
 #if defined(MBEDTLS_PARAM_FAILED)
 /** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h.
  *
@@ -50,6 +56,11 @@
  * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed().
  */
 #define MBEDTLS_PARAM_FAILED_ALT
+
+#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT)
+#define MBEDTLS_PARAM_FAILED( cond ) assert( cond )
+#define MBEDTLS_PARAM_FAILED_ALT
+
 #else /* MBEDTLS_PARAM_FAILED */
 #define MBEDTLS_PARAM_FAILED( cond ) \
     mbedtls_param_failed( #cond, __FILE__, __LINE__ )
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 906c427..4ff5bdd 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -150,13 +150,13 @@
  * \note           The choice of padding mode is strictly enforced for private key
  *                 operations, since there might be security concerns in
  *                 mixing padding modes. For public key operations it is
- *                 a default value, which can be overriden by calling specific
+ *                 a default value, which can be overridden by calling specific
  *                 \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions.
  *
  * \note           The hash selected in \p hash_id is always used for OEAP
  *                 encryption. For PSS signatures, it is always used for
- *                 making signatures, but can be overriden for verifying them.
- *                 If set to #MBEDTLS_MD_NONE, it is always overriden.
+ *                 making signatures, but can be overridden for verifying them.
+ *                 If set to #MBEDTLS_MD_NONE, it is always overridden.
  *
  * \param ctx      The RSA context to initialize. This must not be \c NULL.
  * \param padding  The padding mode to use. This must be either
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index b517089..ead0fa7 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -906,11 +906,13 @@
     int  (*f_rng)(void *, unsigned char *, size_t);
     void *p_rng;                    /*!< context for the RNG function       */
 
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     /** Callback to retrieve a session from the cache                       */
     int (*f_get_cache)(void *, mbedtls_ssl_session *);
     /** Callback to store a session into the cache                          */
     int (*f_set_cache)(void *, const mbedtls_ssl_session *);
     void *p_cache;                  /*!< context for cache callbacks        */
+#endif /* MBEDTLS_SSL_SRV_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
     /** Callback for setting cert according to SNI extension                */
@@ -957,7 +959,9 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#if !defined(MBEDTLS_SSL_CONF_CID_LEN)
     size_t cid_len; /*!< The length of CIDs for incoming DTLS records.      */
+#endif /* !MBEDTLS_SSL_CONF_CID_LEN */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -1013,14 +1017,20 @@
      * Numerical settings (int then char)
      */
 
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
     uint32_t read_timeout;          /*!< timeout for mbedtls_ssl_read (ms)  */
+#endif /* !MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN)
     uint32_t hs_timeout_min;        /*!< initial value of the handshake
                                          retransmission timeout (ms)        */
+#endif /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN */
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX)
     uint32_t hs_timeout_max;        /*!< maximum value of the handshake
                                          retransmission timeout (ms)        */
-#endif
+#endif /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     int renego_max_records;         /*!< grace period for renegotiation     */
@@ -1029,7 +1039,9 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#if !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
     unsigned int badmac_limit;      /*!< limit of records with a bad MAC    */
+#endif /* !MBEDTLS_SSL_CONF_BADMAC_LIMIT */
 #endif
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
@@ -1045,11 +1057,17 @@
      * Flags (bitfields)
      */
 
+#if !defined(MBEDTLS_SSL_CONF_ENDPOINT)
     unsigned int endpoint : 1;      /*!< 0: client, 1: server               */
+#endif /* !MBEDTLS_SSL_CONF_ENDPOINT */
     unsigned int transport : 1;     /*!< stream (TLS) or datagram (DTLS)    */
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
     unsigned int authmode : 2;      /*!< MBEDTLS_SSL_VERIFY_XXX             */
+#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
     unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX   */
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 #if defined(MBEDTLS_ARC4_C)
     unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites?        */
 #endif
@@ -1070,8 +1088,10 @@
 #endif /* !MBEDTLS_SSL_CONF_ENFORCE_EXTENDED_MASTER_SECRET */
 #endif
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
     unsigned int anti_replay : 1;   /*!< detect and prevent replay?         */
-#endif
+#endif /* !MBEDTLS_SSL_CONF_ANTI_REPLAY */
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
     unsigned int cbc_record_splitting : 1;  /*!< do cbc record splitting    */
 #endif
@@ -1088,13 +1108,17 @@
     unsigned int fallback : 1;      /*!< is this a fallback?                */
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
+#if !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
     unsigned int cert_req_ca_list : 1;  /*!< enable sending CA list in
                                           Certificate Request messages?     */
+#endif /* !MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
 #endif
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#if !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
     unsigned int ignore_unexpected_cid : 1; /*!< Determines whether DTLS
                                              *   record with unexpected CID
                                              *   should lead to failure.    */
+#endif /* !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 };
 
@@ -1363,13 +1387,18 @@
  */
 int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl );
 
+#if !defined(MBEDTLS_SSL_CONF_ENDPOINT)
 /**
  * \brief          Set the current endpoint type
  *
+ * \note           On constrained systems, this can also be configured
+ *                 at compile-time via MBEDTLS_SSL_CONF_ENDPOINT.
+ *
  * \param conf     SSL configuration
  * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER
  */
 void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint );
+#endif /* !MBEDTLS_SSL_CONF_ENDPOINT */
 
 /**
  * \brief           Set the transport type (TLS or DTLS).
@@ -1680,6 +1709,7 @@
 void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
 /**
  * \brief          Set the timeout period for mbedtls_ssl_read()
  *                 (Default: no timeout.)
@@ -1693,10 +1723,14 @@
  *                 With non-blocking I/O, this will only work if timer
  *                 callbacks were set with \c mbedtls_ssl_set_timer_cb().
  *
+ * \note           On constrained systems, this option can also be configured
+ *                 at compile-time via MBEDTLS_SSL_CONF_READ_TIMEOUT.
+ *
  * \note           With non-blocking I/O, you may also skip this function
  *                 altogether and handle timeouts at the application layer.
  */
 void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout );
+#endif /* !MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
 /**
  * \brief          Set the timer callbacks (Mandatory for DTLS.)
@@ -2016,14 +2050,16 @@
 
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
+    !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
 /**
  * \brief          Enable or disable anti-replay protection for DTLS.
  *                 (DTLS only, no effect on TLS.)
  *                 Default: enabled.
  *
  * \param conf     SSL configuration
- * \param mode     MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED.
+ * \param mode     MBEDTLS_SSL_ANTI_REPLAY_ENABLED or
+ *                 MBEDTLS_SSL_ANTI_REPLAY_DISABLED.
  *
  * \warning        Disabling this is a security risk unless the application
  *                 protocol handles duplicated packets in a safe way. You
@@ -2031,11 +2067,16 @@
  *                 However, if your application already detects duplicated
  *                 packets and needs information about them to adjust its
  *                 transmission strategy, then you'll want to disable this.
+ *
+ * \note            On constrained systems, this option can also be
+ *                  fixed at compile-time by defining the constant
+ *                  MBEDTLS_SSL_CONF_ANTI_REPLAY.
  */
 void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode );
-#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY && !MBEDTLS_SSL_CONF_ANTI_REPLAY */
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
+    !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
 /**
  * \brief          Set a limit on the number of records with a bad MAC
  *                 before terminating the connection.
@@ -2058,9 +2099,13 @@
  *                 connection. On the other hand, a high limit or no limit
  *                 might make us waste resources checking authentication on
  *                 many bogus packets.
+ *
+ * \note           On constrained systems, this option can also be
+ *                 fixed at compile-time by defining the constant
+ *                 MBEDTLS_SSL_CONF_BADMAC_LIMIT.
  */
 void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit );
-#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT && !MBEDTLS_SSL_CONF_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
@@ -2129,7 +2174,7 @@
 void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
 /**
  * \brief          Set the session cache callbacks (server-side only)
  *                 If not set, no session resuming is done (except if session
@@ -2171,9 +2216,9 @@
         void *p_cache,
         int (*f_get_cache)(void *, mbedtls_ssl_session *),
         int (*f_set_cache)(void *, const mbedtls_ssl_session *) );
-#endif /* MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SRV_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
-#if defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
 /**
  * \brief          Request resumption of session (client-side only)
  *                 Session data is copied from presented session structure.
@@ -2189,7 +2234,7 @@
  * \sa             mbedtls_ssl_get_session()
  */
 int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session );
-#endif /* MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C && !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
 
 /**
  * \brief          Load serialized session data into a session structure.
@@ -2293,9 +2338,11 @@
 void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf,
                                    const int *ciphersuites );
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
 #define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0
 #define MBEDTLS_SSL_UNEXPECTED_CID_FAIL   1
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    !defined(MBEDTLS_SSL_CONF_CID_LEN) &&      \
+    !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
 /**
  * \brief               Specify the length of Connection IDs for incoming
  *                      encrypted DTLS records, as well as the behaviour
@@ -2324,13 +2371,19 @@
  *                      same SSL configuration; this allows simpler parsing of
  *                      record headers.
  *
+ * \note                On constrained systems, this configuration can also be
+ *                      fixed at compile-time via MBEDTLS_SSL_CONF_CID_LEN and
+ *                      MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID.
+ *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len
  *                      is too large.
  */
 int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, size_t len,
                           int ignore_other_cids );
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID &&
+          !MBEDTLS_SSL_CONF_CID_LEN &&
+          !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 
 /**
  * \brief               Set the list of allowed ciphersuites and the
@@ -2395,7 +2448,7 @@
  *                 provision more than one cert/key pair (eg one ECDSA, one
  *                 RSA with SHA-256, one RSA with SHA-1). An adequate
  *                 certificate will be selected according to the client's
- *                 advertised capabilities. In case mutliple certificates are
+ *                 advertised capabilities. In case multiple certificates are
  *                 adequate, preference is given to the one set by the first
  *                 call to this function, then second, etc.
  *
@@ -2916,19 +2969,22 @@
 void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 );
 #endif /* MBEDTLS_ARC4_C */
 
-#if defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
 /**
  * \brief          Whether to send a list of acceptable CAs in
  *                 CertificateRequest messages.
  *                 (Default: do send)
  *
+ * \note           On constrained systems, this options can also be configured
+ *                 at compile-time via MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST.
+ *
  * \param conf     SSL configuration
  * \param cert_req_ca_list   MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or
  *                          MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED
  */
 void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
                                           char cert_req_ca_list );
-#endif /* MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SRV_C && !MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 /**
@@ -3030,6 +3086,7 @@
 void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation );
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
 /**
  * \brief          Prevent or allow legacy renegotiation.
  *                 (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION)
@@ -3056,8 +3113,14 @@
  * \param allow_legacy  Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION,
  *                                        SSL_ALLOW_LEGACY_RENEGOTIATION or
  *                                        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE)
+ *
+ *
+ * \note            On constrained systems, this option can also be
+ *                  fixed at compile-time by defining the constant
+ *                  MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION.
  */
 void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy );
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
 /**
@@ -3733,7 +3796,7 @@
  *                 mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free().
  *
  * \note           You need to call mbedtls_ssl_config_defaults() unless you
- *                 manually set all of the relevent fields yourself.
+ *                 manually set all of the relevant fields yourself.
  *
  * \param conf     SSL configuration context
  */
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 7009c4f..74c9f1a 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -509,7 +509,9 @@
     unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
                                         /*!<  premaster secret        */
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
     int resume;                         /*!<  session resume indicator*/
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
     int max_major_ver;                  /*!< max. major version client*/
     int max_minor_ver;                  /*!< max. minor version client*/
     int cli_exts;                       /*!< client extension presence*/
@@ -1081,10 +1083,212 @@
 
 
 /*
+ * Accessor functions for optional fields of various structures
+ */
+
+static inline int mbedtls_ssl_handshake_get_resume(
+        const mbedtls_ssl_handshake_params *handshake )
+{
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+    return( handshake->resume );
+#else
+    (void) handshake;
+    return( 0 );
+#endif
+}
+
+static inline int mbedtls_ssl_get_renego_status(
+        const mbedtls_ssl_context *ssl )
+{
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    return( ssl->renego_status );
+#else
+    (void) ssl;
+    return( MBEDTLS_SSL_INITIAL_HANDSHAKE );
+#endif
+}
+
+
+/*
  * Getter functions for fields in mbedtls_ssl_config which may
  * be fixed at compile time via one of MBEDTLS_SSL_SSL_CONF_XXX.
  */
 
+#if defined(MBEDTLS_SSL_SRV_C)
+#if !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
+static inline unsigned int mbedtls_ssl_conf_get_cert_req_ca_list(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->cert_req_ca_list );
+}
+#else /* !MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
+static inline unsigned int mbedtls_ssl_conf_get_cert_req_ca_list(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST );
+}
+#endif /* MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if !defined(MBEDTLS_SSL_CONF_ENDPOINT)
+static inline unsigned int mbedtls_ssl_conf_get_endpoint(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->endpoint );
+}
+#else /* !MBEDTLS_SSL_CONF_ENDPOINT */
+static inline unsigned int mbedtls_ssl_conf_get_endpoint(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_ENDPOINT );
+}
+#endif /* MBEDTLS_SSL_CONF_ENDPOINT */
+
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
+static inline uint32_t mbedtls_ssl_conf_get_read_timeout(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->read_timeout );
+}
+#else /* !MBEDTLS_SSL_CONF_READ_TIMEOUT */
+static inline uint32_t mbedtls_ssl_conf_get_read_timeout(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_READ_TIMEOUT );
+}
+#endif /* MBEDTLS_SSL_CONF_READ_TIMEOUT */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN)
+static inline uint32_t mbedtls_ssl_conf_get_hs_timeout_min(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->hs_timeout_min );
+}
+#else /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN */
+static inline uint32_t mbedtls_ssl_conf_get_hs_timeout_min(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN );
+}
+#endif /* MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN */
+
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX)
+static inline uint32_t mbedtls_ssl_conf_get_hs_timeout_max(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->hs_timeout_max );
+}
+#else /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+static inline uint32_t mbedtls_ssl_conf_get_hs_timeout_max(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX );
+}
+#endif /* MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#if !defined(MBEDTLS_SSL_CONF_CID_LEN)
+static inline size_t mbedtls_ssl_conf_get_cid_len(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->cid_len );
+}
+#else /* !MBEDTLS_SSL_CONF_CID_LEN */
+static inline size_t mbedtls_ssl_conf_get_cid_len(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_CID_LEN );
+}
+#endif /* MBEDTLS_SSL_CONF_CID_LEN */
+
+#if !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
+static inline unsigned int mbedtls_ssl_conf_get_ignore_unexpected_cid(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->ignore_unexpected_cid );
+}
+#else /* !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
+static inline unsigned int mbedtls_ssl_conf_get_ignore_unexpected_cid(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID );
+}
+#endif /* MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+static inline unsigned int mbedtls_ssl_conf_get_allow_legacy_renegotiation(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->allow_legacy_renegotiation );
+}
+#else /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+static inline unsigned int mbedtls_ssl_conf_get_allow_legacy_renegotiation(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION );
+}
+#endif /* MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
+static inline int mbedtls_ssl_conf_get_authmode(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->authmode );
+}
+#else /* !MBEDTLS_SSL_CONF_AUTHMODE */
+static inline int mbedtls_ssl_conf_get_authmode(
+    mbedtls_ssl_config const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_AUTHMODE );
+}
+#endif /* MBEDTLS_SSL_CONF_AUTHMODE */
+
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#if !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
+static inline unsigned int mbedtls_ssl_conf_get_badmac_limit(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->badmac_limit );
+}
+#else /* !MBEDTLS_SSL_CONF_BADMAC_LIMIT */
+static inline unsigned int mbedtls_ssl_conf_get_badmac_limit(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_BADMAC_LIMIT );
+}
+#endif /* MBEDTLS_SSL_CONF_BADMAC_LIMIT */
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
+static inline unsigned int mbedtls_ssl_conf_get_anti_replay(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->anti_replay );
+}
+#else /* !MBEDTLS_SSL_CONF_ANTI_REPLAY */
+static inline unsigned int mbedtls_ssl_conf_get_anti_replay(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_ANTI_REPLAY );
+}
+#endif /* MBEDTLS_SSL_CONF_ANTI_REPLAY */
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
 static inline unsigned int mbedtls_ssl_conf_get_ems(
     mbedtls_ssl_config const *conf )
diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index a84e781..774a007 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -117,14 +117,14 @@
 /**
  * \brief           Implementation of the ticket write callback
  *
- * \note            See \c mbedlts_ssl_ticket_write_t for description
+ * \note            See \c mbedtls_ssl_ticket_write_t for description
  */
 mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write;
 
 /**
  * \brief           Implementation of the ticket parse callback
  *
- * \note            See \c mbedlts_ssl_ticket_parse_t for description
+ * \note            See \c mbedtls_ssl_ticket_parse_t for description
  */
 mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse;
 
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index cc736e1..ef8e4c1 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -40,16 +40,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  16
-#define MBEDTLS_VERSION_PATCH  1
+#define MBEDTLS_VERSION_PATCH  2
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02100100
-#define MBEDTLS_VERSION_STRING         "2.16.1"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.1"
+#define MBEDTLS_VERSION_NUMBER         0x02100200
+#define MBEDTLS_VERSION_STRING         "2.16.2"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.2"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index ff06d13..b69dd71 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -77,7 +77,7 @@
 #define MBEDTLS_ERR_X509_ALLOC_FAILED                     -0x2880  /**< Allocation of memory failed. */
 #define MBEDTLS_ERR_X509_FILE_IO_ERROR                    -0x2900  /**< Read/write of file failed. */
 #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL                 -0x2980  /**< Destination buffer is too small. */
-#define MBEDTLS_ERR_X509_FATAL_ERROR                      -0x3000  /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */
+#define MBEDTLS_ERR_X509_FATAL_ERROR                      -0x3000  /**< A fatal error occurred, eg the chain is too long or the vrfy callback failed. */
 /* \} name */
 
 /**
@@ -184,6 +184,15 @@
  */
 
 /**
+ * Basic length-value buffer structure
+ */
+typedef struct mbedtls_x509_buf_raw
+{
+    unsigned char *p;    /*!< The address of the first byte in the buffer. */
+    size_t len;          /*!< The number of Bytes in the buffer.           */
+} mbedtls_x509_buf_raw;
+
+/**
  * Type-length-value structure that allows for ASN1 using DER.
  */
 typedef mbedtls_asn1_buf mbedtls_x509_buf;
@@ -250,7 +259,7 @@
  *
  * \param to       mbedtls_x509_time to check
  *
- * \return         1 if the given time is in the past or an error occured,
+ * \return         1 if the given time is in the past or an error occurred,
  *                 0 otherwise.
  */
 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to );
@@ -264,11 +273,34 @@
  *
  * \param from     mbedtls_x509_time to check
  *
- * \return         1 if the given time is in the future or an error occured,
+ * \return         1 if the given time is in the future or an error occurred,
  *                 0 otherwise.
  */
 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from );
 
+/**
+ * \brief          Free a dynamic linked list presentation of an X.509 name
+ *                 as returned e.g. by mbedtls_x509_crt_get_subject().
+ *
+ * \param name     The address of the first name component. This may
+ *                 be \c NULL, in which case this functions returns
+ *                 immediately.
+ */
+void mbedtls_x509_name_free( mbedtls_x509_name *name );
+
+/**
+ * \brief          Free a dynamic linked list presentation of an X.509 sequence
+ *                 as returned e.g. by mbedtls_x509_crt_get_subject_alt_name().
+ *
+ * \param seq      The address of the first sequence component. This may
+ *                 be \c NULL, in which case this functions returns
+ *                 immediately.
+ */
+static inline void mbedtls_x509_sequence_free( mbedtls_x509_sequence *seq )
+{
+    mbedtls_asn1_sequence_free( (mbedtls_asn1_sequence*) seq );
+}
+
 #if defined(MBEDTLS_SELF_TEST)
 
 /**
@@ -280,49 +312,6 @@
 
 #endif /* MBEDTLS_SELF_TEST */
 
-/*
- * Internal module functions. You probably do not want to use these unless you
- * know you do.
- */
-int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
-                   mbedtls_x509_name *cur );
-int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
-                       mbedtls_x509_buf *alg );
-int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
-                  mbedtls_x509_buf *alg, mbedtls_x509_buf *params );
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
-                                mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
-                                int *salt_len );
-#endif
-int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig );
-int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
-                      mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
-                      void **sig_opts );
-int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
-                   mbedtls_x509_time *t );
-int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
-                     mbedtls_x509_buf *serial );
-int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
-                  mbedtls_x509_buf *ext, int tag );
-#if !defined(MBEDTLS_X509_REMOVE_INFO)
-int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
-                       mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
-                       const void *sig_opts );
-#endif
-int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name );
-int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name );
-int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
-                        int critical, const unsigned char *val,
-                        size_t val_len );
-int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
-                           mbedtls_asn1_named_data *first );
-int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
-                      mbedtls_asn1_named_data *first );
-int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
-                    const char *oid, size_t oid_len,
-                    unsigned char *sig, size_t size );
-
 #define MBEDTLS_X509_SAFE_SNPRINTF                          \
     do {                                                    \
         if( ret < 0 || (size_t) ret >= n )                  \
@@ -332,6 +321,18 @@
         p += (size_t) ret;                                  \
     } while( 0 )
 
+#define MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP             \
+    do {                                                    \
+        if( ret < 0 || (size_t) ret >= n )                  \
+        {                                                   \
+            ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;        \
+            goto cleanup;                                   \
+        }                                                   \
+                                                            \
+        n -= (size_t) ret;                                  \
+        p += (size_t) ret;                                  \
+    } while( 0 )
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/x509_crl.h b/include/mbedtls/x509_crl.h
index 2bb95de..bf9e3be 100644
--- a/include/mbedtls/x509_crl.h
+++ b/include/mbedtls/x509_crl.h
@@ -75,7 +75,7 @@
     int version;            /**< CRL version (1=v1, 2=v2) */
     mbedtls_x509_buf sig_oid;       /**< CRL signature type identifier */
 
-    mbedtls_x509_buf issuer_raw;    /**< The raw issuer data (DER). */
+    mbedtls_x509_buf_raw issuer_raw;           /**< The raw issuer data (DER). */
 
     mbedtls_x509_name issuer;       /**< The parsed issuer data (named information object). */
 
@@ -111,7 +111,7 @@
 /**
  * \brief          Parse one or more CRLs and append them to the chained list
  *
- * \note           Mutliple CRLs are accepted only if using PEM format
+ * \note           Multiple CRLs are accepted only if using PEM format
  *
  * \param chain    points to the start of the chain
  * \param buf      buffer holding the CRL data in PEM or DER format
@@ -126,7 +126,7 @@
 /**
  * \brief          Load one or more CRLs and append them to the chained list
  *
- * \note           Mutliple CRLs are accepted only if using PEM format
+ * \note           Multiple CRLs are accepted only if using PEM format
  *
  * \param chain    points to the start of the chain
  * \param path     filename to read the CRLs from (in PEM or DER encoding)
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 09ba69f..3eee460 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -32,6 +32,7 @@
 
 #include "x509.h"
 #include "x509_crl.h"
+#include "x509_internal.h"
 
 /**
  * \addtogroup x509_module
@@ -47,14 +48,69 @@
  * \{
  */
 
+typedef struct mbedtls_x509_crt_frame
+{
+    /* Keep these 8-bit fields at the front of the structure to allow them to
+     * be fetched in a single instruction on Thumb2; putting them at the back
+     * requires an intermediate address calculation. */
+
+    uint8_t version;                        /**< The X.509 version. (1=v1, 2=v2, 3=v3)                          */
+    uint8_t ca_istrue;                      /**< Optional Basic Constraint extension value:
+                                             *   1 if this certificate belongs to a CA, 0 otherwise.            */
+    uint8_t max_pathlen;                    /**< Optional Basic Constraint extension value:
+                                             *   The maximum path length to the root certificate.
+                                             *   Path length is 1 higher than RFC 5280 'meaning', so 1+         */
+    uint8_t ns_cert_type;                   /**< Optional Netscape certificate type extension value:
+                                             *   See the values in x509.h                                       */
+
+    mbedtls_md_type_t sig_md;               /**< The hash algorithm used to hash CRT before signing.            */
+    mbedtls_pk_type_t sig_pk;               /**< The signature algorithm used to sign the CRT hash.             */
+
+    uint16_t key_usage;                     /**< Optional key usage extension value: See the values in x509.h   */
+    uint32_t ext_types;                     /**< Bitfield indicating which extensions are present.
+                                             *   See the values in x509.h.                                      */
+
+    mbedtls_x509_time valid_from;           /**< The start time of certificate validity.                        */
+    mbedtls_x509_time valid_to;             /**< The end time of certificate validity.                          */
+
+    mbedtls_x509_buf_raw raw;               /**< The raw certificate data in DER.                               */
+    mbedtls_x509_buf_raw tbs;               /**< The part of the CRT that is [T]o [B]e [S]igned.                */
+
+    mbedtls_x509_buf_raw serial;            /**< The unique ID for certificate issued by a specific CA.         */
+
+    mbedtls_x509_buf_raw pubkey_raw;        /**< The raw public key data (DER).                                 */
+
+    mbedtls_x509_buf_raw issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier.                 */
+    mbedtls_x509_buf_raw issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison.          */
+
+    mbedtls_x509_buf_raw subject_id;        /**< Optional X.509 v2/v3 subject unique identifier.                */
+    mbedtls_x509_buf_raw subject_raw;       /**< The raw subject data (DER). Used for quick comparison.         */
+
+    mbedtls_x509_buf_raw sig;               /**< Signature: hash of the tbs part signed with the private key.   */
+    mbedtls_x509_buf_raw sig_alg;           /**< The signature algorithm used for \p sig.                       */
+
+    mbedtls_x509_buf_raw v3_ext;            /**< The raw data for the extension list in the certificate.
+                                             *   Might be useful for manual inspection of extensions that
+                                             *   Mbed TLS doesn't yet support.                                  */
+    mbedtls_x509_buf_raw subject_alt_raw;   /**< The raw data for the SubjectAlternativeNames extension.        */
+    mbedtls_x509_buf_raw ext_key_usage_raw; /**< The raw data for the ExtendedKeyUsage extension.               */
+
+} mbedtls_x509_crt_frame;
+
 /**
  * Container for an X.509 certificate. The certificate may be chained.
  */
 typedef struct mbedtls_x509_crt
 {
     int own_buffer;                     /**< Indicates if \c raw is owned
-                                         *   by the structure or not.        */
-    mbedtls_x509_buf raw;               /**< The raw certificate data (DER). */
+                                         *   by the structure or not.         */
+    mbedtls_x509_buf raw;               /**< The raw certificate data (DER).  */
+    mbedtls_x509_crt_cache *cache;      /**< Internal parsing cache.      */
+
+    struct mbedtls_x509_crt *next;     /**< Next certificate in the CA-chain. */
+
+    /* Legacy fields */
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
     mbedtls_x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
 
     int version;                /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
@@ -84,7 +140,7 @@
 
     unsigned int key_usage;     /**< Optional key usage extension value: See the values in x509.h */
 
-    mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
+    mbedtls_x509_sequence ext_key_usage;    /**< Optional list of extended key usage OIDs. */
 
     unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
 
@@ -92,8 +148,7 @@
     mbedtls_md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */
     mbedtls_pk_type_t sig_pk;           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
     void *sig_opts;             /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
-
-    struct mbedtls_x509_crt *next;     /**< Next certificate in the CA-chain. */
+#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
 }
 mbedtls_x509_crt;
 
@@ -586,6 +641,366 @@
  */
 void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/**
+ * \brief           Request CRT frame giving access to basic CRT fields
+ *                  and raw ASN.1 data of complex fields.
+ *
+ * \param crt       The CRT to use. This must be initialized and set up.
+ * \param dst       The address of the destination frame structure.
+ *                  This need not be initialized.
+ *
+ * \note            ::mbedtls_x509_crt_frame does not contain pointers to
+ *                  dynamically allocated memory, and hence need not be freed.
+ *                  Users may e.g. allocate an instance of
+ *                  ::mbedtls_x509_crt_frame on the stack and call this function
+ *                  on it, in which case no allocation/freeing has to be done.
+ *
+ * \note            You may also use mbedtls_x509_crt_frame_acquire() and
+ *                  mbedtls_x509_crt_frame_release() for copy-less variants
+ *                  of this function.
+ *
+ * \return          \c 0 on success. In this case, \p dst is updated
+ *                  to hold the frame for the given CRT.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_frame( mbedtls_x509_crt const *crt,
+                                mbedtls_x509_crt_frame *dst );
+
+/**
+ * \brief           Set up a PK context with the public key in a certificate.
+ *
+ * \param crt       The certificate to use. This must be initialized and set up.
+ * \param pk        The address of the destination PK context to fill.
+ *                  This must be initialized via mbedtls_pk_init().
+ *
+ * \note            You may also use mbedtls_x509_crt_pk_acquire() and
+ *                  mbedtls_x509_crt_pk_release() for copy-less variants
+ *                  of this function.
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the destination PK context, and is responsible for
+ *                  calling mbedtls_pk_free() on it once it's no longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_pk( mbedtls_x509_crt const *crt,
+                             mbedtls_pk_context *pk );
+
+/**
+ * \brief           Request the subject name of a CRT, presented
+ *                  as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and set up.
+ * \param subject   The address at which to store the address of the
+ *                  first entry of the generated linked list holding
+ *                  the subject name.
+ *
+ * \note            Depending on your use case, consider using the raw ASN.1
+ *                  describing the subject name instead of the heap-allocated
+ *                  linked list generated by this call. The pointers to the
+ *                  raw ASN.1 data are part of the CRT frame that can be queried
+ *                  via mbedtls_x509_crt_get_frame(), and they can be traversed
+ *                  via mbedtls_asn1_traverse_sequence_of().
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_name_free() once it's no
+ *                  longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
+                                  mbedtls_x509_name **subject );
+
+/**
+ * \brief           Request the subject name of a CRT, presented
+ *                  as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and set up.
+ * \param issuer    The address at which to store the address of the
+ *                  first entry of the generated linked list holding
+ *                  the subject name.
+ *
+ * \note            Depending on your use case, consider using the raw ASN.1
+ *                  describing the issuer name instead of the heap-allocated
+ *                  linked list generated by this call. The pointers to the
+ *                  raw ASN.1 data are part of the CRT frame that can be queried
+ *                  via mbedtls_x509_crt_get_frame(), and they can be traversed
+ *                  via mbedtls_asn1_traverse_sequence_of().
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_name_free() once it's no
+ *                  longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_issuer( mbedtls_x509_crt const *crt,
+                                 mbedtls_x509_name **issuer );
+
+/**
+ * \brief           Request the subject alternative name of a CRT, presented
+ *                  as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and set up.
+ * \param subj_alt  The address at which to store the address of the
+ *                  first component of the subject alternative names list.
+ *
+ * \note            Depending in your use case, consider using the raw ASN.1
+ *                  describing the subject alternative names extension
+ *                  instead of the heap-allocated linked list generated by this
+ *                  call. The pointers to the raw ASN.1 data are part of the CRT
+ *                  frame that can be queried via mbedtls_x509_crt_get_frame(),
+ *                  and mbedtls_asn1_traverse_sequence_of() can be used to
+ *                  traverse the list of subject alternative names.
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_sequence_free() once it's
+ *                  no longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
+                                            mbedtls_x509_sequence **subj_alt );
+
+/**
+ * \brief           Request the ExtendedKeyUsage extension of a CRT,
+ *                  presented as a dynamically allocated linked list.
+ *
+ * \param crt       The CRT to use. This must be initialized and set up.
+ * \param ext_key_usage The address at which to store the address of the
+ *                  first entry of the ExtendedKeyUsage extension.
+ *
+ * \note            Depending in your use case, consider using the raw ASN.1
+ *                  describing the extended key usage extension instead of
+ *                  the heap-allocated linked list generated by this call.
+ *                  The pointers to the raw ASN.1 data are part of the CRT
+ *                  frame that can be queried via mbedtls_x509_crt_get_frame(),
+ *                  and mbedtls_asn1_traverse_sequence_of() can be used to
+ *                  traverse the entries in the extended key usage extension.
+ *
+ * \return          \c 0 on success. In this case, the user takes ownership
+ *                  of the name context, and is responsible for freeing it
+ *                  through a call to mbedtls_x509_sequence_free() once it's
+ *                  no longer needed.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
+                                        mbedtls_x509_sequence **ext_key_usage );
+
+/**
+ * \brief           Flush internal X.509 CRT parsing cache, if present.
+ *
+ * \param crt       The CRT structure whose cache to flush.
+ *
+ * \note            Calling this function frequently reduces RAM usage
+ *                  at the cost of performance.
+ *
+ * \return          \c 0 on success.
+ * \return          A negative error code on failure.
+ */
+int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt );
+
+/**
+ * \brief        Request temporary read-access to a certificate frame
+ *               for a given certificate.
+ *
+ *               Once no longer needed, the frame must be released
+ *               through a call to mbedtls_x509_crt_frame_release().
+ *
+ *               This is a copy-less version of mbedtls_x509_crt_get_frame().
+ *               See there for more information.
+ *
+ * \param crt    The certificate to use. This must be initialized and set up.
+ * \param dst    The address at which to store the address of a readable
+ *               certificate frame for the input certificate \p crt which the
+ *               caller can use until calling mbedtls_x509_crt_frame_release().
+ *
+ * \note         The certificate frame `**frame_ptr` returned by this function
+ *               is owned by the X.509 module and must not be freed or modified
+ *               by the caller. The X.509 module guarantees its validity as long
+ *               as \p crt is valid and mbedtls_x509_crt_frame_release() hasn't
+ *               been issued.
+ *
+ * \note         In a single-threaded application using
+ *               MBEDTLS_X509_ALWAYS_FLUSH, nested calls to this function
+ *               are not allowed and will fail gracefully with
+ *               MBEDTLS_ERR_X509_FATAL_ERROR.
+ *
+ * \return       \c 0 on success. In this case, `*frame_ptr` is updated
+ *               to hold the address of a frame for the given CRT.
+ * \return       A negative error code on failure.
+ */
+static inline int mbedtls_x509_crt_frame_acquire( mbedtls_x509_crt const *crt,
+                                          mbedtls_x509_crt_frame const **dst )
+{
+    int ret = 0;
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->frame_readers == 0 )
+#endif
+        ret = mbedtls_x509_crt_cache_provide_frame( crt );
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->frame_readers == MBEDTLS_X509_CACHE_FRAME_READERS_MAX )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+
+    crt->cache->frame_readers++;
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+    *dst = crt->cache->frame;
+    return( ret );
+}
+
+/**
+ * \brief        Release access to a certificate frame acquired
+ *               through a prior call to mbedtls_x509_crt_frame_acquire().
+ *
+ * \param crt    The certificate for which a certificate frame has
+ *               previously been acquired.
+ */
+static inline int mbedtls_x509_crt_frame_release( mbedtls_x509_crt const *crt )
+{
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->frame_readers == 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    crt->cache->frame_readers--;
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock( &crt->cache->frame_mutex );
+#endif /* MBEDTLS_THREADING_C */
+
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
+    (void) mbedtls_x509_crt_flush_cache_frame( crt );
+#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
+    !defined(MBEDTLS_THREADING_C)
+    ((void) crt);
+#endif
+
+    return( 0 );
+}
+
+/**
+ * \brief        Request temporary access to a public key context
+ *               for a given certificate.
+ *
+ *               Once no longer needed, the frame must be released
+ *               through a call to mbedtls_x509_crt_pk_release().
+ *
+ *               This is a copy-less version of mbedtls_x509_crt_get_pk().
+ *               See there for more information.
+ *
+ * \param crt    The certificate to use. This must be initialized and set up.
+ * \param dst    The address at which to store the address of a public key
+ *               context for the public key in the input certificate \p crt.
+ *
+ * \warning      The public key context `**pk_ptr` returned by this function
+ *               is owned by the X.509 module and must be used by the caller
+ *               in a thread-safe way. In particular, the caller must only
+ *               use the context with functions which are `const` on the input
+ *               context, or those which are known to be thread-safe. The latter
+ *               for example includes mbedtls_pk_verify() for ECC or RSA public
+ *               key contexts.
+ *
+ * \note         In a single-threaded application using
+ *               MBEDTLS_X509_ALWAYS_FLUSH, nested calls to this function
+ *               are not allowed and will fail gracefully with
+ *               MBEDTLS_ERR_X509_FATAL_ERROR.
+ *
+ * \return       \c 0 on success. In this case, `*pk_ptr` is updated
+ *               to hold the address of a public key context for the given
+ *               certificate.
+ * \return       A negative error code on failure.
+ */
+static inline int mbedtls_x509_crt_pk_acquire( mbedtls_x509_crt const *crt,
+                                               mbedtls_pk_context **dst )
+{
+    int ret = 0;
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->pk_readers == 0 )
+#endif
+        ret = mbedtls_x509_crt_cache_provide_pk( crt );
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->pk_readers == MBEDTLS_X509_CACHE_PK_READERS_MAX )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+
+    crt->cache->pk_readers++;
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+    *dst = crt->cache->pk;
+    return( ret );
+}
+
+/**
+ * \brief        Release access to a public key context acquired
+ *               through a prior call to mbedtls_x509_crt_frame_acquire().
+ *
+ * \param crt    The certificate for which a certificate frame has
+ *               previously been acquired.
+ */
+static inline int mbedtls_x509_crt_pk_release( mbedtls_x509_crt const *crt )
+{
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif /* MBEDTLS_THREADING_C */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    if( crt->cache->pk_readers == 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    crt->cache->pk_readers--;
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock( &crt->cache->pk_mutex );
+#endif /* MBEDTLS_THREADING_C */
+
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
+    (void) mbedtls_x509_crt_flush_cache_pk( crt );
+#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
+    !defined(MBEDTLS_THREADING_C)
+    ((void) crt);
+#endif
+
+    return( 0 );
+}
+
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 /* \} name */
diff --git a/include/mbedtls/x509_internal.h b/include/mbedtls/x509_internal.h
new file mode 100644
index 0000000..6ca3db5
--- /dev/null
+++ b/include/mbedtls/x509_internal.h
@@ -0,0 +1,117 @@
+/**
+ * \file x509_internal.h
+ *
+ * \brief Internal X.509 functions
+ */
+/*
+ *  Copyright (C) 2006-2019, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDTLS_X509_INTERNAL_H
+#define MBEDTLS_X509_INTERNAL_H
+
+#include "x509.h"
+#include "threading.h"
+
+/* Internal structure used for caching parsed data from an X.509 CRT. */
+
+struct mbedtls_x509_crt;
+struct mbedtls_pk_context;
+struct mbedtls_x509_crt_frame;
+#define MBEDTLS_X509_CACHE_PK_READERS_MAX    ((uint32_t) -1)
+#define MBEDTLS_X509_CACHE_FRAME_READERS_MAX ((uint32_t) -1)
+typedef struct mbedtls_x509_crt_cache
+{
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
+    defined(MBEDTLS_THREADING_C)
+    uint32_t frame_readers;
+    uint32_t pk_readers;
+#endif /* !MBEDTLS_X509_ALWAYS_FLUSH || MBEDTLS_THREADING_C */
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_threading_mutex_t frame_mutex;
+    mbedtls_threading_mutex_t pk_mutex;
+#endif
+    mbedtls_x509_buf_raw pk_raw;
+    struct mbedtls_x509_crt_frame *frame;
+    struct mbedtls_pk_context *pk;
+} mbedtls_x509_crt_cache;
+
+/* Internal X.509 CRT cache handling functions. */
+
+int mbedtls_x509_crt_flush_cache_frame( struct mbedtls_x509_crt const *crt );
+int mbedtls_x509_crt_flush_cache_pk( struct mbedtls_x509_crt const *crt );
+
+int mbedtls_x509_crt_cache_provide_frame( struct mbedtls_x509_crt const *crt );
+int mbedtls_x509_crt_cache_provide_pk( struct mbedtls_x509_crt const *crt );
+
+/* Uncategorized internal X.509 functions */
+
+int mbedtls_x509_get_name( unsigned char *p, size_t len,
+                           mbedtls_x509_name *cur );
+int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                       mbedtls_x509_buf *alg );
+int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
+                  mbedtls_x509_buf *alg, mbedtls_x509_buf *params );
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
+                                mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
+                                int *salt_len );
+#endif
+int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig );
+int mbedtls_x509_get_sig_alg_raw( unsigned char **p, unsigned char const *end,
+                                  mbedtls_md_type_t *md_alg,
+                                  mbedtls_pk_type_t *pk_alg,
+                                  void **sig_opts );
+int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
+                      mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
+                      void **sig_opts );
+int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
+                   mbedtls_x509_time *t );
+int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
+                     mbedtls_x509_buf *serial );
+int mbedtls_x509_name_cmp_raw( mbedtls_x509_buf_raw const *a,
+                               mbedtls_x509_buf_raw const *b,
+                               int (*check)( void *ctx,
+                                             mbedtls_x509_buf *oid,
+                                             mbedtls_x509_buf *val,
+                                             int next_merged ),
+                               void *check_ctx );
+int mbedtls_x509_memcasecmp( const void *s1, const void *s2,
+                             size_t len1, size_t len2 );
+int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
+                  mbedtls_x509_buf *ext, int tag );
+
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+int mbedtls_x509_sig_alg_gets( char *buf, size_t size,
+                       mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
+                       const void *sig_opts );
+#endif
+int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name );
+int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name );
+int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
+                        int critical, const unsigned char *val,
+                        size_t val_len );
+int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
+                           mbedtls_asn1_named_data *first );
+int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
+                      mbedtls_asn1_named_data *first );
+int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
+                    const char *oid, size_t oid_len,
+                    unsigned char *sig, size_t size );
+
+#endif /* MBEDTLS_X509_INTERNAL_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index a9a5b7b..461843b 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -167,15 +167,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.1 SOVERSION 3)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.2 SOVERSION 3)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.1 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.2 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.16.1 SOVERSION 12)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.16.2 SOVERSION 12)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/Makefile b/library/Makefile
index d653aa0..45ed148 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -39,7 +39,7 @@
 SOEXT_X509=so.0
 SOEXT_CRYPTO=so.3
 
-# Set AR_DASH= (empty string) to use an ar implentation that does not accept
+# Set AR_DASH= (empty string) to use an ar implementation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
 AR_DASH ?= -
 
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 171c340..aac253b 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -229,6 +229,103 @@
     return( 0 );
 }
 
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq )
+{
+    while( seq != NULL )
+    {
+        mbedtls_asn1_sequence *next = seq->next;
+        mbedtls_platform_zeroize( seq, sizeof( *seq ) );
+        mbedtls_free( seq );
+        seq = next;
+    }
+}
+
+/*
+ * Traverse an ASN.1 "SEQUENCE OF <tag>"
+ * and call a callback for each entry found.
+ */
+int mbedtls_asn1_traverse_sequence_of(
+    unsigned char **p,
+    const unsigned char *end,
+    uint8_t tag_must_mask, uint8_t tag_must_val,
+    uint8_t tag_may_mask, uint8_t tag_may_val,
+    int (*cb)( void *ctx, int tag,
+               unsigned char *start, size_t len ),
+    void *ctx )
+{
+    int ret;
+    size_t len;
+
+    /* Get main sequence tag */
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( *p + len != end )
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+    while( *p < end )
+    {
+        unsigned char const tag = *(*p)++;
+
+        if( ( tag & tag_must_mask ) != tag_must_val )
+            return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+
+        if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 )
+            return( ret );
+
+        if( ( tag & tag_may_mask ) == tag_may_val )
+        {
+            if( cb != NULL )
+            {
+                ret = cb( ctx, tag, *p, len );
+                if( ret != 0 )
+                    return( ret );
+            }
+        }
+
+        *p += len;
+    }
+
+    return( 0 );
+}
+
+typedef struct
+{
+    int tag;
+    mbedtls_asn1_sequence *cur;
+} asn1_get_sequence_of_cb_ctx_t;
+
+static int asn1_get_sequence_of_cb( void *ctx,
+                                    int tag,
+                                    unsigned char *start,
+                                    size_t len )
+{
+    asn1_get_sequence_of_cb_ctx_t *cb_ctx =
+        (asn1_get_sequence_of_cb_ctx_t *) ctx;
+    mbedtls_asn1_sequence *cur =
+        cb_ctx->cur;
+
+    if( cur->buf.p != NULL )
+    {
+        cur->next =
+            mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+        if( cur->next == NULL )
+            return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+        cur = cur->next;
+    }
+
+    cur->buf.p = start;
+    cur->buf.len = len;
+    cur->buf.tag = tag;
+
+    cb_ctx->cur = cur;
+    return( 0 );
+}
 
 
 /*
@@ -239,49 +336,11 @@
                           mbedtls_asn1_sequence *cur,
                           int tag)
 {
-    int ret;
-    size_t len;
-    mbedtls_asn1_buf *buf;
-
-    /* Get main sequence tag */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( ret );
-
-    if( *p + len != end )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-    while( *p < end )
-    {
-        buf = &(cur->buf);
-        buf->tag = **p;
-
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
-            return( ret );
-
-        buf->p = *p;
-        *p += buf->len;
-
-        /* Allocate and assign next pointer */
-        if( *p < end )
-        {
-            cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
-                                            sizeof( mbedtls_asn1_sequence ) );
-
-            if( cur->next == NULL )
-                return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
-            cur = cur->next;
-        }
-    }
-
-    /* Set final sequence entry's next pointer to NULL */
-    cur->next = NULL;
-
-    if( *p != end )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
+    asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
+    memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
+    return( mbedtls_asn1_traverse_sequence_of(
+                p, end, 0xFF, tag, 0, 0,
+                asn1_get_sequence_of_cb, &cb_ctx ) );
 }
 
 int mbedtls_asn1_get_alg( unsigned char **p,
@@ -295,15 +354,12 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
         return( ret );
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
-
-    alg->tag = **p;
     end = *p + len;
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 )
         return( ret );
 
+    alg->tag = MBEDTLS_ASN1_OID;
     alg->p = *p;
     *p += alg->len;
 
diff --git a/library/bignum.c b/library/bignum.c
index 4194618..d94754a 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -127,7 +127,7 @@
 
     if( X->n < nblimbs )
     {
-        if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
+        if( ( p = (mbedtls_mpi_uint *)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
 
         if( X->p != NULL )
@@ -169,7 +169,7 @@
     if( i < nblimbs )
         i = nblimbs;
 
-    if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL )
+    if( ( p = (mbedtls_mpi_uint *)mbedtls_calloc( i, ciL ) ) == NULL )
         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
 
     if( X->p != NULL )
diff --git a/library/cipher.c b/library/cipher.c
index 2739975..5821716 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -331,13 +331,13 @@
                 ? MBEDTLS_CHACHAPOLY_ENCRYPT
                 : MBEDTLS_CHACHAPOLY_DECRYPT;
 
-        result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+        result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                                         ctx->iv,
                                                         mode );
         if ( result != 0 )
             return( result );
 
-        return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+        return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                                ad, ad_len ) );
     }
 #endif
@@ -391,7 +391,7 @@
     if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
     {
         *olen = ilen;
-        return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+        return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                            ilen, input, output ) );
     }
 #endif
@@ -924,7 +924,7 @@
         if ( tag_len != 16U )
             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
-        return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+        return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                            tag ) );
     }
 #endif
@@ -975,7 +975,7 @@
         if ( tag_len != sizeof( check_tag ) )
             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
-        ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+        ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                                      check_tag );
         if ( ret != 0 )
         {
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index 6dd8c5d..54572ef 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -1987,7 +1987,7 @@
     if( key_bitlen != 256U )
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
-    if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) )
+    if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context *)ctx, key ) )
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
     return( 0 );
diff --git a/library/debug.c b/library/debug.c
index c6788b6..da4ceac 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -71,7 +71,7 @@
      */
 #if defined(MBEDTLS_THREADING_C)
     char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
-    mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str );
+    mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void *)ssl, str );
     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr );
 #else
     ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
@@ -382,6 +382,8 @@
 
     while( crt != NULL )
     {
+        int ret;
+        mbedtls_pk_context *pk;
         char buf[1024];
 
         mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
@@ -390,7 +392,17 @@
         mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
         debug_print_line_by_line( ssl, level, file, line, buf );
 
-        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
+        ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
+        if( ret != 0 )
+        {
+            mbedtls_snprintf( str, sizeof( str ),
+                        "mbedtls_x509_crt_pk_acquire() failed with -%#04x\n",
+                        -ret );
+            debug_send_line( ssl, level, file, line, str );
+            return;
+        }
+        debug_print_pk( ssl, level, file, line, "crt->", pk );
+        mbedtls_x509_crt_pk_release( crt );
 
         crt = crt->next;
     }
diff --git a/library/ecjpake.c b/library/ecjpake.c
index be941b1..b276514 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -951,7 +951,7 @@
     0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
 };
 
-/* Load my private keys and generate the correponding public keys */
+/* Load my private keys and generate the corresponding public keys */
 static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
                               const unsigned char *xm1, size_t len1,
                               const unsigned char *xm2, size_t len2 )
diff --git a/library/error.c b/library/error.c
index 546fa49..f250fe4 100644
--- a/library/error.c
+++ b/library/error.c
@@ -571,7 +571,7 @@
         if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) )
             mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" );
         if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) )
-            mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" );
+            mbedtls_snprintf( buf, buflen, "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" );
 #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
         // END generated code
 
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 816b130..8d6c788 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -72,8 +72,8 @@
 #endif
 #endif /* _MSC_VER */
 
-#define read(fd,buf,len)        recv( fd, (char*)( buf ), (int)( len ), 0 )
-#define write(fd,buf,len)       send( fd, (char*)( buf ), (int)( len ), 0 )
+#define read(fd,buf,len)        recv( fd, (char *)( buf ), (int)( len ), 0 )
+#define write(fd,buf,len)       send( fd, (char *)( buf ), (int)( len ), 0 )
 #define close(fd)               closesocket(fd)
 
 static int wsa_init_done = 0;
@@ -284,7 +284,7 @@
     int err = errno;
 
     /*
-     * Never return 'WOULD BLOCK' on a non-blocking socket
+     * Never return 'WOULD BLOCK' on a blocking socket
      */
     if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
     {
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 17611d6..2749389 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -828,9 +828,7 @@
         return( MBEDTLS_ERR_SSL_NO_RNG );
     }
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+    if( mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE )
     {
         ssl->major_ver = ssl->conf->min_major_ver;
         ssl->minor_ver = ssl->conf->min_minor_ver;
@@ -882,36 +880,40 @@
      *   ..   . ..    extensions length (2 bytes)
      *   ..   . ..    extensions
      */
-    n = ssl->session_negotiate->id_len;
 
-    if( n < 16 || n > 32 ||
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
-#endif
-        ssl->handshake->resume == 0 )
+    /*
+     * We'll write a session of non-zero length if resumption was requested
+     * by the user, we're not renegotiating, and the session ID is of
+     * appropriate length. Otherwise make the length 0 (for now, see next code
+     * block for behaviour with tickets).
+     */
+    if( mbedtls_ssl_handshake_get_resume( ssl->handshake ) == 0 ||
+        mbedtls_ssl_get_renego_status( ssl ) != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
+        ssl->session_negotiate->id_len < 16 ||
+        ssl->session_negotiate->id_len > 32 )
     {
         n = 0;
     }
+    else
+    {
+        n = ssl->session_negotiate->id_len;
+    }
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     /*
      * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
      * generate and include a Session ID in the TLS ClientHello."
      */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+    if( mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
+        ssl->session_negotiate->ticket != NULL &&
+        ssl->session_negotiate->ticket_len != 0 )
     {
-        if( ssl->session_negotiate->ticket != NULL &&
-                ssl->session_negotiate->ticket_len != 0 )
-        {
-            ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 );
+        ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 );
 
-            if( ret != 0 )
-                return( ret );
+        if( ret != 0 )
+            return( ret );
 
-            ssl->session_negotiate->id_len = n = 32;
-        }
+        ssl->session_negotiate->id_len = n = 32;
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
@@ -985,9 +987,7 @@
     /*
      * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
      */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+    if( mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
         *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
@@ -1797,28 +1797,30 @@
 
     /*
      * Check if the session can be resumed
+     *
+     * We're only resuming a session if it was requested (handshake->resume
+     * already set to 1 by mbedtls_ssl_set_session()), and further conditions
+     * are satisfied (not renegotiating, ID and ciphersuite match, etc).
+     *
+     * Update handshake->resume to the value it will keep for the rest of the
+     * handshake, and that will be used to determine the relative order
+     * client/server last flights, as well as in handshake_wrapup().
      */
-    if( ssl->handshake->resume == 0 || n == 0 ||
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
-#endif
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+    if( n == 0 ||
+        mbedtls_ssl_get_renego_status( ssl ) != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
         ssl->session_negotiate->ciphersuite != i ||
         ssl->session_negotiate->compression != comp ||
         ssl->session_negotiate->id_len != n ||
         memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 )
     {
-        ssl->state++;
         ssl->handshake->resume = 0;
-#if defined(MBEDTLS_HAVE_TIME)
-        ssl->session_negotiate->start = mbedtls_time( NULL );
-#endif
-        ssl->session_negotiate->ciphersuite = i;
-        ssl->session_negotiate->compression = comp;
-        ssl->session_negotiate->id_len = n;
-        memcpy( ssl->session_negotiate->id, buf + 35, n );
     }
-    else
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
+
+    if( mbedtls_ssl_handshake_get_resume( ssl->handshake ) == 1 )
     {
+        /* Resume a session */
         ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
 
         if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
@@ -1829,9 +1831,21 @@
             return( ret );
         }
     }
+    else
+    {
+        /* Start a new session */
+        ssl->state++;
+#if defined(MBEDTLS_HAVE_TIME)
+        ssl->session_negotiate->start = mbedtls_time( NULL );
+#endif
+        ssl->session_negotiate->ciphersuite = i;
+        ssl->session_negotiate->compression = comp;
+        ssl->session_negotiate->id_len = n;
+        memcpy( ssl->session_negotiate->id, buf + 35, n );
+    }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
-                   ssl->handshake->resume ? "a" : "no" ) );
+               mbedtls_ssl_handshake_get_resume( ssl->handshake ) ? "a" : "no" ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) );
@@ -2059,7 +2073,8 @@
      * Renegotiation security checks
      */
     if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
@@ -2074,7 +2089,8 @@
     }
     else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
+             mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+               MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
         handshake_failure = 1;
@@ -2334,7 +2350,15 @@
         peer_pk = &ssl->handshake->peer_pubkey;
 #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
     if( ssl->session_negotiate->peer_cert != NULL )
-        peer_pk = &ssl->session_negotiate->peer_cert->pk;
+    {
+        ret = mbedtls_x509_crt_pk_acquire( ssl->session_negotiate->peer_cert,
+                                           &peer_pk );
+        if( ret != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+            return( ret );
+        }
+    }
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
     if( peer_pk == NULL )
@@ -2350,7 +2374,8 @@
     if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
-        return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
+        ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+        goto cleanup;
     }
 
     if( ( ret = mbedtls_pk_encrypt( peer_pk,
@@ -2360,7 +2385,7 @@
                             ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
-        return( ret );
+        goto cleanup;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
@@ -2373,11 +2398,16 @@
     }
 #endif
 
+cleanup:
+
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     /* We don't need the peer's public key anymore. Free it. */
     mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    return( 0 );
+#else
+    mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    return( ret );
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
@@ -2463,13 +2493,21 @@
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
-    peer_pk = &ssl->session_negotiate->peer_cert->pk;
+
+    ret = mbedtls_x509_crt_pk_acquire( ssl->session_negotiate->peer_cert,
+                                       &peer_pk );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+        return( ret );
+    }
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
     if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
-        return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
+        ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+        goto cleanup;
     }
 
     peer_key = mbedtls_pk_ec( *peer_pk );
@@ -2478,21 +2516,26 @@
                                  MBEDTLS_ECDH_THEIRS ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
-        return( ret );
+        goto cleanup;
     }
 
     if( ssl_check_server_ecdh_params( ssl ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
+        goto cleanup;
     }
 
+cleanup:
+
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     /* We don't need the peer's public key anymore. Free it,
      * so that more RAM is available for upcoming expensive
      * operations like ECDHE. */
     mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#else
+    mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
     return( ret );
 }
@@ -2799,7 +2842,14 @@
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
         }
-        peer_pk = &ssl->session_negotiate->peer_cert->pk;
+
+        ret = mbedtls_x509_crt_pk_acquire( ssl->session_negotiate->peer_cert,
+                                           &peer_pk );
+        if( ret != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+            return( ret );
+        }
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
         /*
@@ -2810,6 +2860,9 @@
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
             mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                             MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+            mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
             return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
         }
 
@@ -2831,6 +2884,9 @@
             if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
                 ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
 #endif
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+            mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
             return( ret );
         }
 
@@ -2839,7 +2895,9 @@
          * so that more RAM is available for upcoming expensive
          * operations like ECDHE. */
         mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#else
+        mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
     }
 #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index ecde1b0..66f25ea 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -55,7 +55,7 @@
                                  const unsigned char *info,
                                  size_t ilen )
 {
-    if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) != MBEDTLS_SSL_IS_SERVER )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
     mbedtls_free( ssl->cli_id );
@@ -791,15 +791,58 @@
 
     for( cur = list; cur != NULL; cur = cur->next )
     {
-        MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
-                          cur->cert );
+        int match = 1;
+        mbedtls_pk_context *pk;
 
-        if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
+        /* WARNING: With the current X.509 caching architecture, this MUST
+         * happen outside of the PK acquire/release block, because it moves
+         * the cached PK context. In a threading-enabled build, this would
+         * rightfully fail, but lead to a use-after-free otherwise. */
+        MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
+                               cur->cert );
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        /* ASYNC_PRIVATE may use a NULL entry for the opaque private key, so
+         * we have to use the public key context to infer the capabilities
+         * of the key. */
+        {
+            int ret;
+            ret = mbedtls_x509_crt_pk_acquire( cur->cert, &pk );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+                return( ret );
+            }
+        }
+#else
+        /* Outside of ASYNC_PRIVATE, use private key context directly
+         * instead of querying for the public key context from the
+         * certificate, so save a few bytes of code. */
+        pk = cur->key;
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+        if( ! mbedtls_pk_can_do( pk, pk_alg ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
-            continue;
+            match = 0;
         }
 
+#if defined(MBEDTLS_ECDSA_C)
+        if( pk_alg == MBEDTLS_PK_ECDSA &&
+            ssl_check_key_curve( pk, ssl->handshake->curves ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
+            match = 0;
+        }
+#endif
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        mbedtls_x509_crt_pk_release( cur->cert );
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+         if( match == 0 )
+            continue;
+
         /*
          * This avoids sending the client a cert it'll reject based on
          * keyUsage or other extensions.
@@ -816,31 +859,42 @@
             continue;
         }
 
-#if defined(MBEDTLS_ECDSA_C)
-        if( pk_alg == MBEDTLS_PK_ECDSA &&
-            ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
-            continue;
-        }
-#endif
-
+#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
+    defined(MBEDTLS_SSL_PROTO_TLS1_1)
         /*
          * Try to select a SHA-1 certificate for pre-1.2 clients, but still
          * present them a SHA-higher cert rather than failing if it's the only
          * one we got that satisfies the other conditions.
          */
-        if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 &&
-            cur->cert->sig_md != MBEDTLS_MD_SHA1 )
+        if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
         {
-            if( fallback == NULL )
-                fallback = cur;
+            mbedtls_md_type_t sig_md;
             {
+                int ret;
+                mbedtls_x509_crt_frame const *frame;
+                ret = mbedtls_x509_crt_frame_acquire( cur->cert, &frame );
+                if( ret != 0 )
+                {
+                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_frame_acquire", ret );
+                    return( ret );
+                }
+                sig_md = frame->sig_md;
+                mbedtls_x509_crt_frame_release( cur->cert );
+            }
+
+            if( sig_md != MBEDTLS_MD_SHA1 )
+            {
+                if( fallback == NULL )
+                    fallback = cur;
+
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: "
-                                    "sha-2 with pre-TLS 1.2 client" ) );
-            continue;
+                                            "sha-2 with pre-TLS 1.2 client" ) );
+                continue;
             }
         }
+#endif /* MBEDTLS_SSL_PROTO_TLS1   ||
+          MBEDTLS_SSL_PROTO_TLS1_1 ||
+          MBEDTLS_SSL_PROTO_SSL3 */
 
         /* If we get there, we got a winner */
         break;
@@ -1227,7 +1281,8 @@
      * SSLv2 Client Hello relevant renegotiation security checks
      */
     if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -1287,16 +1342,12 @@
      * otherwise read it ourselves manually in order to support SSLv2
      * ClientHello, which doesn't use the same record layer format.
      */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
+    if( mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
+        ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
     {
-        if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
-        {
-            /* No alert on a read error. */
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-            return( ret );
-        }
+        /* No alert on a read error. */
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
+        return( ret );
     }
 
     buf = ssl->in_hdr;
@@ -1351,11 +1402,8 @@
     /* For DTLS if this is the initial handshake, remember the client sequence
      * number to use it in our next message (RFC 6347 4.2.1) */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport )
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
-#endif
-        )
+    if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
+        mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE )
     {
         /* Epoch should be 0 for initial handshakes */
         if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 )
@@ -1525,7 +1573,7 @@
      */
 
     /*
-     * Minimal length (with everything empty and extensions ommitted) is
+     * Minimal length (with everything empty and extensions omitted) is
      * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
      * read at least up to session id length without worrying.
      */
@@ -1616,11 +1664,8 @@
                        buf + cookie_offset + 1, cookie_len );
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-        if( ssl->conf->f_cookie_check != NULL
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
-#endif
-            )
+        if( ssl->conf->f_cookie_check != NULL &&
+            mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE )
         {
             if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
                                      buf + cookie_offset + 1, cookie_len,
@@ -2004,7 +2049,8 @@
      * Renegotiation security checks
      */
     if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
@@ -2019,7 +2065,8 @@
     }
     else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
+             mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf )
+               == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
         handshake_failure = 1;
@@ -2637,15 +2684,14 @@
 
     MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     /*
      * Resume is 0  by default, see ssl_handshake_init().
      * It may be already set to 1 by ssl_parse_session_ticket_ext().
      * If not, try looking up session ID in our cache.
      */
-    if( ssl->handshake->resume == 0 &&
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
-#endif
+    if( mbedtls_ssl_handshake_get_resume( ssl->handshake ) == 0 &&
+        mbedtls_ssl_get_renego_status( ssl ) == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
         ssl->session_negotiate->id_len != 0 &&
         ssl->conf->f_get_cache != NULL &&
         ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 )
@@ -2653,8 +2699,25 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
         ssl->handshake->resume = 1;
     }
+#endif /* !MBEDTLS_SSL_NO_SESSION_CACHE */
 
-    if( ssl->handshake->resume == 0 )
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+    if( mbedtls_ssl_handshake_get_resume( ssl->handshake ) == 1 )
+    {
+        /*
+         * Resuming a session
+         */
+        n = ssl->session_negotiate->id_len;
+        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
+            return( ret );
+        }
+    }
+    else
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
     {
         /*
          * New session, create a new session id,
@@ -2681,20 +2744,6 @@
                 return( ret );
         }
     }
-    else
-    {
-        /*
-         * Resuming a session
-         */
-        n = ssl->session_negotiate->id_len;
-        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-
-        if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-            return( ret );
-        }
-    }
 
     /*
      *    38  .  38     session id length
@@ -2711,7 +2760,7 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
-                   ssl->handshake->resume ? "a" : "no" ) );
+            mbedtls_ssl_handshake_get_resume( ssl->handshake ) ? "a" : "no" ) );
 
     *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 );
     *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite      );
@@ -2848,7 +2897,7 @@
         authmode = ssl->handshake->sni_authmode;
     else
 #endif
-        authmode = ssl->conf->authmode;
+        authmode = mbedtls_ssl_conf_get_authmode( ssl->conf );
 
     if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ||
         authmode == MBEDTLS_SSL_VERIFY_NONE )
@@ -2944,7 +2993,8 @@
 
     total_dn_size = 0;
 
-    if( ssl->conf->cert_req_ca_list ==  MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
+    if( mbedtls_ssl_conf_get_cert_req_ca_list( ssl->conf )
+        == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
     {
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
         if( ssl->handshake->sni_ca_chain != NULL )
@@ -2953,26 +3003,38 @@
 #endif
             crt = ssl->conf->ca_chain;
 
-        while( crt != NULL && crt->version != 0 )
+        while( crt != NULL && crt->raw.p != NULL )
         {
-            dn_size = crt->subject_raw.len;
+            mbedtls_x509_crt_frame const *frame;
+            ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_frame_acquire", ret );
+                return( ret );
+            }
+
+            dn_size = frame->subject_raw.len;
 
             if( end < p ||
                 (size_t)( end - p ) < dn_size ||
                 (size_t)( end - p ) < 2 + dn_size )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
+                mbedtls_x509_crt_frame_release( crt );
                 break;
             }
 
             *p++ = (unsigned char)( dn_size >> 8 );
             *p++ = (unsigned char)( dn_size      );
-            memcpy( p, crt->subject_raw.p, dn_size );
+            memcpy( p, frame->subject_raw.p, dn_size );
             p += dn_size;
 
             MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size );
 
             total_dn_size += 2 + dn_size;
+
+            mbedtls_x509_crt_frame_release( crt );
+
             crt = crt->next;
         }
     }
@@ -3614,9 +3676,8 @@
                                       size_t peer_pmssize )
 {
     int ret;
+    size_t len = (size_t)( end - p ); /* Cast is safe because p <= end. */
     mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
-    mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
-    size_t len = mbedtls_pk_get_len( public_key );
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     /* If we have already started decoding the message and there is an ongoing
@@ -3634,12 +3695,17 @@
      */
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
     if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
     {
-        if ( p + 2 > end ) {
+        if( len < 2 )
+        {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
             return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
         }
+        len -= 2;
+
         if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
             *p++ != ( ( len      ) & 0xFF ) )
         {
@@ -3649,12 +3715,6 @@
     }
 #endif
 
-    if( p + len != end )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
     /*
      * Decrypt the premaster secret
      */
@@ -4194,7 +4254,15 @@
         peer_pk = &ssl->handshake->peer_pubkey;
 #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
     if( ssl->session_negotiate->peer_cert != NULL )
-        peer_pk = &ssl->session_negotiate->peer_cert->pk;
+    {
+        ret = mbedtls_x509_crt_pk_acquire( ssl->session_negotiate->peer_cert,
+                                           &peer_pk );
+        if( ret != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+            return( ret );
+        }
+    }
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
     if( peer_pk == NULL )
@@ -4209,7 +4277,7 @@
     if( 0 != ret )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
-        return( ret );
+        goto exit;
     }
 
     ssl->state++;
@@ -4219,7 +4287,8 @@
         ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+        goto exit;
     }
 
     i = mbedtls_ssl_hs_hdr_len( ssl );
@@ -4254,7 +4323,8 @@
         if( i + 2 > ssl->in_hslen )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+            goto exit;
         }
 
         /*
@@ -4266,7 +4336,8 @@
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
                                 " for verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+            goto exit;
         }
 
 #if !defined(MBEDTLS_MD_SHA1)
@@ -4287,7 +4358,8 @@
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
                                 " for verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+            goto exit;
         }
 
         /*
@@ -4296,7 +4368,8 @@
         if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+            goto exit;
         }
 
         i++;
@@ -4311,7 +4384,8 @@
     if( i + 2 > ssl->in_hslen )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+        goto exit;
     }
 
     sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1];
@@ -4320,7 +4394,8 @@
     if( i + sig_len != ssl->in_hslen )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY;
+        goto exit;
     }
 
     /* Calculate hash and verify signature */
@@ -4334,13 +4409,19 @@
                            ssl->in_msg + i, sig_len ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
-        return( ret );
+        goto exit;
     }
 
     mbedtls_ssl_update_handshake_status( ssl );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
 
+exit:
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    mbedtls_x509_crt_pk_release( ssl->session_negotiate->peer_cert );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
     return( ret );
 }
 #endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index fff20ff..91b944c 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -117,6 +117,9 @@
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
 /* Top-level Connection ID API */
 
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    !defined(MBEDTLS_SSL_CONF_CID_LEN) &&      \
+    !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
 int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf,
                           size_t len,
                           int ignore_other_cid )
@@ -134,6 +137,21 @@
     conf->cid_len = len;
     return( 0 );
 }
+#else  /* MBEDTLS_SSL_DTLS_CONNECTION_ID &&
+          !MBEDTLS_SSL_CONF_CID_LEN &&
+          !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
+
+#if MBEDTLS_SSL_CONF_CID_LEN > MBEDTLS_SSL_CID_IN_LEN_MAX
+#error "Invalid hardcoded value for MBEDTLS_SSL_CONF_CID_LEN"
+#endif
+#if MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE && \
+    MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID != MBEDTLS_SSL_UNEXPECTED_CID_FAIL
+#error "Invalid hardcoded value for MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID"
+#endif
+
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID &&
+          !MBEDTLS_SSL_CONF_CID_LEN &&
+          !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 
 int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl,
                          int enable,
@@ -152,11 +170,11 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) );
     MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len );
 
-    if( own_cid_len != ssl->conf->cid_len )
+    if( own_cid_len != mbedtls_ssl_conf_get_cid_len( ssl->conf ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config",
                                     (unsigned) own_cid_len,
-                                    (unsigned) ssl->conf->cid_len ) );
+                                    (unsigned) mbedtls_ssl_conf_get_cid_len( ssl->conf ) ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
@@ -300,8 +318,11 @@
 {
     uint32_t new_timeout;
 
-    if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
+    if( ssl->handshake->retransmit_timeout >=
+        mbedtls_ssl_conf_get_hs_timeout_max( ssl->conf ) )
+    {
         return( -1 );
+    }
 
     /* Implement the final paragraph of RFC 6347 section 4.1.1.1
      * in the following way: after the initial transmission and a first
@@ -309,7 +330,8 @@
      * This value is guaranteed to be deliverable (if not guaranteed to be
      * delivered) of any compliant IPv4 (and IPv6) network, and should work
      * on most non-IP stacks too. */
-    if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
+    if( ssl->handshake->retransmit_timeout !=
+        mbedtls_ssl_conf_get_hs_timeout_min( ssl->conf ) )
     {
         ssl->handshake->mtu = 508;
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
@@ -319,9 +341,9 @@
 
     /* Avoid arithmetic overflow and range overflow */
     if( new_timeout < ssl->handshake->retransmit_timeout ||
-        new_timeout > ssl->conf->hs_timeout_max )
+        new_timeout > mbedtls_ssl_conf_get_hs_timeout_max( ssl->conf ) )
     {
-        new_timeout = ssl->conf->hs_timeout_max;
+        new_timeout = mbedtls_ssl_conf_get_hs_timeout_max( ssl->conf );
     }
 
     ssl->handshake->retransmit_timeout = new_timeout;
@@ -333,7 +355,7 @@
 
 static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
 {
-    ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
+    ssl->handshake->retransmit_timeout = mbedtls_ssl_conf_get_hs_timeout_min( ssl->conf );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
                         ssl->handshake->retransmit_timeout ) );
 }
@@ -1263,11 +1285,13 @@
     (void) ssl;
 #endif
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
     if( handshake->resume != 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
         return( 0 );
     }
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
 
     MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster,
                                                   handshake->pmslen );
@@ -1366,7 +1390,7 @@
                                   ssl->handshake->tls_prf,
                                   ssl->handshake->randbytes,
                                   ssl->minor_ver,
-                                  ssl->conf->endpoint,
+                                  mbedtls_ssl_conf_get_endpoint( ssl->conf ),
                                   ssl );
     if( ret != 0 )
     {
@@ -2993,7 +3017,9 @@
      * timeout if we were using the usual handshake doubling scheme */
     if( ssl->conf->renego_max_records < 0 )
     {
-        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;
+        uint32_t ratio =
+            mbedtls_ssl_conf_get_hs_timeout_max( ssl->conf ) /
+            mbedtls_ssl_conf_get_hs_timeout_min( ssl->conf ) + 1;
         unsigned char doublings = 1;
 
         while( ratio != 0 )
@@ -3107,7 +3133,7 @@
         }
 
         /*
-         * A record can't be split accross datagrams. If we need to read but
+         * A record can't be split across datagrams. If we need to read but
          * are not at the beginning of a new record, the caller did something
          * wrong.
          */
@@ -3134,7 +3160,7 @@
             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
                 timeout = ssl->handshake->retransmit_timeout;
             else
-                timeout = ssl->conf->read_timeout;
+                timeout = mbedtls_ssl_conf_get_read_timeout( ssl->conf );
 
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) );
 
@@ -3172,7 +3198,8 @@
                 return( MBEDTLS_ERR_SSL_WANT_READ );
             }
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-            else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+            else if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                       MBEDTLS_SSL_IS_SERVER &&
                      ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
             {
                 if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 )
@@ -3209,8 +3236,8 @@
                 if( ssl->f_recv_timeout != NULL )
                 {
                     ret = ssl->f_recv_timeout( ssl->p_bio,
-                                               ssl->in_hdr + ssl->in_left, len,
-                                               ssl->conf->read_timeout );
+                             ssl->in_hdr + ssl->in_left, len,
+                             mbedtls_ssl_conf_get_read_timeout( ssl->conf ) );
                 }
                 else
                 {
@@ -3698,7 +3725,8 @@
 #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
         if( ! ( ssl->minor_ver      == MBEDTLS_SSL_MINOR_VERSION_0 &&
                 ssl->out_msgtype    == MBEDTLS_SSL_MSG_ALERT       &&
-                ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
+                mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                  MBEDTLS_SSL_IS_CLIENT ) )
 #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@@ -4322,8 +4350,11 @@
     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
     uint64_t bit;
 
-    if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+    if( mbedtls_ssl_conf_get_anti_replay( ssl->conf ) ==
+        MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+    {
         return( 0 );
+    }
 
     if( rec_seqnum > ssl->in_window_top )
         return( 0 );
@@ -4346,8 +4377,11 @@
 {
     uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
 
-    if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+    if( mbedtls_ssl_conf_get_anti_replay( ssl->conf ) ==
+        MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+    {
         return;
+    }
 
     if( rec_seqnum > ssl->in_window_top )
     {
@@ -4611,7 +4645,7 @@
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
         ssl->in_msgtype      == MBEDTLS_SSL_MSG_CID            &&
-        ssl->conf->cid_len   != 0 )
+        mbedtls_ssl_conf_get_cid_len( ssl->conf ) != 0 )
     {
         /* Shift pointers to account for record header including CID
          * struct {
@@ -4628,7 +4662,7 @@
 
         /* So far, we only support static CID lengths
          * fixed in the configuration. */
-        ssl->in_len = ssl->in_cid + ssl->conf->cid_len;
+        ssl->in_len = ssl->in_cid + mbedtls_ssl_conf_get_cid_len( ssl->conf );
         ssl->in_iv  = ssl->in_msg = ssl->in_len + 2;
     }
     else
@@ -4724,7 +4758,8 @@
              * have an active transform (possibly iv_len != 0), so use the
              * fact that the record header len is 13 instead.
              */
-            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+            if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                  MBEDTLS_SSL_IS_SERVER &&
                 ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
                 rec_epoch == 0 &&
                 ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
@@ -4857,8 +4892,8 @@
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
-                ssl->conf->ignore_unexpected_cid
-                    == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
+                mbedtls_ssl_conf_get_ignore_unexpected_cid( ssl->conf )
+                  == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
@@ -5774,8 +5809,8 @@
                 }
 
 #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-                if( ssl->conf->badmac_limit != 0 &&
-                    ++ssl->badmac_seen >= ssl->conf->badmac_limit )
+                if( mbedtls_ssl_conf_get_badmac_limit( ssl->conf ) != 0 &&
+                    ++ssl->badmac_seen >= mbedtls_ssl_conf_get_badmac_limit( ssl->conf ) )
                 {
                     MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
                     return( MBEDTLS_ERR_SSL_INVALID_MAC );
@@ -5907,7 +5942,8 @@
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
         if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
-            ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+            mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_SERVER &&
             ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
             ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
         {
@@ -6074,7 +6110,8 @@
     }
 
 #if defined(MBEDTLS_SSL_CLI_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+          MBEDTLS_SSL_IS_CLIENT )
     {
         if( ssl->client_auth == 0 )
         {
@@ -6103,7 +6140,7 @@
     }
 #endif /* MBEDTLS_SSL_CLI_C */
 #if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
     {
         if( mbedtls_ssl_own_cert( ssl ) == NULL )
         {
@@ -6307,7 +6344,8 @@
         /* Check if we're handling the first CRT in the chain. */
 #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
         if( crt_cnt++ == 0 &&
-            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+            mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_CLIENT &&
             ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
         {
             /* During client-side renegotiation, check that the server's
@@ -6373,7 +6411,7 @@
 #if defined(MBEDTLS_SSL_SRV_C)
 static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
 {
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_CLIENT )
         return( -1 );
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
@@ -6431,7 +6469,7 @@
         return( SSL_CERTIFICATE_SKIP );
 
 #if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
     {
         if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
             return( SSL_CERTIFICATE_SKIP );
@@ -6455,7 +6493,7 @@
                                          mbedtls_x509_crt *chain,
                                          void *rs_ctx )
 {
-    int ret = 0;
+    int verify_ret;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
         ssl->handshake->ciphersuite_info;
     mbedtls_x509_crt *ca_chain;
@@ -6480,7 +6518,7 @@
     /*
      * Main check: verify certificate
      */
-    ret = mbedtls_x509_crt_verify_restartable(
+    verify_ret = mbedtls_x509_crt_verify_restartable(
         chain,
         ca_chain, ca_crl,
         ssl->conf->cert_profile,
@@ -6488,13 +6526,13 @@
         &ssl->session_negotiate->verify_result,
         ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
 
-    if( ret != 0 )
+    if( verify_ret != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", verify_ret );
     }
 
 #if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
-    if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+    if( verify_ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
         return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
 #endif
 
@@ -6504,29 +6542,41 @@
 
 #if defined(MBEDTLS_ECP_C)
     {
-        const mbedtls_pk_context *pk = &chain->pk;
+        int ret;
+        mbedtls_pk_context *pk;
+        ret = mbedtls_x509_crt_pk_acquire( chain, &pk );
+        if( ret != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_x509_crt_pk_acquire", ret );
+            return( ret );
+        }
 
         /* If certificate uses an EC key, make sure the curve is OK */
-        if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
-            mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
+        if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) )
+            ret = mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id );
+
+        mbedtls_x509_crt_pk_release( chain );
+
+        if( ret != 0 )
         {
             ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
 
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
-            if( ret == 0 )
-                ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
+            if( verify_ret == 0 )
+                verify_ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
         }
     }
 #endif /* MBEDTLS_ECP_C */
 
     if( mbedtls_ssl_check_cert_usage( chain,
                                       ciphersuite_info,
-                                      ! ssl->conf->endpoint,
+                                      ( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                                        MBEDTLS_SSL_IS_CLIENT ),
                                       &ssl->session_negotiate->verify_result ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
-        if( ret == 0 )
-            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
+        if( verify_ret == 0 )
+            verify_ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
     }
 
     /* mbedtls_x509_crt_verify_with_profile is supposed to report a
@@ -6536,19 +6586,19 @@
      * functions, are treated as fatal and lead to a failure of
      * ssl_parse_certificate even if verification was optional. */
     if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
-        ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
-          ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
+        ( verify_ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+          verify_ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
     {
-        ret = 0;
+        verify_ret = 0;
     }
 
     if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
-        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+        verify_ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
     }
 
-    if( ret != 0 )
+    if( verify_ret != 0 )
     {
         uint8_t alert;
 
@@ -6593,7 +6643,7 @@
     }
 #endif /* MBEDTLS_DEBUG_C */
 
-    return( ret );
+    return( verify_ret );
 }
 
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@@ -6658,9 +6708,9 @@
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
     const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
                        ? ssl->handshake->sni_authmode
-                       : ssl->conf->authmode;
+                       : mbedtls_ssl_conf_get_authmode( ssl->conf );
 #else
-    const int authmode = ssl->conf->authmode;
+    const int authmode = mbedtls_ssl_conf_get_authmode( ssl->conf );
 #endif
     void *rs_ctx = NULL;
     mbedtls_x509_crt *chain = NULL;
@@ -6760,8 +6810,8 @@
         crt_len   = chain->raw.len;
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-        pk_start = chain->pk_raw.p;
-        pk_len   = chain->pk_raw.len;
+        pk_start = chain->cache->pk_raw.p;
+        pk_len   = chain->cache->pk_raw.len;
 
         /* Free the CRT structures before computing
          * digest and copying the peer's public key. */
@@ -7273,8 +7323,6 @@
 
 void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl )
 {
-    int resume = ssl->handshake->resume;
-
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) );
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -7302,16 +7350,18 @@
     ssl->session = ssl->session_negotiate;
     ssl->session_negotiate = NULL;
 
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     /*
      * Add cache entry
      */
     if( ssl->conf->f_set_cache != NULL &&
         ssl->session->id_len != 0 &&
-        resume == 0 )
+        ssl->handshake->resume == 0 )
     {
         if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 )
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) );
     }
+#endif /* MBEDTLS_SSL_SRV_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
@@ -7341,7 +7391,8 @@
 
     ssl_update_out_pointers( ssl, ssl->transform_negotiate );
 
-    ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
+    ssl->handshake->calc_finished( ssl, ssl->out_msg + 4,
+                                   mbedtls_ssl_conf_get_endpoint( ssl->conf ) );
 
     /*
      * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
@@ -7360,6 +7411,7 @@
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
     /*
      * In case of session resuming, invert the client and server
      * ChangeCipherSpec messages order.
@@ -7367,15 +7419,22 @@
     if( ssl->handshake->resume != 0 )
     {
 #if defined(MBEDTLS_SSL_CLI_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_CLIENT )
+        {
             ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+        }
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_SERVER )
+        {
             ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
+        }
 #endif
     }
     else
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
         ssl->state++;
 
     /*
@@ -7469,7 +7528,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
 
-    ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
+    ssl->handshake->calc_finished( ssl, buf,
+                             mbedtls_ssl_conf_get_endpoint( ssl->conf ) ^ 1 );
 
     if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
@@ -7516,18 +7576,20 @@
     memcpy( ssl->peer_verify_data, buf, hash_len );
 #endif
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
     if( ssl->handshake->resume != 0 )
     {
 #if defined(MBEDTLS_SSL_CLI_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_CLIENT )
             ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
             ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
 #endif
     }
     else
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
         ssl->state++;
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -7672,7 +7734,7 @@
     {
         ssl->handshake->alt_transform_out = ssl->transform_out;
 
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_CLIENT )
             ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
         else
             ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
@@ -8044,29 +8106,34 @@
 /*
  * SSL set accessors
  */
+#if !defined(MBEDTLS_SSL_CONF_ENDPOINT)
 void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint )
 {
     conf->endpoint   = endpoint;
 }
+#endif /* MBEDTLS_SSL_CONF_ENDPOINT */
 
 void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport )
 {
     conf->transport = transport;
 }
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
+    !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
 void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode )
 {
-    conf->anti_replay = mode;
+    conf->anti_replay   = mode;
 }
-#endif
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY && !MBEDTLS_SSL_CONF_ANTI_REPLAY */
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit )
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
+    !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
+void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf,
+                                         unsigned limit )
 {
     conf->badmac_limit = limit;
 }
-#endif
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT && !MBEDTLS_SSL_CONF_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
@@ -8076,17 +8143,36 @@
     ssl->disable_datagram_packing = !allow_packing;
 }
 
+#if !( defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX) &&      \
+       defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN) )
 void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
                                          uint32_t min, uint32_t max )
 {
     conf->hs_timeout_min = min;
     conf->hs_timeout_max = max;
 }
-#endif
+#else /* !( MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN &&
+            MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX ) */
+void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
+                                         uint32_t min, uint32_t max )
+{
+    ((void) conf);
+    ((void) min);
+    ((void) max);
+}
+#endif /* MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN &&
+          MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode )
 {
-    conf->authmode   = authmode;
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
+    conf->authmode = authmode;
+#else
+    ((void) conf);
+    ((void) authmode);
+#endif /* MBEDTLS_SSL_CONF_AUTHMODE */
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -8134,10 +8220,12 @@
 }
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
 void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
 {
     conf->read_timeout   = timeout;
 }
+#endif /* MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
 void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
                                void *p_timer,
@@ -8152,7 +8240,7 @@
     ssl_set_timer( ssl, 0 );
 }
 
-#if defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
 void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf,
         void *p_cache,
         int (*f_get_cache)(void *, mbedtls_ssl_session *),
@@ -8162,9 +8250,9 @@
     conf->f_get_cache = f_get_cache;
     conf->f_set_cache = f_set_cache;
 }
-#endif /* MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SRV_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
-#if defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
 int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session )
 {
     int ret;
@@ -8172,7 +8260,7 @@
     if( ssl == NULL ||
         session == NULL ||
         ssl->session_negotiate == NULL ||
-        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT )
+        mbedtls_ssl_conf_get_endpoint( ssl->conf ) != MBEDTLS_SSL_IS_CLIENT )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
@@ -8185,7 +8273,7 @@
 
     return( 0 );
 }
-#endif /* MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C && !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
 
 void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf,
                                    const int *ciphersuites )
@@ -8300,7 +8388,7 @@
     if( ssl->handshake == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
         role = MBEDTLS_ECJPAKE_SERVER;
     else
         role = MBEDTLS_ECJPAKE_CLIENT;
@@ -8594,7 +8682,7 @@
 }
 #endif
 
-#if defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
 void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
                                           char cert_req_ca_list )
 {
@@ -8661,10 +8749,12 @@
 }
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
 void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy )
 {
     conf->allow_legacy_renegotiation = allow_legacy;
 }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
 void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation )
@@ -8968,7 +9058,7 @@
 static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
 {
     /* Return unlimited mtu for client hello messages to avoid fragmentation. */
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_CLIENT &&
         ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
           ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
         return ( 0 );
@@ -9050,7 +9140,7 @@
     if( ssl == NULL ||
         dst == NULL ||
         ssl->session == NULL ||
-        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT )
+        mbedtls_ssl_conf_get_endpoint( ssl->conf ) != MBEDTLS_SSL_IS_CLIENT )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
@@ -9634,11 +9724,11 @@
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
 #if defined(MBEDTLS_SSL_CLI_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_CLIENT )
         ret = mbedtls_ssl_handshake_client_step( ssl );
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
         ret = mbedtls_ssl_handshake_server_step( ssl );
 #endif
 
@@ -9721,10 +9811,15 @@
     if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
         ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
     {
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_SERVER )
+        {
             ssl->handshake->out_msg_seq = 1;
+        }
         else
+        {
             ssl->handshake->in_msg_seq = 1;
+        }
     }
 #endif
 
@@ -9755,7 +9850,7 @@
 
 #if defined(MBEDTLS_SSL_SRV_C)
     /* On server, just send the request */
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) == MBEDTLS_SSL_IS_SERVER )
     {
         if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -9898,7 +9993,8 @@
         if( ssl->f_get_timer != NULL &&
             ssl->f_get_timer( ssl->p_timer ) == -1 )
         {
-            ssl_set_timer( ssl, ssl->conf->read_timeout );
+            ssl_set_timer( ssl,
+                           mbedtls_ssl_conf_get_read_timeout( ssl->conf ) );
         }
 
         if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
@@ -9937,7 +10033,8 @@
              */
 
 #if defined(MBEDTLS_SSL_CLI_C)
-            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+            if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                  MBEDTLS_SSL_IS_CLIENT &&
                 ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
                   ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) ) )
             {
@@ -9960,7 +10057,8 @@
 #endif /* MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_SSL_SRV_C)
-            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+            if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                  MBEDTLS_SSL_IS_SERVER &&
                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
@@ -9985,7 +10083,7 @@
             /* Determine whether renegotiation attempt should be accepted */
             if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
                     ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-                      ssl->conf->allow_legacy_renegotiation ==
+                      mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
                                                    MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
             {
                 /*
@@ -9995,7 +10093,8 @@
                 /* DTLS clients need to know renego is server-initiated */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
                 if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
-                    ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+                    mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+                      MBEDTLS_SSL_IS_CLIENT )
                 {
                     ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
                 }
@@ -10108,7 +10207,8 @@
          * Do it now, after setting in_offt, to avoid taking this branch
          * again if ssl_write_hello_request() returns WANT_WRITE */
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+        if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+              MBEDTLS_SSL_IS_SERVER &&
             ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
         {
             if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 )
@@ -10677,8 +10777,12 @@
 
 #if defined(MBEDTLS_ECP_C)
 static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = {
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
     MBEDTLS_ECP_DP_SECP256R1,
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
     MBEDTLS_ECP_DP_SECP384R1,
+#endif
     MBEDTLS_ECP_DP_NONE
 };
 #endif
@@ -10704,7 +10808,9 @@
 #if defined(MBEDTLS_SSL_CLI_C)
     if( endpoint == MBEDTLS_SSL_IS_CLIENT )
     {
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
         conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
+#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
         conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED;
 #endif
@@ -10738,18 +10844,25 @@
     conf->f_cookie_check = ssl_cookie_check_dummy;
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
+    !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
     conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED;
 #endif
 
 #if defined(MBEDTLS_SSL_SRV_C)
+#if !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
     conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;
-#endif
+#endif /* !MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
+#endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN)
     conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;
+#endif /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN */
+#if !defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX)
     conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
-#endif
+#endif /* !MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;
diff --git a/library/timing.c b/library/timing.c
index 413d133..009516a 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -51,7 +51,6 @@
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
 #include <windows.h>
-#include <winbase.h>
 #include <process.h>
 
 struct _hr_time
diff --git a/library/version_features.c b/library/version_features.c
index 5e9d923..3753864 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -87,6 +87,9 @@
 #if defined(MBEDTLS_CHECK_PARAMS)
     "MBEDTLS_CHECK_PARAMS",
 #endif /* MBEDTLS_CHECK_PARAMS */
+#if defined(MBEDTLS_CHECK_PARAMS_ASSERT)
+    "MBEDTLS_CHECK_PARAMS_ASSERT",
+#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */
 #if defined(MBEDTLS_TIMING_ALT)
     "MBEDTLS_TIMING_ALT",
 #endif /* MBEDTLS_TIMING_ALT */
@@ -513,6 +516,12 @@
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     "MBEDTLS_SSL_SESSION_TICKETS",
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
+#if defined(MBEDTLS_SSL_NO_SESSION_CACHE)
+    "MBEDTLS_SSL_NO_SESSION_CACHE",
+#endif /* MBEDTLS_SSL_NO_SESSION_CACHE */
+#if defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+    "MBEDTLS_SSL_NO_SESSION_RESUMPTION",
+#endif /* MBEDTLS_SSL_NO_SESSION_RESUMPTION */
 #if defined(MBEDTLS_SSL_EXPORT_KEYS)
     "MBEDTLS_SSL_EXPORT_KEYS",
 #endif /* MBEDTLS_SSL_EXPORT_KEYS */
@@ -534,6 +543,12 @@
 #if defined(MBEDTLS_VERSION_FEATURES)
     "MBEDTLS_VERSION_FEATURES",
 #endif /* MBEDTLS_VERSION_FEATURES */
+#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    "MBEDTLS_X509_ON_DEMAND_PARSING",
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
+    "MBEDTLS_X509_ALWAYS_FLUSH",
+#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
 #if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
     "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3",
 #endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */
diff --git a/library/x509.c b/library/x509.c
index 858dd90..0d2b9ef 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_X509_USE_C)
 
 #include "mbedtls/x509.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/oid.h"
 
@@ -123,7 +124,7 @@
 }
 
 /*
- * Parse an algorithm identifier with (optional) paramaters
+ * Parse an algorithm identifier with (optional) parameters
  */
 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
                   mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
@@ -347,64 +348,59 @@
  *  AttributeType ::= OBJECT IDENTIFIER
  *
  *  AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ *  NOTE: This function returns an ASN.1 low-level error code.
  */
 static int x509_get_attr_type_value( unsigned char **p,
                                      const unsigned char *end,
-                                     mbedtls_x509_name *cur )
+                                     mbedtls_x509_buf *oid,
+                                     mbedtls_x509_buf *val )
 {
     int ret;
     size_t len;
-    mbedtls_x509_buf *oid;
-    mbedtls_x509_buf *val;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+    ret = mbedtls_asn1_get_tag( p, end, &len,
+                                MBEDTLS_ASN1_CONSTRUCTED |
+                                MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        goto exit;
 
     end = *p + len;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID );
+    if( ret != 0 )
+        goto exit;
 
-    oid = &cur->oid;
-    oid->tag = **p;
-
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
-
+    oid->tag = MBEDTLS_ASN1_OID;
     oid->p = *p;
     *p += oid->len;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if( *p == end )
+    {
+        ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+        goto exit;
+    }
 
-    if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
-        **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
-        **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
-        **p != MBEDTLS_ASN1_BIT_STRING )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+    if( !MBEDTLS_ASN1_IS_STRING_TAG( **p ) )
+    {
+        ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
+        goto exit;
+    }
 
-    val = &cur->val;
     val->tag = *(*p)++;
 
-    if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+    ret = mbedtls_asn1_get_len( p, end, &val->len );
+    if( ret != 0 )
+        goto exit;
 
     val->p = *p;
     *p += val->len;
 
     if( *p != end )
-    {
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
 
-    cur->next = NULL;
-
-    return( 0 );
+exit:
+    return( ret );
 }
 
 /*
@@ -429,58 +425,235 @@
  * For the general case we still use a flat list, but we mark elements of the
  * same set so that they are "merged" together in the functions that consume
  * this list, eg mbedtls_x509_dn_gets().
+ *
+ * NOTE: This function returns an ASN.1 low-level error code.
  */
-int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
-                   mbedtls_x509_name *cur )
+static int x509_set_sequence_iterate( unsigned char **p,
+                                      unsigned char const **end_set,
+                                      unsigned char const *end,
+                                      mbedtls_x509_buf *oid,
+                                      mbedtls_x509_buf *val )
 {
     int ret;
     size_t set_len;
-    const unsigned char *end_set;
 
-    /* don't use recursion, we'd risk stack overflow if not optimized */
-    while( 1 )
+    if( *p == *end_set )
     {
-        /*
-         * parse SET
-         */
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+        /* Parse next TLV of ASN.1 SET structure. */
+        ret = mbedtls_asn1_get_tag( p, end, &set_len,
+                                    MBEDTLS_ASN1_CONSTRUCTED |
+                                    MBEDTLS_ASN1_SET );
+        if( ret != 0 )
+            goto exit;
 
-        end_set  = *p + set_len;
+        *end_set = *p + set_len;
+    }
 
-        while( 1 )
+    /* x509_get_attr_type_value() returns ASN.1 low-level error codes. */
+    ret = x509_get_attr_type_value( p, *end_set, oid, val );
+
+exit:
+    return( ret );
+}
+
+/*
+ * Like memcmp, but case-insensitive and always returns -1 if different
+ */
+int mbedtls_x509_memcasecmp( const void *s1, const void *s2,
+                             size_t len1, size_t len2 )
+{
+    size_t i;
+    unsigned char diff;
+    const unsigned char *n1 = s1, *n2 = s2;
+
+    if( len1 != len2 )
+        return( -1 );
+
+    for( i = 0; i < len1; i++ )
+    {
+        diff = n1[i] ^ n2[i];
+
+        if( diff == 0 )
+            continue;
+
+        if( diff == 32 &&
+            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
         {
-            if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
-                return( ret );
-
-            if( *p == end_set )
-                break;
-
-            /* Mark this item as being no the only one in a set */
-            cur->next_merged = 1;
-
-            cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
-
-            if( cur->next == NULL )
-                return( MBEDTLS_ERR_X509_ALLOC_FAILED );
-
-            cur = cur->next;
+            continue;
         }
 
-        /*
-         * continue until end of SEQUENCE is reached
-         */
-        if( *p == end )
-            return( 0 );
+        return( -1 );
+    }
 
+    return( 0 );
+}
+
+/*
+ * Compare two X.509 strings, case-insensitive, and allowing for some encoding
+ * variations (but not all).
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_string_cmp( const mbedtls_x509_buf *a,
+                            const mbedtls_x509_buf *b )
+{
+    if( a->tag == b->tag &&
+        a->len == b->len &&
+        memcmp( a->p, b->p, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+        ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+        mbedtls_x509_memcasecmp( a->p, b->p,
+                                 a->len, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    return( -1 );
+}
+
+/*
+ * Compare two X.509 Names (aka rdnSequence) given as raw ASN.1 data.
+ *
+ * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
+ * We sometimes return unequal when the full algorithm would return equal,
+ * but never the other way. (In particular, we don't do Unicode normalisation
+ * or space folding.)
+ *
+ * Further, this function allows to pass a callback to be triggered for every
+ * pair of well-formed and equal entries in the two input name lists.
+ *
+ * Returns:
+ * - 0 if both sequences are well-formed, present the same X.509 name,
+ *   and the callback (if provided) hasn't returned a non-zero value
+ *   on any of the name components.
+ * - 1 if a difference was detected in the name components.
+ * - A non-zero error code if the abort callback returns a non-zero value.
+ *   In this case, the returned error code is the error code from the callback.
+ * - A negative error code if a parsing error occurred in either
+ *   of the two buffers.
+ *
+ * This function can be used to verify that a buffer contains a well-formed
+ * ASN.1 encoded X.509 name by calling it with equal parameters.
+ */
+int mbedtls_x509_name_cmp_raw( mbedtls_x509_buf_raw const *a,
+                               mbedtls_x509_buf_raw const *b,
+                               int (*abort_check)( void *ctx,
+                                                   mbedtls_x509_buf *oid,
+                                                   mbedtls_x509_buf *val,
+                                                   int next_merged ),
+                               void *abort_check_ctx )
+{
+    int ret;
+    size_t idx;
+    unsigned char *p[2], *end[2], *set[2];
+
+    p[0] = a->p;
+    p[1] = b->p;
+    end[0] = p[0] + a->len;
+    end[1] = p[1] + b->len;
+
+    for( idx = 0; idx < 2; idx++ )
+    {
+        size_t len;
+        ret = mbedtls_asn1_get_tag( &p[idx], end[idx], &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED |
+                                    MBEDTLS_ASN1_SEQUENCE );
+
+        if( end[idx] != p[idx] + len )
+        {
+            return( MBEDTLS_ERR_X509_INVALID_NAME +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        }
+
+        set[idx] = p[idx];
+    }
+
+    while( 1 )
+    {
+        int next_merged;
+        mbedtls_x509_buf oid[2], val[2];
+
+        ret = x509_set_sequence_iterate( &p[0], (const unsigned char **) &set[0],
+                                         end[0], &oid[0], &val[0] );
+        if( ret != 0 )
+            goto exit;
+
+        ret = x509_set_sequence_iterate( &p[1], (const unsigned char **) &set[1],
+                                         end[1], &oid[1], &val[1] );
+        if( ret != 0 )
+            goto exit;
+
+        if( oid[0].len != oid[1].len ||
+            memcmp( oid[0].p, oid[1].p, oid[1].len ) != 0 )
+        {
+            return( 1 );
+        }
+
+        if( x509_string_cmp( &val[0], &val[1] ) != 0 )
+            return( 1 );
+
+        next_merged = ( set[0] != p[0] );
+        if( next_merged != ( set[1] != p[1] ) )
+            return( 1 );
+
+        if( abort_check != NULL )
+        {
+            ret = abort_check( abort_check_ctx, &oid[0], &val[0],
+                               next_merged );
+            if( ret != 0 )
+                return( ret );
+        }
+
+        if( p[0] == end[0] && p[1] == end[1] )
+            break;
+    }
+
+exit:
+    if( ret < 0 )
+        ret += MBEDTLS_ERR_X509_INVALID_NAME;
+
+    return( ret );
+}
+
+static int x509_get_name_cb( void *ctx,
+                             mbedtls_x509_buf *oid,
+                             mbedtls_x509_buf *val,
+                             int next_merged )
+{
+    mbedtls_x509_name **cur_ptr = (mbedtls_x509_name**) ctx;
+    mbedtls_x509_name *cur = *cur_ptr;
+
+    if( cur->oid.p != NULL )
+    {
         cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
-
         if( cur->next == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+            return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
 
         cur = cur->next;
     }
+
+    cur->oid = *oid;
+    cur->val = *val;
+    cur->next_merged = next_merged;
+
+    *cur_ptr = cur;
+    return( 0 );
+}
+
+int mbedtls_x509_get_name( unsigned char *p,
+                           size_t len,
+                           mbedtls_x509_name *cur )
+{
+    mbedtls_x509_buf_raw name_buf = { p, len };
+    memset( cur, 0, sizeof( mbedtls_x509_name ) );
+    return( mbedtls_x509_name_cmp_raw( &name_buf, &name_buf,
+                                       x509_get_name_cb,
+                                       &cur ) );
 }
 
 static int x509_parse_int( unsigned char **p, size_t n, int *res )
@@ -655,6 +828,21 @@
     return( 0 );
 }
 
+int mbedtls_x509_get_sig_alg_raw( unsigned char **p, unsigned char const *end,
+                                  mbedtls_md_type_t *md_alg,
+                                  mbedtls_pk_type_t *pk_alg,
+                                  void **sig_opts )
+{
+    int ret;
+    mbedtls_asn1_buf alg, params;
+    ret = mbedtls_asn1_get_alg( p, end, &alg, &params );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+
+    return( mbedtls_x509_get_sig_alg( &alg, &params, md_alg,
+                                      pk_alg, sig_opts ) );
+}
+
 /*
  * Get signature algorithm from alg OID and optional parameters
  */
@@ -664,9 +852,6 @@
 {
     int ret;
 
-    if( *sig_opts != NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
-
     if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
 
@@ -689,7 +874,10 @@
             return( ret );
         }
 
-        *sig_opts = (void *) pss_opts;
+        if( sig_opts != NULL )
+            *sig_opts = (void *) pss_opts;
+        else
+            mbedtls_free( pss_opts );
     }
     else
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
@@ -697,7 +885,10 @@
         /* Make sure parameters are absent or NULL */
         if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
               sig_params->len != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG );
+            return( MBEDTLS_ERR_X509_INVALID_ALG );
+
+        if( sig_opts != NULL )
+            *sig_opts = NULL;
     }
 
     return( 0 );
@@ -840,20 +1031,34 @@
 /*
  * Helper for writing signature algorithms
  */
-int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
-                       mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
-                       const void *sig_opts )
+int mbedtls_x509_sig_alg_gets( char *buf, size_t size, mbedtls_pk_type_t pk_alg,
+                               mbedtls_md_type_t md_alg, const void *sig_opts )
 {
     int ret;
     char *p = buf;
     size_t n = size;
     const char *desc = NULL;
+    mbedtls_x509_buf sig_oid;
+    mbedtls_md_type_t tmp_md_alg = md_alg;
 
-    ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
-    if( ret != 0 )
-        ret = mbedtls_snprintf( p, n, "???"  );
-    else
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    /* The hash for RSASSA is determined by the algorithm parameters;
+     * in the OID list, the hash is set to MBEDTLS_MD_NONE. */
+    if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
+        tmp_md_alg = MBEDTLS_MD_NONE;
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+    sig_oid.tag = MBEDTLS_ASN1_OID;
+    ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, tmp_md_alg,
+                                          (const char**) &sig_oid.p,
+                                          &sig_oid.len );
+    if( ret == 0 &&
+        mbedtls_oid_get_sig_alg_desc( &sig_oid, &desc ) == 0 )
+    {
         ret = mbedtls_snprintf( p, n, "%s", desc );
+    }
+    else
+        ret = mbedtls_snprintf( p, n, "???" );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
@@ -1003,6 +1208,17 @@
 }
 #endif /* MBEDTLS_HAVE_TIME_DATE */
 
+void mbedtls_x509_name_free( mbedtls_x509_name *name )
+{
+    while( name != NULL )
+    {
+        mbedtls_x509_name *next = name->next;
+        mbedtls_platform_zeroize( name, sizeof( *name ) );
+        mbedtls_free( name );
+        name = next;
+    }
+}
+
 #if defined(MBEDTLS_SELF_TEST)
 
 #include "mbedtls/x509_crt.h"
diff --git a/library/x509_create.c b/library/x509_create.c
index 546e8fa..1639630 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_X509_CREATE_C)
 
 #include "mbedtls/x509.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/oid.h"
 
diff --git a/library/x509_crl.c b/library/x509_crl.c
index 4f5507f..3113de4 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
 
 #include "mbedtls/x509_crl.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -428,15 +429,17 @@
         mbedtls_x509_crl_free( crl );
         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
     }
+    p += len;
+    crl->issuer_raw.len = p - crl->issuer_raw.p;
 
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
+    if( ( ret = mbedtls_x509_get_name( crl->issuer_raw.p,
+                                       crl->issuer_raw.len,
+                                       &crl->issuer ) ) != 0 )
     {
         mbedtls_x509_crl_free( crl );
         return( ret );
     }
 
-    crl->issuer_raw.len = p - crl->issuer_raw.p;
-
     /*
      * thisUpdate          Time
      * nextUpdate          Time OPTIONAL
@@ -690,8 +693,8 @@
     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,
-                             crl->sig_opts );
+    ret = mbedtls_x509_sig_alg_gets( p, n, crl->sig_pk,
+                                     crl->sig_md, crl->sig_opts );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
     ret = mbedtls_snprintf( p, n, "\n" );
diff --git a/library/x509_crt.c b/library/x509_crt.c
index e4a35f6..eb3ee99 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -40,6 +40,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -78,6 +79,385 @@
 #endif /* !_WIN32 || EFIX64 || EFI32 */
 #endif
 
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+static void x509_buf_to_buf_raw( mbedtls_x509_buf_raw *dst,
+                                 mbedtls_x509_buf const *src )
+{
+    dst->p = src->p;
+    dst->len = src->len;
+}
+
+static void x509_buf_raw_to_buf( mbedtls_x509_buf *dst,
+                                 mbedtls_x509_buf_raw const *src )
+{
+    dst->p = src->p;
+    dst->len = src->len;
+}
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+
+static int x509_crt_parse_frame( unsigned char *start,
+                                 unsigned char *end,
+                                 mbedtls_x509_crt_frame *frame );
+static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame const *frame,
+                                        mbedtls_x509_name *subject );
+static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame const *frame,
+                                       mbedtls_x509_name *issuer );
+static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame const *frame,
+                                        mbedtls_x509_sequence *subject_alt );
+static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame const *frame,
+                                        mbedtls_x509_sequence *ext_key_usage );
+
+int mbedtls_x509_crt_flush_cache_pk( mbedtls_x509_crt const *crt )
+{
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    /* Can only free the PK context if nobody is using it.
+     * If MBEDTLS_X509_ALWAYS_FLUSH is set, nested uses
+     * of xxx_acquire() are prohibited, and no reference
+     * counting is needed. Also, notice that the code-path
+     * below is safe if the cache isn't filled. */
+    if( crt->cache->pk_readers == 0 )
+#endif /* !MBEDTLS_X509_ALWAYS_FLUSH ||
+          MBEDTLS_THREADING_C */
+    {
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+        /* The cache holds a shallow copy of the PK context
+         * in the legacy struct, so don't free PK context. */
+        mbedtls_free( crt->cache->pk );
+#else
+        mbedtls_pk_free( crt->cache->pk );
+        mbedtls_free( crt->cache->pk );
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+        crt->cache->pk = NULL;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+    return( 0 );
+}
+
+int mbedtls_x509_crt_flush_cache_frame( mbedtls_x509_crt const *crt )
+{
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+    /* Can only free the PK context if nobody is using it.
+     * If MBEDTLS_X509_ALWAYS_FLUSH is set, nested uses
+     * of xxx_acquire() are prohibited, and no reference
+     * counting is needed. Also, notice that the code-path
+     * below is safe if the cache isn't filled. */
+    if( crt->cache->frame_readers == 0 )
+#endif /* !MBEDTLS_X509_ALWAYS_FLUSH ||
+          MBEDTLS_THREADING_C */
+    {
+        mbedtls_free( crt->cache->frame );
+        crt->cache->frame = NULL;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+    return( 0 );
+}
+
+int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt )
+{
+    int ret;
+    ret = mbedtls_x509_crt_flush_cache_frame( crt );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_x509_crt_flush_cache_pk( crt );
+    if( ret != 0 )
+        return( ret );
+    return( 0 );
+}
+
+static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame );
+
+int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
+{
+    mbedtls_x509_crt_cache *cache = crt->cache;
+    mbedtls_x509_crt_frame *frame;
+
+    if( cache->frame != NULL )
+    {
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+        return( 0 );
+#else
+        /* If MBEDTLS_X509_ALWAYS_FLUSH is set, we don't
+         * allow nested uses of acquire. */
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+#endif
+    }
+
+    frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
+    if( frame == NULL )
+        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    cache->frame = frame;
+
+#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    /* This would work with !MBEDTLS_X509_ON_DEMAND_PARSING, too,
+     * but is inefficient compared to copying the respective fields
+     * from the legacy mbedtls_x509_crt. */
+    return( x509_crt_parse_frame( crt->raw.p,
+                                  crt->raw.p + crt->raw.len,
+                                  frame ) );
+#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
+    /* Make sure all extension related fields are properly initialized. */
+    frame->ca_istrue = 0;
+    frame->max_pathlen = 0;
+    frame->ext_types = 0;
+    frame->version = crt->version;
+    frame->sig_md = crt->sig_md;
+    frame->sig_pk = crt->sig_pk;
+    frame->valid_from = crt->valid_from;
+    frame->valid_to = crt->valid_to;
+    x509_buf_to_buf_raw( &frame->raw, &crt->raw );
+    x509_buf_to_buf_raw( &frame->tbs, &crt->tbs );
+    x509_buf_to_buf_raw( &frame->serial, &crt->serial );
+    x509_buf_to_buf_raw( &frame->pubkey_raw, &crt->pk_raw );
+    x509_buf_to_buf_raw( &frame->issuer_raw, &crt->issuer_raw );
+    x509_buf_to_buf_raw( &frame->subject_raw, &crt->subject_raw );
+    x509_buf_to_buf_raw( &frame->subject_id, &crt->subject_id );
+    x509_buf_to_buf_raw( &frame->issuer_id, &crt->issuer_id );
+    x509_buf_to_buf_raw( &frame->sig, &crt->sig );
+    x509_buf_to_buf_raw( &frame->v3_ext, &crt->v3_ext );
+
+    /* The legacy CRT structure doesn't explicitly contain
+     * the `AlgorithmIdentifier` bounds; however, those can
+     * be inferred from the surrounding (mandatory) `SerialNumber`
+     * and `Issuer` fields. */
+    frame->sig_alg.p = crt->serial.p + crt->serial.len;
+    frame->sig_alg.len = crt->issuer_raw.p - frame->sig_alg.p;
+
+    return( x509_crt_frame_parse_ext( frame ) );
+#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
+}
+
+int mbedtls_x509_crt_cache_provide_pk( mbedtls_x509_crt const *crt )
+{
+    mbedtls_x509_crt_cache *cache = crt->cache;
+    mbedtls_pk_context *pk;
+
+    if( cache->pk != NULL )
+    {
+#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) ||      \
+    defined(MBEDTLS_THREADING_C)
+        return( 0 );
+#else
+        /* If MBEDTLS_X509_ALWAYS_FLUSH is set, we don't
+         * allow nested uses of acquire. */
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+#endif
+    }
+
+    pk = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) );
+    if( pk == NULL )
+        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    cache->pk = pk;
+
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    *pk = crt->pk;
+    return( 0 );
+#else
+    {
+        mbedtls_x509_buf_raw pk_raw = cache->pk_raw;
+        return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
+                                            pk_raw.p + pk_raw.len,
+                                            pk ) );
+    }
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+}
+
+static void x509_crt_cache_init( mbedtls_x509_crt_cache *cache )
+{
+    memset( cache, 0, sizeof( *cache ) );
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &cache->frame_mutex );
+    mbedtls_mutex_init( &cache->pk_mutex );
+#endif
+}
+
+static void x509_crt_cache_clear_pk( mbedtls_x509_crt_cache *cache )
+{
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    /* The cache holds a shallow copy of the PK context
+     * in the legacy struct, so don't free PK context. */
+    mbedtls_free( cache->pk );
+#else
+    mbedtls_pk_free( cache->pk );
+    mbedtls_free( cache->pk );
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+
+    cache->pk = NULL;
+}
+
+static void x509_crt_cache_clear_frame( mbedtls_x509_crt_cache *cache )
+{
+    mbedtls_free( cache->frame );
+    cache->frame = NULL;
+}
+
+static void x509_crt_cache_free( mbedtls_x509_crt_cache *cache )
+{
+    if( cache == NULL )
+        return;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_free( &cache->frame_mutex );
+    mbedtls_mutex_free( &cache->pk_mutex );
+#endif
+
+    x509_crt_cache_clear_frame( cache );
+    x509_crt_cache_clear_pk( cache );
+
+    memset( cache, 0, sizeof( *cache ) );
+}
+
+int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
+                                            mbedtls_x509_sequence **subj_alt )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    mbedtls_x509_sequence *seq;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
+    if( seq == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_subject_alt_from_frame( frame, seq );
+
+    mbedtls_x509_crt_frame_release( crt );
+
+    *subj_alt = seq;
+    return( ret );
+}
+
+int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
+                                        mbedtls_x509_sequence **ext_key_usage )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    mbedtls_x509_sequence *seq;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
+    if( seq == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_ext_key_usage_from_frame( frame, seq );
+
+    mbedtls_x509_crt_frame_release( crt );
+
+    *ext_key_usage = seq;
+    return( ret );
+}
+
+int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
+                                  mbedtls_x509_name **subject )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    mbedtls_x509_name *name;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
+    if( name == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_subject_from_frame( frame, name );
+
+    mbedtls_x509_crt_frame_release( crt );
+
+    *subject = name;
+    return( ret );
+}
+
+int mbedtls_x509_crt_get_issuer( mbedtls_x509_crt const *crt,
+                                 mbedtls_x509_name **issuer )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    mbedtls_x509_name *name;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
+    if( name == NULL )
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+    else
+        ret = x509_crt_issuer_from_frame( frame, name );
+
+    mbedtls_x509_crt_frame_release( crt );
+
+    *issuer = name;
+    return( ret );
+}
+
+int mbedtls_x509_crt_get_frame( mbedtls_x509_crt const *crt,
+                                mbedtls_x509_crt_frame *dst )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+    *dst = *frame;
+    mbedtls_x509_crt_frame_release( crt );
+    return( 0 );
+}
+
+int mbedtls_x509_crt_get_pk( mbedtls_x509_crt const *crt,
+                             mbedtls_pk_context *dst )
+{
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    mbedtls_x509_buf_raw pk_raw = crt->cache->pk_raw;
+    return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
+                                        pk_raw.p + pk_raw.len,
+                                        dst ) );
+#else /* !MBEDTLS_X509_ON_DEMAND_PARSING */
+    int ret;
+    mbedtls_pk_context *pk;
+    ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
+    if( ret != 0 )
+        return( ret );
+
+    /* Move PK from CRT cache to destination pointer
+     * to avoid a copy. */
+    *dst = *pk;
+    mbedtls_free( crt->cache->pk );
+    crt->cache->pk = NULL;
+
+    mbedtls_x509_crt_pk_release( crt );
+    return( 0 );
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+}
+
 /*
  * Item in a verification chain: cert and flags for it
  */
@@ -228,44 +608,18 @@
 }
 
 /*
- * Like memcmp, but case-insensitive and always returns -1 if different
- */
-static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
-{
-    size_t i;
-    unsigned char diff;
-    const unsigned char *n1 = s1, *n2 = s2;
-
-    for( i = 0; i < len; i++ )
-    {
-        diff = n1[i] ^ n2[i];
-
-        if( diff == 0 )
-            continue;
-
-        if( diff == 32 &&
-            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
-              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
-        {
-            continue;
-        }
-
-        return( -1 );
-    }
-
-    return( 0 );
-}
-
-/*
  * Return 0 if name matches wildcard, -1 otherwise
  */
-static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
+static int x509_check_wildcard( char const *cn,
+                                size_t cn_len,
+                                unsigned char const *buf,
+                                size_t buf_len )
 {
     size_t i;
-    size_t cn_idx = 0, cn_len = strlen( cn );
+    size_t cn_idx = 0;
 
     /* We can't have a match if there is no wildcard to match */
-    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+    if( buf_len < 3 || buf[0] != '*' || buf[1] != '.' )
         return( -1 );
 
     for( i = 0; i < cn_len; ++i )
@@ -280,8 +634,8 @@
     if( cn_idx == 0 )
         return( -1 );
 
-    if( cn_len - cn_idx == name->len - 1 &&
-        x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+    if( mbedtls_x509_memcasecmp( buf + 1, cn + cn_idx,
+                                 buf_len - 1, cn_len - cn_idx ) == 0 )
     {
         return( 0 );
     }
@@ -290,74 +644,6 @@
 }
 
 /*
- * Compare two X.509 strings, case-insensitive, and allowing for some encoding
- * variations (but not all).
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
-{
-    if( a->tag == b->tag &&
-        a->len == b->len &&
-        memcmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
-    }
-
-    if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
-        ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
-        a->len == b->len &&
-        x509_memcasecmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
-    }
-
-    return( -1 );
-}
-
-/*
- * Compare two X.509 Names (aka rdnSequence).
- *
- * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
- * we sometimes return unequal when the full algorithm would return equal,
- * but never the other way. (In particular, we don't do Unicode normalisation
- * or space folding.)
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
-{
-    /* Avoid recursion, it might not be optimised by the compiler */
-    while( a != NULL || b != NULL )
-    {
-        if( a == NULL || b == NULL )
-            return( -1 );
-
-        /* type */
-        if( a->oid.tag != b->oid.tag ||
-            a->oid.len != b->oid.len ||
-            memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
-        {
-            return( -1 );
-        }
-
-        /* value */
-        if( x509_string_cmp( &a->val, &b->val ) != 0 )
-            return( -1 );
-
-        /* structure of the list of sets */
-        if( a->next_merged != b->next_merged )
-            return( -1 );
-
-        a = a->next;
-        b = b->next;
-    }
-
-    /* a == NULL == b */
-    return( 0 );
-}
-
-/*
  * Reset (init or clear) a verify_chain
  */
 static void x509_crt_verify_chain_reset(
@@ -445,15 +731,13 @@
  */
 static int x509_get_uid( unsigned char **p,
                          const unsigned char *end,
-                         mbedtls_x509_buf *uid, int n )
+                         mbedtls_x509_buf_raw *uid, int n )
 {
     int ret;
 
     if( *p == end )
         return( 0 );
 
-    uid->tag = **p;
-
     if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
     {
@@ -487,7 +771,7 @@
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( ret );
 
     if( *p == end )
         return( 0 );
@@ -498,7 +782,7 @@
             ret = mbedtls_asn1_get_int( p, end, ca_istrue );
 
         if( ret != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( ret );
 
         if( *ca_istrue != 0 )
             *ca_istrue = 1;
@@ -508,11 +792,10 @@
         return( 0 );
 
     if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( ret );
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
 
     (*max_pathlen)++;
 
@@ -527,11 +810,10 @@
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( ret );
 
     if( bs.len != 1 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
 
     /* Get actual bitstring */
     *ns_cert_type = *bs.p;
@@ -540,29 +822,53 @@
 
 static int x509_get_key_usage( unsigned char **p,
                                const unsigned char *end,
-                               unsigned int *key_usage)
+                               uint16_t *key_usage)
 {
     int ret;
     size_t i;
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( ret );
 
     if( bs.len < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
 
     /* Get actual bitstring */
     *key_usage = 0;
-    for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
+    for( i = 0; i < bs.len && i < sizeof( *key_usage ); i++ )
     {
-        *key_usage |= (unsigned int) bs.p[i] << (8*i);
+        *key_usage |= (uint16_t) bs.p[i] << ( 8*i );
     }
 
     return( 0 );
 }
 
+static int asn1_build_sequence_cb( void *ctx,
+                                   int tag,
+                                   unsigned char *data,
+                                   size_t data_len )
+{
+    mbedtls_asn1_sequence **cur_ptr = (mbedtls_asn1_sequence **) ctx;
+    mbedtls_asn1_sequence *cur = *cur_ptr;
+
+    /* Allocate and assign next pointer */
+    if( cur->buf.p != NULL )
+    {
+        cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+        if( cur->next == NULL )
+            return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+        cur = cur->next;
+    }
+
+    cur->buf.tag = tag;
+    cur->buf.p = data;
+    cur->buf.len = data_len;
+
+    *cur_ptr = cur;
+    return( 0 );
+}
+
 /*
  * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
  *
@@ -572,17 +878,11 @@
                                const unsigned char *end,
                                mbedtls_x509_sequence *ext_key_usage)
 {
-    int ret;
-
-    if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-    /* Sequence length must be >= 1 */
-    if( ext_key_usage->buf.p == NULL )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
-
-    return( 0 );
+    return( mbedtls_asn1_traverse_sequence_of( p, end,
+                                               0xFF, MBEDTLS_ASN1_OID,
+                                               0, 0,
+                                               asn1_build_sequence_cb,
+                                               (void *) &ext_key_usage ) );
 }
 
 /*
@@ -611,220 +911,551 @@
  *
  * NOTE: we only parse and use dNSName at this point.
  */
-static int x509_get_subject_alt_name( unsigned char **p,
+static int x509_get_subject_alt_name( unsigned char *p,
                                       const unsigned char *end,
                                       mbedtls_x509_sequence *subject_alt_name )
 {
-    int ret;
-    size_t len, tag_len;
-    mbedtls_asn1_buf *buf;
-    unsigned char tag;
-    mbedtls_asn1_sequence *cur = subject_alt_name;
-
-    /* Get main sequence tag */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-    if( *p + len != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-    while( *p < end )
-    {
-        if( ( end - *p ) < 1 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_OUT_OF_DATA );
-
-        tag = **p;
-        (*p)++;
-        if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-        if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
-                MBEDTLS_ASN1_CONTEXT_SPECIFIC )
-        {
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
-        }
-
-        /* Skip everything but DNS name */
-        if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
-        {
-            *p += tag_len;
-            continue;
-        }
-
-        /* Allocate and assign next pointer */
-        if( cur->buf.p != NULL )
-        {
-            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 = tag;
-        buf->p = *p;
-        buf->len = tag_len;
-        *p += buf->len;
-    }
-
-    /* Set final sequence entry's next pointer to NULL */
-    cur->next = NULL;
-
-    if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-    return( 0 );
+    return( mbedtls_asn1_traverse_sequence_of( &p, end,
+                                               MBEDTLS_ASN1_TAG_CLASS_MASK,
+                                               MBEDTLS_ASN1_CONTEXT_SPECIFIC,
+                                               MBEDTLS_ASN1_TAG_VALUE_MASK,
+                                               2 /* SubjectAlt DNS */,
+                                               asn1_build_sequence_cb,
+                                               (void *) &subject_alt_name ) );
 }
 
 /*
  * X.509 v3 extensions
  *
  */
-static int x509_get_crt_ext( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_x509_crt *crt )
+static int x509_crt_get_ext_cb( void *ctx,
+                                int tag,
+                                unsigned char *p,
+                                size_t ext_len )
 {
     int ret;
+    mbedtls_x509_crt_frame *frame = (mbedtls_x509_crt_frame *) ctx;
     size_t len;
-    unsigned char *end_ext_data, *end_ext_octet;
+    unsigned char *end, *end_ext_octet;
+    mbedtls_x509_buf extn_oid = { 0, 0, NULL };
+    int is_critical = 0; /* DEFAULT FALSE */
+    int ext_type = 0;
 
-    if( *p == end )
-        return( 0 );
+    ((void) tag);
 
-    if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
-        return( ret );
+    /*
+     * Extension  ::=  SEQUENCE  {
+     *      extnID      OBJECT IDENTIFIER,
+     *      critical    BOOLEAN DEFAULT FALSE,
+     *      extnValue   OCTET STRING  }
+     */
 
-    end = crt->v3_ext.p + crt->v3_ext.len;
-    while( *p < end )
+    end = p + ext_len;
+
+    /* Get extension ID */
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &extn_oid.len,
+                                      MBEDTLS_ASN1_OID ) ) != 0 )
+        goto err;
+
+    extn_oid.tag = MBEDTLS_ASN1_OID;
+    extn_oid.p = p;
+    p += extn_oid.len;
+
+    /* Get optional critical */
+    if( ( ret = mbedtls_asn1_get_bool( &p, end, &is_critical ) ) != 0 &&
+        ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
+        goto err;
+
+    /* Data should be octet string type */
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                      MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+        goto err;
+
+    end_ext_octet = p + len;
+    if( end_ext_octet != end )
     {
-        /*
-         * Extension  ::=  SEQUENCE  {
-         *      extnID      OBJECT IDENTIFIER,
-         *      critical    BOOLEAN DEFAULT FALSE,
-         *      extnValue   OCTET STRING  }
-         */
-        mbedtls_x509_buf extn_oid = {0, 0, NULL};
-        int is_critical = 0; /* DEFAULT FALSE */
-        int ext_type = 0;
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+        goto err;
+    }
 
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-        end_ext_data = *p + len;
-
-        /* Get extension ID */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
-                                          MBEDTLS_ASN1_OID ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-        extn_oid.tag = MBEDTLS_ASN1_OID;
-        extn_oid.p = *p;
-        *p += extn_oid.len;
-
-        /* Get optional critical */
-        if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
-            ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-        /* Data should be octet string type */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
-                MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
-
-        end_ext_octet = *p + len;
-
-        if( end_ext_octet != end_ext_data )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-        /*
-         * Detect supported extensions
-         */
-        ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
-
-        if( ret != 0 )
-        {
-            /* No parser found, skip extension */
-            *p = end_ext_octet;
-
+    /*
+     * Detect supported extensions
+     */
+    ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
+    if( ret != 0 )
+    {
 #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-            if( is_critical )
-            {
-                /* Data is marked as critical: fail */
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
-            }
-#endif
-            continue;
-        }
-
-        /* Forbid repeated extensions */
-        if( ( crt->ext_types & ext_type ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
-
-        crt->ext_types |= ext_type;
-
-        switch( ext_type )
+        if( is_critical )
         {
+            /* Data is marked as critical: fail */
+            ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
+            goto err;
+        }
+#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
+        return( 0 );
+    }
+
+    /* Forbid repeated extensions */
+    if( ( frame->ext_types & ext_type ) != 0 )
+        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
+
+    frame->ext_types |= ext_type;
+    switch( ext_type )
+    {
         case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
+        {
+            int ca_istrue;
+            int max_pathlen;
+
             /* Parse basic constraints */
-            if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
-                    &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
-                return( ret );
+            ret = x509_get_basic_constraints( &p, end_ext_octet,
+                                              &ca_istrue,
+                                              &max_pathlen );
+            if( ret != 0 )
+                goto err;
+
+            frame->ca_istrue   = ca_istrue;
+            frame->max_pathlen = max_pathlen;
             break;
+        }
 
         case MBEDTLS_X509_EXT_KEY_USAGE:
             /* Parse key usage */
-            if( ( ret = x509_get_key_usage( p, end_ext_octet,
-                    &crt->key_usage ) ) != 0 )
-                return( ret );
+            ret = x509_get_key_usage( &p, end_ext_octet,
+                                      &frame->key_usage );
+            if( ret != 0 )
+                goto err;
+            break;
+
+        case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
+            /* Copy reference to raw subject alt name data. */
+            frame->subject_alt_raw.p   = p;
+            frame->subject_alt_raw.len = end_ext_octet - p;
+
+            ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
+                                      MBEDTLS_ASN1_TAG_CLASS_MASK,
+                                      MBEDTLS_ASN1_CONTEXT_SPECIFIC,
+                                      MBEDTLS_ASN1_TAG_VALUE_MASK,
+                                      2 /* SubjectAlt DNS */,
+                                      NULL, NULL );
+            if( ret != 0 )
+                goto err;
             break;
 
         case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
             /* Parse extended key usage */
-            if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
-                    &crt->ext_key_usage ) ) != 0 )
-                return( ret );
-            break;
+            frame->ext_key_usage_raw.p   = p;
+            frame->ext_key_usage_raw.len = end_ext_octet - p;
+            if( frame->ext_key_usage_raw.len == 0 )
+            {
+                ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+                goto err;
+            }
 
-        case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
-            /* Parse subject alt name */
-            if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
-                    &crt->subject_alt_names ) ) != 0 )
-                return( ret );
+            /* Check structural sanity of extension. */
+            ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
+                                                     0xFF, MBEDTLS_ASN1_OID,
+                                                     0, 0, NULL, NULL );
+            if( ret != 0 )
+                goto err;
+
             break;
 
         case MBEDTLS_X509_EXT_NS_CERT_TYPE:
             /* Parse netscape certificate type */
-            if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
-                    &crt->ns_cert_type ) ) != 0 )
-                return( ret );
+            ret = x509_get_ns_cert_type( &p, end_ext_octet,
+                                         &frame->ns_cert_type );
+            if( ret != 0 )
+                goto err;
             break;
 
         default:
-            return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
-        }
+            /*
+             * If this is a non-critical extension, which the oid layer
+             * supports, but there isn't an X.509 parser for it,
+             * skip the extension.
+             */
+#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+            if( is_critical )
+                return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+#endif
+            p = end_ext_octet;
     }
 
-    if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+    return( 0 );
+
+err:
+    return( ret );
+}
+
+static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame )
+{
+    int ret;
+    unsigned char *p = frame->v3_ext.p;
+    unsigned char *end = p + frame->v3_ext.len;
+
+    if( p == end )
+        return( 0 );
+
+    ret = mbedtls_asn1_traverse_sequence_of( &p, end,
+                 0xFF, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED,
+                 0, 0, x509_crt_get_ext_cb, frame );
+
+    if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+        return( ret );
+    if( ret == MBEDTLS_ERR_X509_INVALID_EXTENSIONS )
+        return( ret );
+
+    if( ret != 0 )
+        ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+
+    return( ret );
+}
+
+static int x509_crt_parse_frame( unsigned char *start,
+                                 unsigned char *end,
+                                 mbedtls_x509_crt_frame *frame )
+{
+    int ret;
+    unsigned char *p;
+    size_t len;
+
+    mbedtls_x509_buf tmp;
+    unsigned char *tbs_start;
+
+    mbedtls_x509_buf outer_sig_alg;
+    size_t inner_sig_alg_len;
+    unsigned char *inner_sig_alg_start;
+
+    memset( frame, 0, sizeof( *frame ) );
+
+    /*
+     * Certificate  ::=  SEQUENCE {
+     *      tbsCertificate       TBSCertificate,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING
+     * }
+     *
+     */
+    p = start;
+
+    frame->raw.p = p;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    }
+
+    /* NOTE: We are currently not checking that the `Certificate`
+     * structure spans the entire buffer. */
+    end = p + len;
+    frame->raw.len = end - frame->raw.p;
+
+    /*
+     * TBSCertificate  ::=  SEQUENCE  { ...
+     */
+    frame->tbs.p = p;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
+    }
+    tbs_start = p;
+
+    /* Breadth-first parsing: Jump over TBS for now. */
+    p += len;
+    frame->tbs.len = p - frame->tbs.p;
+
+    /*
+     *  AlgorithmIdentifier ::= SEQUENCE { ...
+     */
+    outer_sig_alg.p = p;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+    }
+    p += len;
+    outer_sig_alg.len = p - outer_sig_alg.p;
+
+    /*
+     *  signatureValue       BIT STRING
+     */
+    ret = mbedtls_x509_get_sig( &p, end, &tmp );
+    if( ret != 0 )
+        return( ret );
+    frame->sig.p   = tmp.p;
+    frame->sig.len = tmp.len;
+
+    /* Check that we consumed the entire `Certificate` structure. */
+    if( p != end )
+    {
+        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    /* Parse TBSCertificate structure
+     *
+     * TBSCertificate  ::=  SEQUENCE  {
+     *             version         [0]  EXPLICIT Version DEFAULT v1,
+     *             serialNumber         CertificateSerialNumber,
+     *             signature            AlgorithmIdentifier,
+     *             issuer               Name,
+     *             validity             Validity,
+     *             subject              Name,
+     *             subjectPublicKeyInfo SubjectPublicKeyInfo,
+     *             issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                                  -- If present, version MUST be v2 or v3
+     *             subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+     *                                  -- If present, version MUST be v2 or v3
+     *             extensions      [3]  EXPLICIT Extensions OPTIONAL
+     *                                  -- If present, version MUST be v3
+     *         }
+     */
+    end = frame->tbs.p + frame->tbs.len;
+    p = tbs_start;
+
+    /*
+     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+     */
+    {
+        int version;
+        ret = x509_get_version( &p, end, &version );
+        if( ret != 0 )
+            return( ret );
+
+        if( version < 0 || version > 2 )
+            return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
+
+        frame->version = version + 1;
+    }
+
+    /*
+     * CertificateSerialNumber  ::=  INTEGER
+     */
+    ret = mbedtls_x509_get_serial( &p, end, &tmp );
+    if( ret != 0 )
+        return( ret );
+
+    frame->serial.p   = tmp.p;
+    frame->serial.len = tmp.len;
+
+    /*
+     * signature            AlgorithmIdentifier
+     */
+    inner_sig_alg_start = p;
+    ret = mbedtls_x509_get_sig_alg_raw( &p, end, &frame->sig_md,
+                                        &frame->sig_pk, NULL );
+    if( ret != 0 )
+        return( ret );
+    inner_sig_alg_len = p - inner_sig_alg_start;
+
+    frame->sig_alg.p   = inner_sig_alg_start;
+    frame->sig_alg.len = inner_sig_alg_len;
+
+    /* Consistency check:
+     * Inner and outer AlgorithmIdentifier structures must coincide:
+     *
+     * Quoting RFC 5280, Section 4.1.1.2:
+     *    This field MUST contain the same algorithm identifier as the
+     *    signature field in the sequence tbsCertificate (Section 4.1.2.3).
+     */
+    if( outer_sig_alg.len != inner_sig_alg_len ||
+        memcmp( outer_sig_alg.p, inner_sig_alg_start, inner_sig_alg_len ) != 0 )
+    {
+        return( MBEDTLS_ERR_X509_SIG_MISMATCH );
+    }
+
+    /*
+     * issuer               Name
+     *
+     * Name ::= CHOICE { -- only one possibility for now --
+     *                      rdnSequence  RDNSequence }
+     *
+     * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+     */
+    frame->issuer_raw.p = p;
+
+    ret = mbedtls_asn1_get_tag( &p, end, &len,
+                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
+    p += len;
+    frame->issuer_raw.len = p - frame->issuer_raw.p;
+
+    /* Comparing the raw buffer to itself amounts to structural validation. */
+    ret = mbedtls_x509_name_cmp_raw( &frame->issuer_raw,
+                                     &frame->issuer_raw,
+                                     NULL, NULL );
+    if( ret != 0 )
+        return( ret );
+
+    /*
+     * Validity ::= SEQUENCE { ...
+     */
+    ret = x509_get_dates( &p, end, &frame->valid_from, &frame->valid_to );
+    if( ret != 0 )
+        return( ret );
+
+    /*
+     * subject              Name
+     *
+     * Name ::= CHOICE { -- only one possibility for now --
+     *                      rdnSequence  RDNSequence }
+     *
+     * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+     */
+    frame->subject_raw.p = p;
+
+    ret = mbedtls_asn1_get_tag( &p, end, &len,
+                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
+    p += len;
+    frame->subject_raw.len = p - frame->subject_raw.p;
+
+    /* Comparing the raw buffer to itself amounts to structural validation. */
+    ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
+                                     &frame->subject_raw,
+                                     NULL, NULL );
+    if( ret != 0 )
+        return( ret );
+
+    /*
+     * SubjectPublicKeyInfo
+     */
+    frame->pubkey_raw.p = p;
+    ret = mbedtls_asn1_get_tag( &p, end, &len,
+                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+    if( ret != 0 )
+        return( ret + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+    p += len;
+    frame->pubkey_raw.len = p - frame->pubkey_raw.p;
+
+    if( frame->version != 1 )
+    {
+        /*
+         *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+         *                       -- If present, version shall be v2 or v3
+         */
+        ret = x509_get_uid( &p, end, &frame->issuer_id, 1 /* implicit tag */ );
+        if( ret != 0 )
+            return( ret );
+
+        /*
+         *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+         *                       -- If present, version shall be v2 or v3
+         */
+        ret = x509_get_uid( &p, end, &frame->subject_id, 2 /* implicit tag */ );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    /*
+     *  extensions      [3]  EXPLICIT Extensions OPTIONAL
+     *                       -- If present, version shall be v3
+     */
+#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
+    if( frame->version == 3 )
+#endif
+    {
+        if( p != end )
+        {
+            ret = mbedtls_asn1_get_tag( &p, end, &len,
+                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                        MBEDTLS_ASN1_CONSTRUCTED | 3 );
+            if( len == 0 )
+                ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+            if( ret != 0 )
+                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+            frame->v3_ext.p = p;
+            frame->v3_ext.len = len;
+
+            p += len;
+        }
+
+        ret = x509_crt_frame_parse_ext( frame );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    /* Wrapup: Check that we consumed the entire `TBSCertificate` structure. */
+    if( p != end )
+    {
+        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    }
 
     return( 0 );
 }
 
+static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame const *frame,
+                                        mbedtls_x509_name *subject )
+{
+    return( mbedtls_x509_get_name( frame->subject_raw.p,
+                                   frame->subject_raw.len,
+                                   subject ) );
+}
+
+static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame const *frame,
+                                       mbedtls_x509_name *issuer )
+{
+    return( mbedtls_x509_get_name( frame->issuer_raw.p,
+                                   frame->issuer_raw.len,
+                                   issuer ) );
+}
+
+static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame const *frame,
+                                            mbedtls_x509_sequence *subject_alt )
+{
+    int ret;
+    unsigned char *p   = frame->subject_alt_raw.p;
+    unsigned char *end = p + frame->subject_alt_raw.len;
+
+    memset( subject_alt, 0, sizeof( *subject_alt ) );
+
+    if( ( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) == 0 )
+        return( 0 );
+
+    ret = x509_get_subject_alt_name( p, end, subject_alt );
+    if( ret != 0 )
+        ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+    return( ret );
+}
+
+static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame const *frame,
+                                        mbedtls_x509_sequence *ext_key_usage )
+{
+    int ret;
+    unsigned char *p   = frame->ext_key_usage_raw.p;
+    unsigned char *end = p + frame->ext_key_usage_raw.len;
+
+    memset( ext_key_usage, 0, sizeof( *ext_key_usage ) );
+
+    if( ( frame->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
+        return( 0 );
+
+    ret = x509_get_ext_key_usage( &p, end, ext_key_usage );
+    if( ret != 0 )
+    {
+        ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+static int x509_crt_pk_from_frame( mbedtls_x509_crt_frame *frame,
+                                   mbedtls_pk_context *pk )
+{
+    unsigned char *p   = frame->pubkey_raw.p;
+    unsigned char *end = p + frame->pubkey_raw.len;
+    return( mbedtls_pk_parse_subpubkey( &p, end, pk ) );
+}
+#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
+
 /*
  * Parse and fill a single X.509 certificate in DER format
  */
@@ -834,256 +1465,178 @@
                                     int make_copy )
 {
     int ret;
-    size_t len;
-    unsigned char *p, *end, *crt_end;
-    mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
+    mbedtls_x509_crt_frame *frame;
+    mbedtls_x509_crt_cache *cache;
 
-    memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
-
-    /*
-     * Check for valid input
-     */
     if( crt == NULL || buf == NULL )
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
 
-    /* Use the original buffer until we figure out actual length. */
-    p = (unsigned char*) buf;
-    len = buflen;
-    end = p + len;
-
-    /*
-     * Certificate  ::=  SEQUENCE  {
-     *      tbsCertificate       TBSCertificate,
-     *      signatureAlgorithm   AlgorithmIdentifier,
-     *      signatureValue       BIT STRING  }
-     */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    if( make_copy == 0 )
     {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
-    }
-
-    end = crt_end = p + len;
-    crt->raw.len = crt_end - buf;
-    if( make_copy != 0 )
-    {
-        /* Create and populate a new buffer for the raw field. */
-        crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
-        if( crt->raw.p == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
-
-        memcpy( crt->raw.p, buf, crt->raw.len );
-        crt->own_buffer = 1;
-
-        p += crt->raw.len - len;
-        end = crt_end = p + len;
+        crt->raw.p = (unsigned char*) buf;
+        crt->raw.len = buflen;
+        crt->own_buffer = 0;
     }
     else
     {
-        crt->raw.p = (unsigned char*) buf;
-        crt->own_buffer = 0;
+        /* Call mbedtls_calloc with buflen + 1 in order to avoid potential
+         * return of NULL in case of length 0 certificates, which we want
+         * to cleanly fail with MBEDTLS_ERR_X509_INVALID_FORMAT in the
+         * core parsing routine, but not here. */
+        crt->raw.p = mbedtls_calloc( 1, buflen + 1 );
+        if( crt->raw.p == NULL )
+            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        crt->raw.len = buflen;
+        memcpy( crt->raw.p, buf, buflen );
+
+        crt->own_buffer = 1;
     }
 
+    cache = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_cache ) );
+    if( cache == NULL )
+    {
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+        goto exit;
+    }
+    crt->cache = cache;
+    x509_crt_cache_init( cache );
+
+#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+
+    ret = mbedtls_x509_crt_cache_provide_frame( crt );
+    if( ret != 0 )
+        goto exit;
+
+    frame = crt->cache->frame;
+
+#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
+
+    frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
+    if( frame == NULL )
+    {
+        ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+        goto exit;
+    }
+    cache->frame = frame;
+
+    ret = x509_crt_parse_frame( crt->raw.p,
+                                crt->raw.p + crt->raw.len,
+                                frame );
+    if( ret != 0 )
+        goto exit;
+
+    /* Copy frame to legacy CRT structure -- that's inefficient, but if
+     * memory matters, the new CRT structure should be used anyway. */
+    x509_buf_raw_to_buf( &crt->tbs, &frame->tbs );
+    x509_buf_raw_to_buf( &crt->serial, &frame->serial );
+    x509_buf_raw_to_buf( &crt->issuer_raw, &frame->issuer_raw );
+    x509_buf_raw_to_buf( &crt->subject_raw, &frame->subject_raw );
+    x509_buf_raw_to_buf( &crt->issuer_id, &frame->issuer_id );
+    x509_buf_raw_to_buf( &crt->subject_id, &frame->subject_id );
+    x509_buf_raw_to_buf( &crt->pk_raw, &frame->pubkey_raw );
+    x509_buf_raw_to_buf( &crt->sig, &frame->sig );
+    x509_buf_raw_to_buf( &crt->v3_ext, &frame->v3_ext );
+    crt->valid_from = frame->valid_from;
+    crt->valid_to = frame->valid_to;
+    crt->version      = frame->version;
+    crt->ca_istrue    = frame->ca_istrue;
+    crt->max_pathlen  = frame->max_pathlen;
+    crt->ext_types    = frame->ext_types;
+    crt->key_usage    = frame->key_usage;
+    crt->ns_cert_type = frame->ns_cert_type;
+
     /*
-     * TBSCertificate  ::=  SEQUENCE  {
+     * Obtain the remaining fields from the frame.
      */
-    crt->tbs.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
-    }
+        /* sig_oid: Previously, needed for convenience in
+         * mbedtls_x509_crt_info(), now pure legacy burden. */
+        unsigned char *tmp = frame->sig_alg.p;
+        unsigned char *end = tmp + frame->sig_alg.len;
+        mbedtls_x509_buf sig_oid, sig_params;
 
-    end = p + len;
-    crt->tbs.len = end - crt->tbs.p;
-
-    /*
-     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
-     *
-     * CertificateSerialNumber  ::=  INTEGER
-     *
-     * signature            AlgorithmIdentifier
-     */
-    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
-        ( ret = mbedtls_x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
-        ( ret = mbedtls_x509_get_alg(      &p, end, &crt->sig_oid,
-                                            &sig_params1 ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-
-    if( crt->version < 0 || crt->version > 2 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
-    }
-
-    crt->version++;
-
-    if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
-                                  &crt->sig_md, &crt->sig_pk,
-                                  &crt->sig_opts ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-
-    /*
-     * issuer               Name
-     */
-    crt->issuer_raw.p = p;
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-
-    crt->issuer_raw.len = p - crt->issuer_raw.p;
-
-    /*
-     * Validity ::= SEQUENCE {
-     *      notBefore      Time,
-     *      notAfter       Time }
-     *
-     */
-    if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
-                                         &crt->valid_to ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-
-    /*
-     * subject              Name
-     */
-    crt->subject_raw.p = p;
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
-    }
-
-    if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-
-    crt->subject_raw.len = p - crt->subject_raw.p;
-
-    /*
-     * SubjectPublicKeyInfo
-     */
-    crt->pk_raw.p = p;
-    if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
-    crt->pk_raw.len = p - crt->pk_raw.p;
-
-    /*
-     *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                       -- If present, version shall be v2 or v3
-     *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
-     *                       -- If present, version shall be v2 or v3
-     *  extensions      [3]  EXPLICIT Extensions OPTIONAL
-     *                       -- If present, version shall be v3
-     */
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
+        ret = mbedtls_x509_get_alg( &tmp, end,
+                                    &sig_oid, &sig_params );
         if( ret != 0 )
         {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
+            /* This should never happen, because we check
+             * the sanity of the AlgorithmIdentifier structure
+             * during frame parsing. */
+            ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+            goto exit;
+        }
+        crt->sig_oid = sig_oid;
+
+        /* Signature parameters */
+        tmp = frame->sig_alg.p;
+        ret = mbedtls_x509_get_sig_alg_raw( &tmp, end,
+                                            &crt->sig_md, &crt->sig_pk,
+                                            &crt->sig_opts );
+        if( ret != 0 )
+        {
+            /* Again, this should never happen. */
+            ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+            goto exit;
         }
     }
 
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
-        if( ret != 0 )
-        {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
-        }
-    }
+    ret = x509_crt_pk_from_frame( frame, &crt->pk );
+    if( ret != 0 )
+        goto exit;
 
-#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
-    if( crt->version == 3 )
-#endif
-    {
-        ret = x509_get_crt_ext( &p, end, crt );
-        if( ret != 0 )
-        {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
-        }
-    }
+    ret = x509_crt_subject_from_frame( frame, &crt->subject );
+    if( ret != 0 )
+        goto exit;
 
-    if( p != end )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
+    ret = x509_crt_issuer_from_frame( frame, &crt->issuer );
+    if( ret != 0 )
+        goto exit;
 
-    end = crt_end;
+    ret = x509_crt_subject_alt_from_frame( frame, &crt->subject_alt_names );
+    if( ret != 0 )
+        goto exit;
 
-    /*
-     *  }
-     *  -- end of TBSCertificate
+    ret = x509_crt_ext_key_usage_from_frame( frame, &crt->ext_key_usage );
+    if( ret != 0 )
+        goto exit;
+#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
+
+    /* Currently, we accept DER encoded CRTs with trailing garbage
+     * and promise to not account for the garbage in the `raw` field.
      *
-     *  signatureAlgorithm   AlgorithmIdentifier,
-     *  signatureValue       BIT STRING
-     */
-    if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
+     * Note that this means that `crt->raw.len` is not necessarily the
+     * full size of the heap buffer allocated at `crt->raw.p` in case
+     * of copy-mode, but this is not a problem: freeing the buffer doesn't
+     * need the size, and the garbage data doesn't need zeroization. */
+    crt->raw.len = frame->raw.len;
 
-    if( crt->sig_oid.len != sig_oid2.len ||
-        memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
-        sig_params1.len != sig_params2.len ||
-        ( sig_params1.len != 0 &&
-          memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_SIG_MISMATCH );
-    }
+    cache->pk_raw = frame->pubkey_raw;
 
-    if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
-    }
+    /* Free the frame before parsing the public key to
+     * keep peak RAM usage low. This is slightly inefficient
+     * because the frame will need to be parsed again on the
+     * first usage of the CRT, but that seems acceptable.
+     * As soon as the frame gets used multiple times, it
+     * will be cached by default. */
+    x509_crt_cache_clear_frame( crt->cache );
 
-    if( p != end )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
+    /* The cache just references the PK structure from the legacy
+     * implementation, so set up the latter first before setting up
+     * the cache.
+     *
+     * We're not actually using the parsed PK context here;
+     * we just parse it to check that it's well-formed. */
+    ret = mbedtls_x509_crt_cache_provide_pk( crt );
+    if( ret != 0 )
+        goto exit;
+    x509_crt_cache_clear_pk( crt->cache );
 
-    return( 0 );
+exit:
+    if( ret != 0 )
+        mbedtls_x509_crt_free( crt );
+
+    return( ret );
 }
 
 /*
@@ -1104,7 +1657,7 @@
     if( crt == NULL || buf == NULL )
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
 
-    while( crt->version != 0 && crt->next != NULL )
+    while( crt->raw.p != NULL && crt->next != NULL )
     {
         prev = crt;
         crt = crt->next;
@@ -1113,7 +1666,7 @@
     /*
      * Add new certificate on the end of the chain if needed.
      */
-    if( crt->version != 0 && crt->next == NULL )
+    if( crt->raw.p != NULL && crt->next == NULL )
     {
         crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
 
@@ -1415,6 +1968,71 @@
 }
 #endif /* MBEDTLS_FS_IO */
 
+typedef struct mbedtls_x509_crt_sig_info
+{
+    mbedtls_md_type_t sig_md;
+    mbedtls_pk_type_t sig_pk;
+    void *sig_opts;
+    uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
+    size_t crt_hash_len;
+    mbedtls_x509_buf_raw sig;
+    mbedtls_x509_buf_raw issuer_raw;
+} mbedtls_x509_crt_sig_info;
+
+static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
+{
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    mbedtls_free( info->sig_opts );
+#else
+    ((void) info);
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+}
+
+static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
+                                  mbedtls_x509_crt_sig_info *info )
+{
+    const mbedtls_md_info_t *md_info;
+
+    md_info = mbedtls_md_info_from_type( frame->sig_md );
+    if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
+                    info->crt_hash ) != 0 )
+    {
+        /* Note: this can't happen except after an internal error */
+        return( -1 );
+    }
+
+    info->crt_hash_len = mbedtls_md_get_size( md_info );
+
+    /* Make sure that this function leaves the target structure
+     * ready to be freed, regardless of success of failure. */
+    info->sig_opts = NULL;
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    {
+        int ret;
+        unsigned char *alg_start = frame->sig_alg.p;
+        unsigned char *alg_end = alg_start + frame->sig_alg.len;
+
+        /* Get signature options -- currently only
+         * necessary for RSASSA-PSS. */
+        ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
+                                            &info->sig_pk, &info->sig_opts );
+        if( ret != 0 )
+        {
+            /* Note: this can't happen except after an internal error */
+            return( -1 );
+        }
+    }
+#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+    info->sig_md   = frame->sig_md;
+    info->sig_pk   = frame->sig_pk;
+#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+    info->issuer_raw = frame->issuer_raw;
+    info->sig = frame->sig;
+    return( 0 );
+}
+
 #if !defined(MBEDTLS_X509_REMOVE_INFO)
 static int x509_info_subject_alt_name( char **buf, size_t *size,
                                        const mbedtls_x509_sequence *subject_alt_name )
@@ -1551,135 +2169,209 @@
 #define BEFORE_COLON    18
 #define BC              "18"
 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
-                   const mbedtls_x509_crt *crt )
+                           const mbedtls_x509_crt *crt )
 {
     int ret;
     size_t n;
     char *p;
     char key_size_str[BEFORE_COLON];
+    mbedtls_x509_crt_frame frame;
+    mbedtls_pk_context pk;
+
+    mbedtls_x509_name *issuer = NULL, *subject = NULL;
+    mbedtls_x509_sequence *ext_key_usage = NULL, *subject_alt_names = NULL;
+    mbedtls_x509_crt_sig_info sig_info;
 
     p = buf;
     n = size;
 
+    memset( &sig_info, 0, sizeof( mbedtls_x509_crt_sig_info ) );
+    mbedtls_pk_init( &pk );
+
     if( NULL == crt )
     {
         ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
         return( (int) ( size - n ) );
     }
 
-    ret = mbedtls_snprintf( p, n, "%scert. version     : %d\n",
-                               prefix, crt->version );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_snprintf( p, n, "%sserial number     : ",
-                               prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_crt_get_frame( crt, &frame );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
 
-    ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_crt_get_subject( crt, &subject );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = mbedtls_x509_crt_get_issuer( crt, &issuer );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = mbedtls_x509_crt_get_subject_alt_names( crt, &subject_alt_names );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = mbedtls_x509_crt_get_ext_key_usage( crt, &ext_key_usage );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = mbedtls_x509_crt_get_pk( crt, &pk );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = x509_crt_get_sig_info( &frame, &sig_info );
+    if( ret != 0 )
+    {
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+        goto cleanup;
+    }
+
+    ret = mbedtls_snprintf( p, n, "%scert. version     : %d\n",
+                               prefix, frame.version );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+
+    {
+        mbedtls_x509_buf serial;
+        serial.p   = frame.serial.p;
+        serial.len = frame.serial.len;
+        ret = mbedtls_snprintf( p, n, "%sserial number     : ",
+                                prefix );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+        ret = mbedtls_x509_serial_gets( p, n, &serial );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+    }
 
     ret = mbedtls_snprintf( p, n, "\n%sissuer name       : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->issuer  );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+    ret = mbedtls_x509_dn_gets( p, n, issuer  );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ret = mbedtls_snprintf( p, n, "\n%ssubject name      : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+    ret = mbedtls_x509_dn_gets( p, n, subject );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ret = mbedtls_snprintf( p, n, "\n%sissued  on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_from.year, crt->valid_from.mon,
-                   crt->valid_from.day,  crt->valid_from.hour,
-                   crt->valid_from.min,  crt->valid_from.sec );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+                   frame.valid_from.year, frame.valid_from.mon,
+                   frame.valid_from.day,  frame.valid_from.hour,
+                   frame.valid_from.min,  frame.valid_from.sec );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ret = mbedtls_snprintf( p, n, "\n%sexpires on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_to.year, crt->valid_to.mon,
-                   crt->valid_to.day,  crt->valid_to.hour,
-                   crt->valid_to.min,  crt->valid_to.sec );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+                   frame.valid_to.year, frame.valid_to.mon,
+                   frame.valid_to.day,  frame.valid_to.hour,
+                   frame.valid_to.min,  frame.valid_to.sec );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ret = mbedtls_snprintf( p, n, "\n%ssigned using      : ", prefix );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
-                             crt->sig_md, crt->sig_opts );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
+                                     sig_info.sig_md, sig_info.sig_opts );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     /* Key size */
     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
-                                      mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
+                                      mbedtls_pk_get_name( &pk ) ) ) != 0 )
     {
         return( ret );
     }
 
     ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
-                          (int) mbedtls_pk_get_bitlen( &crt->pk ) );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+                          (int) mbedtls_pk_get_bitlen( &pk ) );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     /*
      * Optional extensions
      */
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
+    if( frame.ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
     {
         ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
-                        crt->ca_istrue ? "true" : "false" );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+                        frame.ca_istrue ? "true" : "false" );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-        if( crt->max_pathlen > 0 )
+        if( frame.max_pathlen > 0 )
         {
-            ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
-            MBEDTLS_X509_SAFE_SNPRINTF;
+            ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", frame.max_pathlen - 1 );
+            MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
         }
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+    if( frame.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
     {
         ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
         if( ( ret = x509_info_subject_alt_name( &p, &n,
-                                            &crt->subject_alt_names ) ) != 0 )
+                                            subject_alt_names ) ) != 0 )
             return( ret );
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
+    if( frame.ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
     {
         ret = mbedtls_snprintf( p, n, "\n%scert. type        : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-        if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
+        if( ( ret = x509_info_cert_type( &p, &n, frame.ns_cert_type ) ) != 0 )
             return( ret );
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
+    if( frame.ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
     {
         ret = mbedtls_snprintf( p, n, "\n%skey usage         : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-        if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
+        if( ( ret = x509_info_key_usage( &p, &n, frame.key_usage ) ) != 0 )
             return( ret );
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
+    if( frame.ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
     {
         ret = mbedtls_snprintf( p, n, "\n%sext key usage     : ", prefix );
-        MBEDTLS_X509_SAFE_SNPRINTF;
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
         if( ( ret = x509_info_ext_key_usage( &p, &n,
-                                             &crt->ext_key_usage ) ) != 0 )
+                                             ext_key_usage ) ) != 0 )
             return( ret );
     }
 
     ret = mbedtls_snprintf( p, n, "\n" );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-    return( (int) ( size - n ) );
+    ret = (int) ( size - n );
+
+cleanup:
+
+    x509_crt_free_sig_info( &sig_info );
+    mbedtls_pk_free( &pk );
+    mbedtls_x509_name_free( issuer );
+    mbedtls_x509_name_free( subject );
+    mbedtls_x509_sequence_free( ext_key_usage );
+    mbedtls_x509_sequence_free( subject_alt_names );
+
+    return( ret );
 }
 
 struct x509_crt_verify_string {
@@ -1741,8 +2433,8 @@
 #endif /* !MBEDTLS_X509_REMOVE_INFO */
 
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
-                                      unsigned int usage )
+static int x509_crt_check_key_usage_frame( const mbedtls_x509_crt_frame *crt,
+                                           unsigned int usage )
 {
     unsigned int usage_must, usage_may;
     unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
@@ -1763,37 +2455,87 @@
 
     return( 0 );
 }
+
+int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
+                                      unsigned int usage )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    ret = x509_crt_check_key_usage_frame( frame, usage );
+    mbedtls_x509_crt_frame_release( crt );
+
+    return( ret );
+}
 #endif
 
 #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
-int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
-                                       const char *usage_oid,
-                                       size_t usage_len )
+typedef struct
 {
-    const mbedtls_x509_sequence *cur;
+    const char *oid;
+    size_t oid_len;
+} x509_crt_check_ext_key_usage_cb_ctx_t;
 
-    /* Extension is not mandatory, absent means no restriction */
-    if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
-        return( 0 );
+static int x509_crt_check_ext_key_usage_cb( void *ctx,
+                                            int tag,
+                                            unsigned char *data,
+                                            size_t data_len )
+{
+    x509_crt_check_ext_key_usage_cb_ctx_t *cb_ctx =
+        (x509_crt_check_ext_key_usage_cb_ctx_t *) ctx;
+    ((void) tag);
 
-    /*
-     * Look for the requested usage (or wildcard ANY) in our list
-     */
-    for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
+    if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
+                             data, data_len ) == 0 )
     {
-        const mbedtls_x509_buf *cur_oid = &cur->buf;
-
-        if( cur_oid->len == usage_len &&
-            memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
-        {
-            return( 0 );
-        }
-
-        if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
-            return( 0 );
+        return( 1 );
     }
 
-    return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if( data_len == cb_ctx->oid_len && memcmp( data, cb_ctx->oid,
+                                               data_len ) == 0 )
+    {
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
+                                               const char *usage_oid,
+                                               size_t usage_len )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+    unsigned ext_types;
+    unsigned char *p, *end;
+    x509_crt_check_ext_key_usage_cb_ctx_t cb_ctx = { usage_oid, usage_len };
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    /* Extension is not mandatory, absent means no restriction */
+    ext_types = frame->ext_types;
+    if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) != 0 )
+    {
+        p = frame->ext_key_usage_raw.p;
+        end = p + frame->ext_key_usage_raw.len;
+
+        ret = mbedtls_asn1_traverse_sequence_of( &p, end,
+                                                 0xFF, MBEDTLS_ASN1_OID, 0, 0,
+                                                 x509_crt_check_ext_key_usage_cb,
+                                                 &cb_ctx );
+        if( ret == 1 )
+            ret = 0;
+        else
+            ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
+    mbedtls_x509_crt_frame_release( crt );
+    return( ret );
 }
 #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
 
@@ -1801,14 +2543,16 @@
 /*
  * Return 1 if the certificate is revoked, or 0 otherwise.
  */
-int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
+static int x509_serial_is_revoked( unsigned char const *serial,
+                                 size_t serial_len,
+                                 const mbedtls_x509_crl *crl )
 {
     const mbedtls_x509_crl_entry *cur = &crl->entry;
 
     while( cur != NULL && cur->serial.len != 0 )
     {
-        if( crt->serial.len == cur->serial.len &&
-            memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
+        if( serial_len == cur->serial.len &&
+            memcmp( serial, cur->serial.p, serial_len ) == 0 )
         {
             if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
                 return( 1 );
@@ -1820,25 +2564,71 @@
     return( 0 );
 }
 
+int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt,
+                                 const mbedtls_x509_crl *crl )
+{
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
+
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    ret = x509_serial_is_revoked( frame->serial.p,
+                                  frame->serial.len,
+                                  crl );
+    mbedtls_x509_crt_frame_release( crt );
+    return( ret );
+}
+
 /*
  * Check that the given certificate is not revoked according to the CRL.
  * Skip validation if no CRL for the given CA is present.
  */
-static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
+static int x509_crt_verifycrl( unsigned char *crt_serial,
+                               size_t crt_serial_len,
+                               mbedtls_x509_crt *ca_crt,
                                mbedtls_x509_crl *crl_list,
                                const mbedtls_x509_crt_profile *profile )
 {
+    int ret;
     int flags = 0;
     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
     const mbedtls_md_info_t *md_info;
+    mbedtls_x509_buf_raw ca_subject;
+    mbedtls_pk_context *pk;
+    int can_sign;
 
-    if( ca == NULL )
+    if( ca_crt == NULL )
         return( flags );
 
+    {
+        mbedtls_x509_crt_frame const *ca;
+        ret = mbedtls_x509_crt_frame_acquire( ca_crt, &ca );
+        if( ret != 0 )
+            return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
+
+        ca_subject = ca->subject_raw;
+
+        can_sign = 0;
+        if( x509_crt_check_key_usage_frame( ca,
+                                            MBEDTLS_X509_KU_CRL_SIGN ) == 0 )
+        {
+            can_sign = 1;
+        }
+
+        mbedtls_x509_crt_frame_release( ca_crt );
+    }
+
+    ret = mbedtls_x509_crt_pk_acquire( ca_crt, &pk );
+    if( ret != 0 )
+        return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
+
     while( crl_list != NULL )
     {
         if( crl_list->version == 0 ||
-            x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
+            mbedtls_x509_name_cmp_raw( &crl_list->issuer_raw,
+                                       &ca_subject, NULL, NULL ) != 0 )
         {
             crl_list = crl_list->next;
             continue;
@@ -1848,8 +2638,7 @@
          * Check if the CA is configured to sign CRLs
          */
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-        if( mbedtls_x509_crt_check_key_usage( ca,
-                                              MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
+        if( !can_sign )
         {
             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
             break;
@@ -1873,10 +2662,10 @@
             break;
         }
 
-        if( x509_profile_check_key( profile, &ca->pk ) != 0 )
+        if( x509_profile_check_key( profile, pk ) != 0 )
             flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
 
-        if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
+        if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, pk,
                            crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
                            crl_list->sig.p, crl_list->sig.len ) != 0 )
         {
@@ -1896,7 +2685,8 @@
         /*
          * Check if certificate is revoked
          */
-        if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
+        if( x509_serial_is_revoked( crt_serial, crt_serial_len,
+                                    crl_list ) )
         {
             flags |= MBEDTLS_X509_BADCERT_REVOKED;
             break;
@@ -1905,6 +2695,7 @@
         crl_list = crl_list->next;
     }
 
+    mbedtls_x509_crt_pk_release( ca_crt );
     return( flags );
 }
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
@@ -1912,38 +2703,49 @@
 /*
  * Check the signature of a certificate by its parent
  */
-static int x509_crt_check_signature( const mbedtls_x509_crt *child,
+static int x509_crt_check_signature( const mbedtls_x509_crt_sig_info *sig_info,
                                      mbedtls_x509_crt *parent,
                                      mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    const mbedtls_md_info_t *md_info;
-    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    int ret;
+    mbedtls_pk_context *pk;
 
-    md_info = mbedtls_md_info_from_type( child->sig_md );
-    if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
-    {
-        /* Note: this can't happen except after an internal error */
-        return( -1 );
-    }
+    ret = mbedtls_x509_crt_pk_acquire( parent, &pk );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
 
     /* Skip expensive computation on obvious mismatch */
-    if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
-        return( -1 );
-
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
+    if( ! mbedtls_pk_can_do( pk, sig_info->sig_pk ) )
     {
-        return( mbedtls_pk_verify_restartable( &parent->pk,
-                    child->sig_md, hash, mbedtls_md_get_size( md_info ),
-                    child->sig.p, child->sig.len, &rs_ctx->pk ) );
+        ret = -1;
+        goto exit;
     }
-#else
-    (void) rs_ctx;
-#endif
 
-    return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
-                child->sig_md, hash, mbedtls_md_get_size( md_info ),
-                child->sig.p, child->sig.len ) );
+#if !( defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) )
+    ((void) rs_ctx);
+#else
+    if( rs_ctx != NULL && sig_info->sig_pk == MBEDTLS_PK_ECDSA )
+    {
+        ret = mbedtls_pk_verify_restartable( pk,
+                    sig_info->sig_md,
+                    sig_info->crt_hash, sig_info->crt_hash_len,
+                    sig_info->sig.p, sig_info->sig.len,
+                    &rs_ctx->pk );
+    }
+    else
+#endif
+    {
+        ret = mbedtls_pk_verify_ext( sig_info->sig_pk,
+                                     sig_info->sig_opts,
+                                     pk,
+                                     sig_info->sig_md,
+                                     sig_info->crt_hash, sig_info->crt_hash_len,
+                                     sig_info->sig.p, sig_info->sig.len );
+    }
+
+exit:
+    mbedtls_x509_crt_pk_release( parent );
+    return( ret );
 }
 
 /*
@@ -1952,15 +2754,19 @@
  *
  * top means parent is a locally-trusted certificate
  */
-static int x509_crt_check_parent( const mbedtls_x509_crt *child,
-                                  const mbedtls_x509_crt *parent,
+static int x509_crt_check_parent( const mbedtls_x509_crt_sig_info *sig_info,
+                                  const mbedtls_x509_crt_frame *parent,
                                   int top )
 {
     int need_ca_bit;
 
     /* Parent must be the issuer */
-    if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
+    if( mbedtls_x509_name_cmp_raw( &sig_info->issuer_raw,
+                                   &parent->subject_raw,
+                                   NULL, NULL ) != 0 )
+    {
         return( -1 );
+    }
 
     /* Parent must have the basicConstraints CA bit set as a general rule */
     need_ca_bit = 1;
@@ -1974,7 +2780,8 @@
 
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
     if( need_ca_bit &&
-        mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
+        x509_crt_check_key_usage_frame( parent,
+                                        MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
     {
         return( -1 );
     }
@@ -2027,7 +2834,7 @@
  *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
 static int x509_crt_find_parent_in(
-                        mbedtls_x509_crt *child,
+                        mbedtls_x509_crt_sig_info const *child_sig,
                         mbedtls_x509_crt *candidates,
                         mbedtls_x509_crt **r_parent,
                         int *r_signature_is_good,
@@ -2037,7 +2844,7 @@
                         mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
     int ret;
-    mbedtls_x509_crt *parent, *fallback_parent;
+    mbedtls_x509_crt *parent_crt, *fallback_parent;
     int signature_is_good, fallback_signature_is_good;
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -2045,7 +2852,7 @@
     if( rs_ctx != NULL && rs_ctx->parent != NULL )
     {
         /* restore saved state */
-        parent = rs_ctx->parent;
+        parent_crt = rs_ctx->parent;
         fallback_parent = rs_ctx->fallback_parent;
         fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
 
@@ -2062,30 +2869,55 @@
     fallback_parent = NULL;
     fallback_signature_is_good = 0;
 
-    for( parent = candidates; parent != NULL; parent = parent->next )
+    for( parent_crt = candidates; parent_crt != NULL;
+         parent_crt = parent_crt->next )
     {
-        /* basic parenting skills (name, CA bit, key usage) */
-        if( x509_crt_check_parent( child, parent, top ) != 0 )
-            continue;
+        int parent_valid, parent_match, path_len_ok;
 
-        /* +1 because stored max_pathlen is 1 higher that the actual value */
-        if( parent->max_pathlen > 0 &&
-            (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
-        {
-            continue;
-        }
-
-        /* Signature */
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 check_signature:
 #endif
-        ret = x509_crt_check_signature( child, parent, rs_ctx );
+
+        parent_valid = parent_match = path_len_ok = 0;
+        {
+            mbedtls_x509_crt_frame const *parent;
+
+            ret = mbedtls_x509_crt_frame_acquire( parent_crt, &parent );
+            if( ret != 0 )
+                return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+            if( !mbedtls_x509_time_is_past( &parent->valid_to ) &&
+                !mbedtls_x509_time_is_future( &parent->valid_from ) )
+            {
+                parent_valid = 1;
+            }
+
+            /* basic parenting skills (name, CA bit, key usage) */
+            if( x509_crt_check_parent( child_sig, parent, top ) == 0 )
+                parent_match = 1;
+
+            /* +1 because the stored max_pathlen is 1 higher
+             * than the actual value */
+            if( !( parent->max_pathlen > 0 &&
+                   (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) )
+            {
+                path_len_ok = 1;
+            }
+
+            mbedtls_x509_crt_frame_release( parent_crt );
+        }
+
+        if( parent_match == 0 || path_len_ok == 0 )
+            continue;
+
+        /* Signature */
+        ret = x509_crt_check_signature( child_sig, parent_crt, rs_ctx );
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
         if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
         {
             /* save state */
-            rs_ctx->parent = parent;
+            rs_ctx->parent = parent_crt;
             rs_ctx->fallback_parent = fallback_parent;
             rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
 
@@ -2100,12 +2932,11 @@
             continue;
 
         /* optional time check */
-        if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
-            mbedtls_x509_time_is_future( &parent->valid_from ) )
+        if( !parent_valid )
         {
             if( fallback_parent == NULL )
             {
-                fallback_parent = parent;
+                fallback_parent = parent_crt;
                 fallback_signature_is_good = signature_is_good;
             }
 
@@ -2115,9 +2946,9 @@
         break;
     }
 
-    if( parent != NULL )
+    if( parent_crt != NULL )
     {
-        *r_parent = parent;
+        *r_parent = parent_crt;
         *r_signature_is_good = signature_is_good;
     }
     else
@@ -2152,7 +2983,8 @@
  *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
 static int x509_crt_find_parent(
-                        mbedtls_x509_crt *child,
+                        mbedtls_x509_crt_sig_info const *child_sig,
+                        mbedtls_x509_crt *rest,
                         mbedtls_x509_crt *trust_ca,
                         mbedtls_x509_crt **parent,
                         int *parent_is_trusted,
@@ -2176,9 +3008,9 @@
 #endif
 
     while( 1 ) {
-        search_list = *parent_is_trusted ? trust_ca : child->next;
+        search_list = *parent_is_trusted ? trust_ca : rest;
 
-        ret = x509_crt_find_parent_in( child, search_list,
+        ret = x509_crt_find_parent_in( child_sig, search_list,
                                        parent, signature_is_good,
                                        *parent_is_trusted,
                                        path_cnt, self_cnt, rs_ctx );
@@ -2219,14 +3051,10 @@
  * check for self-issued as self-signatures are not checked)
  */
 static int x509_crt_check_ee_locally_trusted(
-                    mbedtls_x509_crt *crt,
-                    mbedtls_x509_crt *trust_ca )
+                    mbedtls_x509_crt_frame const *crt,
+                    mbedtls_x509_crt const *trust_ca )
 {
-    mbedtls_x509_crt *cur;
-
-    /* must be self-issued */
-    if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
-        return( -1 );
+    mbedtls_x509_crt const *cur;
 
     /* look for an exact match with trusted cert */
     for( cur = trust_ca; cur != NULL; cur = cur->next )
@@ -2261,7 +3089,7 @@
  * Tests for (aspects of) this function should include at least:
  * - trusted EE
  * - EE -> trusted root
- * - EE -> intermedate CA -> trusted root
+ * - EE -> intermediate CA -> trusted root
  * - if relevant: EE untrusted
  * - if relevant: EE -> intermediate, untrusted
  * with the aspect under test checked at each relevant level (EE, int, root).
@@ -2295,8 +3123,8 @@
     int ret;
     uint32_t *flags;
     mbedtls_x509_crt_verify_chain_item *cur;
-    mbedtls_x509_crt *child;
-    mbedtls_x509_crt *parent;
+    mbedtls_x509_crt *child_crt;
+    mbedtls_x509_crt *parent_crt;
     int parent_is_trusted;
     int child_is_trusted;
     int signature_is_good;
@@ -2312,58 +3140,100 @@
 
         /* restore derived state */
         cur = &ver_chain->items[ver_chain->len - 1];
-        child = cur->crt;
-        flags = &cur->flags;
+        child_crt = cur->crt;
 
+        child_is_trusted = 0;
         goto find_parent;
     }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-    child = crt;
+    child_crt = crt;
     self_cnt = 0;
     parent_is_trusted = 0;
     child_is_trusted = 0;
 
     while( 1 ) {
+#if defined(MBEDTLS_X509_CRL_PARSE_C)
+        mbedtls_x509_buf_raw child_serial;
+#endif /* MBEDTLS_X509_CRL_PARSE_C */
+        int self_issued;
+
         /* Add certificate to the verification chain */
         cur = &ver_chain->items[ver_chain->len];
-        cur->crt = child;
+        cur->crt = child_crt;
         cur->flags = 0;
         ver_chain->len++;
-        flags = &cur->flags;
-
-        /* Check time-validity (all certificates) */
-        if( mbedtls_x509_time_is_past( &child->valid_to ) )
-            *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
-
-        if( mbedtls_x509_time_is_future( &child->valid_from ) )
-            *flags |= MBEDTLS_X509_BADCERT_FUTURE;
-
-        /* Stop here for trusted roots (but not for trusted EE certs) */
-        if( child_is_trusted )
-            return( 0 );
-
-        /* Check signature algorithm: MD & PK algs */
-        if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
-            *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
-
-        if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
-            *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
-
-        /* Special case: EE certs that are locally trusted */
-        if( ver_chain->len == 1 &&
-            x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
-        {
-            return( 0 );
-        }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 find_parent:
 #endif
-        /* Look for a parent in trusted CAs or up the chain */
-        ret = x509_crt_find_parent( child, trust_ca, &parent,
-                                       &parent_is_trusted, &signature_is_good,
-                                       ver_chain->len - 1, self_cnt, rs_ctx );
+
+        flags = &cur->flags;
+
+        {
+            mbedtls_x509_crt_sig_info child_sig;
+            {
+                mbedtls_x509_crt_frame const *child;
+
+                ret = mbedtls_x509_crt_frame_acquire( child_crt, &child );
+                if( ret != 0 )
+                    return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+                /* Check time-validity (all certificates) */
+                if( mbedtls_x509_time_is_past( &child->valid_to ) )
+                    *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
+                if( mbedtls_x509_time_is_future( &child->valid_from ) )
+                    *flags |= MBEDTLS_X509_BADCERT_FUTURE;
+
+                /* Stop here for trusted roots (but not for trusted EE certs) */
+                if( child_is_trusted )
+                {
+                    mbedtls_x509_crt_frame_release( child_crt );
+                    return( 0 );
+                }
+
+                self_issued = 0;
+                if( mbedtls_x509_name_cmp_raw( &child->issuer_raw,
+                                               &child->subject_raw,
+                                               NULL, NULL ) == 0 )
+                {
+                    self_issued = 1;
+                }
+
+                /* Check signature algorithm: MD & PK algs */
+                if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
+                    *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
+
+                if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
+                    *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+
+                /* Special case: EE certs that are locally trusted */
+                if( ver_chain->len == 1 && self_issued &&
+                    x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
+                {
+                    mbedtls_x509_crt_frame_release( child_crt );
+                    return( 0 );
+                }
+
+#if defined(MBEDTLS_X509_CRL_PARSE_C)
+                child_serial = child->serial;
+#endif /* MBEDTLS_X509_CRL_PARSE_C */
+
+                ret = x509_crt_get_sig_info( child, &child_sig );
+                mbedtls_x509_crt_frame_release( child_crt );
+
+                if( ret != 0 )
+                    return( MBEDTLS_ERR_X509_FATAL_ERROR );
+            }
+
+            /* Look for a parent in trusted CAs or up the chain */
+            ret = x509_crt_find_parent( &child_sig, child_crt->next,
+                                        trust_ca, &parent_crt,
+                                        &parent_is_trusted, &signature_is_good,
+                                        ver_chain->len - 1, self_cnt, rs_ctx );
+
+            x509_crt_free_sig_info( &child_sig );
+        }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
         if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
@@ -2372,7 +3242,6 @@
             rs_ctx->in_progress = x509_crt_rs_find_parent;
             rs_ctx->self_cnt = self_cnt;
             rs_ctx->ver_chain = *ver_chain; /* struct copy */
-
             return( ret );
         }
 #else
@@ -2380,7 +3249,7 @@
 #endif
 
         /* No parent? We're done here */
-        if( parent == NULL )
+        if( parent_crt == NULL )
         {
             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
             return( 0 );
@@ -2389,11 +3258,8 @@
         /* Count intermediate self-issued (not necessarily self-signed) certs.
          * These can occur with some strategies for key rollover, see [SIRO],
          * and should be excluded from max_pathlen checks. */
-        if( ver_chain->len != 1 &&
-            x509_name_cmp( &child->issuer, &child->subject ) == 0 )
-        {
+        if( ver_chain->len != 1 && self_issued )
             self_cnt++;
-        }
 
         /* path_cnt is 0 for the first intermediate CA,
          * and if parent is trusted it's not an intermediate CA */
@@ -2408,20 +3274,31 @@
         if( ! signature_is_good )
             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
 
-        /* check size of signing key */
-        if( x509_profile_check_key( profile, &parent->pk ) != 0 )
-            *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+        {
+            mbedtls_pk_context *parent_pk;
+            ret = mbedtls_x509_crt_pk_acquire( parent_crt, &parent_pk );
+            if( ret != 0 )
+                return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+            /* check size of signing key */
+            if( x509_profile_check_key( profile, parent_pk ) != 0 )
+                *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
+            mbedtls_x509_crt_pk_release( parent_crt );
+        }
 
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
         /* Check trusted CA's CRL for the given crt */
-        *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile );
+        *flags |= x509_crt_verifycrl( child_serial.p,
+                                      child_serial.len,
+                                      parent_crt, ca_crl, profile );
 #else
         (void) ca_crl;
 #endif
 
         /* prepare for next iteration */
-        child = parent;
-        parent = NULL;
+        child_crt = parent_crt;
+        parent_crt = NULL;
         child_is_trusted = parent_is_trusted;
         signature_is_good = 0;
     }
@@ -2430,18 +3307,17 @@
 /*
  * Check for CN match
  */
-static int x509_crt_check_cn( const mbedtls_x509_buf *name,
-                              const char *cn, size_t cn_len )
+static int x509_crt_check_cn( unsigned char const *buf,
+                              size_t buflen,
+                              const char *cn,
+                              size_t cn_len )
 {
-    /* try exact match */
-    if( name->len == cn_len &&
-        x509_memcasecmp( cn, name->p, cn_len ) == 0 )
-    {
+    /* Try exact match */
+    if( mbedtls_x509_memcasecmp( cn, buf, buflen, cn_len ) == 0 )
         return( 0 );
-    }
 
     /* try wildcard match */
-    if( x509_check_wildcard( cn, name ) == 0 )
+    if( x509_check_wildcard( cn, cn_len, buf, buflen ) == 0 )
     {
         return( 0 );
     }
@@ -2449,42 +3325,95 @@
     return( -1 );
 }
 
+/* Returns 1 on a match and 0 on a mismatch.
+ * This is because this function is used as a callback for
+ * mbedtls_x509_name_cmp_raw(), which continues the name
+ * traversal as long as the callback returns 0. */
+static int x509_crt_check_name( void *ctx,
+                                mbedtls_x509_buf *oid,
+                                mbedtls_x509_buf *val,
+                                int next_merged )
+{
+    char const *cn = (char const*) ctx;
+    size_t cn_len = strlen( cn );
+    ((void) next_merged);
+
+    if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, oid ) == 0 &&
+        x509_crt_check_cn( val->p, val->len, cn, cn_len ) == 0 )
+    {
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
+/* Returns 1 on a match and 0 on a mismatch.
+ * This is because this function is used as a callback for
+ * mbedtls_asn1_traverse_sequence_of(), which continues the
+ * traversal as long as the callback returns 0. */
+static int x509_crt_subject_alt_check_name( void *ctx,
+                                            int tag,
+                                            unsigned char *data,
+                                            size_t data_len )
+{
+    char const *cn = (char const*) ctx;
+    size_t cn_len = strlen( cn );
+    ((void) tag);
+
+    if( x509_crt_check_cn( data, data_len, cn, cn_len ) == 0 )
+        return( 1 );
+
+    return( 0 );
+}
+
 /*
  * Verify the requested CN - only call this if cn is not NULL!
  */
-static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
-                                  const char *cn,
-                                  uint32_t *flags )
+static int x509_crt_verify_name( const mbedtls_x509_crt *crt,
+                                 const char *cn,
+                                 uint32_t *flags )
 {
-    const mbedtls_x509_name *name;
-    const mbedtls_x509_sequence *cur;
-    size_t cn_len = strlen( cn );
+    int ret;
+    mbedtls_x509_crt_frame const *frame;
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+    if( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
     {
-        for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
-        {
-            if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 )
-                break;
-        }
+        unsigned char *p =
+            frame->subject_alt_raw.p;
+        const unsigned char *end =
+            frame->subject_alt_raw.p + frame->subject_alt_raw.len;
 
-        if( cur == NULL )
-            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+        ret = mbedtls_asn1_traverse_sequence_of( &p, end,
+                                      MBEDTLS_ASN1_TAG_CLASS_MASK,
+                                      MBEDTLS_ASN1_CONTEXT_SPECIFIC,
+                                      MBEDTLS_ASN1_TAG_VALUE_MASK,
+                                      2 /* SubjectAlt DNS */,
+                                      x509_crt_subject_alt_check_name,
+                                      (void *) cn );
     }
     else
     {
-        for( name = &crt->subject; name != NULL; name = name->next )
-        {
-            if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
-                x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
-            {
-                break;
-            }
-        }
-
-        if( name == NULL )
-            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+        ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
+                                         &frame->subject_raw,
+                                         x509_crt_check_name, (void *) cn );
     }
+
+    mbedtls_x509_crt_frame_release( crt );
+
+    /* x509_crt_check_name() and x509_crt_subject_alt_check_name()
+     * return 1 when finding a name component matching `cn`. */
+    if( ret == 1 )
+        return( 0 );
+
+    if( ret != 0 )
+        ret = MBEDTLS_ERR_X509_FATAL_ERROR;
+
+    *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+    return( ret );
 }
 
 /*
@@ -2566,7 +3495,6 @@
                      mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
     int ret;
-    mbedtls_pk_type_t pk_type;
     mbedtls_x509_crt_verify_chain ver_chain;
     uint32_t ee_flags;
 
@@ -2582,16 +3510,31 @@
 
     /* check name if requested */
     if( cn != NULL )
-        x509_crt_verify_name( crt, cn, &ee_flags );
+    {
+        ret = x509_crt_verify_name( crt, cn, &ee_flags );
+        if( ret != 0 )
+            return( ret );
+    }
 
-    /* Check the type and size of the key */
-    pk_type = mbedtls_pk_get_type( &crt->pk );
+    {
+        mbedtls_pk_context *pk;
+        mbedtls_pk_type_t pk_type;
 
-    if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
-        ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+        ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
+        if( ret != 0 )
+            return( MBEDTLS_ERR_X509_FATAL_ERROR );
 
-    if( x509_profile_check_key( profile, &crt->pk ) != 0 )
-        ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+        /* Check the type and size of the key */
+        pk_type = mbedtls_pk_get_type( pk );
+
+        if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
+            ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+
+        if( x509_profile_check_key( profile, pk ) != 0 )
+            ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
+        mbedtls_x509_crt_pk_release( crt );
+    }
 
     /* Check the chain */
     ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
@@ -2641,63 +3584,32 @@
 /*
  * Unallocate all certificate data
  */
+
 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
 {
     mbedtls_x509_crt *cert_cur = crt;
     mbedtls_x509_crt *cert_prv;
-    mbedtls_x509_name *name_cur;
-    mbedtls_x509_name *name_prv;
-    mbedtls_x509_sequence *seq_cur;
-    mbedtls_x509_sequence *seq_prv;
 
     if( crt == NULL )
         return;
 
     do
     {
+        x509_crt_cache_free( cert_cur->cache );
+        mbedtls_free( cert_cur->cache );
+
+#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
         mbedtls_pk_free( &cert_cur->pk );
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
         mbedtls_free( cert_cur->sig_opts );
 #endif
 
-        name_cur = cert_cur->issuer.next;
-        while( name_cur != NULL )
-        {
-            name_prv = name_cur;
-            name_cur = name_cur->next;
-            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-            mbedtls_free( name_prv );
-        }
-
-        name_cur = cert_cur->subject.next;
-        while( name_cur != NULL )
-        {
-            name_prv = name_cur;
-            name_cur = name_cur->next;
-            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-            mbedtls_free( name_prv );
-        }
-
-        seq_cur = cert_cur->ext_key_usage.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 );
-        }
-
-        seq_cur = cert_cur->subject_alt_names.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 );
-        }
+        mbedtls_x509_name_free( cert_cur->issuer.next );
+        mbedtls_x509_name_free( cert_cur->subject.next );
+        mbedtls_x509_sequence_free( cert_cur->ext_key_usage.next );
+        mbedtls_x509_sequence_free( cert_cur->subject_alt_names.next );
+#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
 
         if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
         {
diff --git a/library/x509_csr.c b/library/x509_csr.c
index aa519fb..9b58a86 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
 
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -183,15 +184,17 @@
         mbedtls_x509_csr_free( csr );
         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
     }
+    p += len;
+    csr->subject_raw.len = p - csr->subject_raw.p;
 
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
+    if( ( ret = mbedtls_x509_get_name( csr->subject_raw.p,
+                                       csr->subject_raw.len,
+                                       &csr->subject ) ) != 0 )
     {
         mbedtls_x509_csr_free( csr );
         return( ret );
     }
 
-    csr->subject_raw.len = p - csr->subject_raw.p;
-
     /*
      *  subjectPKInfo SubjectPublicKeyInfo
      */
@@ -357,8 +360,8 @@
     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
-                             csr->sig_opts );
+    ret = mbedtls_x509_sig_alg_gets( p, n, csr->sig_pk,
+                                     csr->sig_md, csr->sig_opts );
     MBEDTLS_X509_SAFE_SNPRINTF;
 
     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 10497e7..93cd82f 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_X509_CRT_WRITE_C)
 
 #include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/sha1.h"
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index d70ba0e..85331b1 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
 
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/platform_util.h"
diff --git a/programs/Makefile b/programs/Makefile
index 28c747b..d09949b 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -296,6 +296,8 @@
 clean:
 ifndef WINDOWS
 	rm -f $(APPS)
+	-rm -f ssl/ssl_pthread_server$(EXEXT)
+	-rm -f test/cpp_dummy_build$(EXEXT)
 else
 	del /S /Q /F *.o *.exe
 endif
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index bdeac3a..8242ea7 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -80,17 +80,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index f58e616..a5acf5b 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -82,17 +82,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/hash/generic_sum.c b/programs/hash/generic_sum.c
index 4b7fe37..709a149 100644
--- a/programs/hash/generic_sum.c
+++ b/programs/hash/generic_sum.c
@@ -52,17 +52,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static int generic_wrapper( const mbedtls_md_info_t *md_info, char *filename, unsigned char *sum )
 {
diff --git a/programs/hash/hello.c b/programs/hash/hello.c
index 6046f86..55a0c7e 100644
--- a/programs/hash/hello.c
+++ b/programs/hash/hello.c
@@ -48,17 +48,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index 1dce31a..86b260c 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -72,17 +72,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index cca43ca..bf5482e 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -69,17 +69,6 @@
  */
 #define GENERATOR "4"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char **argv )
 {
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index a797e60..c011774 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -72,17 +72,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/pkey/ecdh_curve25519.c b/programs/pkey/ecdh_curve25519.c
index 9267c7e..9f849dd 100644
--- a/programs/pkey/ecdh_curve25519.c
+++ b/programs/pkey/ecdh_curve25519.c
@@ -53,17 +53,6 @@
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/ecdh.h"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c
index 4471a20..b851c31 100644
--- a/programs/pkey/ecdsa.c
+++ b/programs/pkey/ecdsa.c
@@ -100,17 +100,6 @@
 #define dump_pubkey( a, b )
 #endif
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 35fc149..23e4e14 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -137,17 +137,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c
index 0bd61e4..7939309 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -64,7 +64,6 @@
     "    password_file=%%s    default: \"\"\n"          \
     "\n"
 
-
 #if !defined(MBEDTLS_BIGNUM_C) ||                                  \
     !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_FS_IO)
 int main( void )
@@ -75,17 +74,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index b81530c..6096429 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -98,17 +98,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/pkey/mpi_demo.c b/programs/pkey/mpi_demo.c
index 80573c0..ecdcd32 100644
--- a/programs/pkey/mpi_demo.c
+++ b/programs/pkey/mpi_demo.c
@@ -50,17 +50,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/pkey/pk_decrypt.c b/programs/pkey/pk_decrypt.c
index 978f39e..bf42507 100644
--- a/programs/pkey/pk_decrypt.c
+++ b/programs/pkey/pk_decrypt.c
@@ -48,7 +48,6 @@
 #include <string.h>
 #endif
 
-
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_PK_PARSE_C) ||  \
     !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \
     !defined(MBEDTLS_CTR_DRBG_C)
@@ -61,17 +60,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/pk_encrypt.c b/programs/pkey/pk_encrypt.c
index 806c59a..a32b147 100644
--- a/programs/pkey/pk_encrypt.c
+++ b/programs/pkey/pk_encrypt.c
@@ -61,17 +61,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 7354082..47a098a 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -60,17 +60,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c
index 9fcf029..a6bfe3f 100644
--- a/programs/pkey/pk_verify.c
+++ b/programs/pkey/pk_verify.c
@@ -56,17 +56,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
@@ -112,7 +101,6 @@
         goto exit;
     }
 
-
     i = fread( buf, 1, sizeof(buf), f );
 
     fclose( f );
diff --git a/programs/pkey/rsa_decrypt.c b/programs/pkey/rsa_decrypt.c
index dc8a920..ff71bd0 100644
--- a/programs/pkey/rsa_decrypt.c
+++ b/programs/pkey/rsa_decrypt.c
@@ -59,17 +59,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/rsa_encrypt.c b/programs/pkey/rsa_encrypt.c
index e9effe8..4a71c15 100644
--- a/programs/pkey/rsa_encrypt.c
+++ b/programs/pkey/rsa_encrypt.c
@@ -59,17 +59,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/rsa_genkey.c b/programs/pkey/rsa_genkey.c
index 81867ee..d556c19 100644
--- a/programs/pkey/rsa_genkey.c
+++ b/programs/pkey/rsa_genkey.c
@@ -64,17 +64,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
index f014872..9bcd7a6 100644
--- a/programs/pkey/rsa_sign.c
+++ b/programs/pkey/rsa_sign.c
@@ -56,17 +56,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c
index 5131745..42209e2 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -60,17 +60,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
index 5d1c085..94f0ef9 100644
--- a/programs/pkey/rsa_verify.c
+++ b/programs/pkey/rsa_verify.c
@@ -55,17 +55,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c
index 34122ca..148cd51 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -60,17 +60,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
@@ -125,7 +114,6 @@
         goto exit;
     }
 
-
     i = fread( buf, 1, MBEDTLS_MPI_MAX_SIZE, f );
 
     fclose( f );
diff --git a/programs/random/gen_entropy.c b/programs/random/gen_entropy.c
index 3b350ed..6ae63b7 100644
--- a/programs/random/gen_entropy.c
+++ b/programs/random/gen_entropy.c
@@ -51,17 +51,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/random/gen_random_ctr_drbg.c b/programs/random/gen_random_ctr_drbg.c
index a50402f..59df34b 100644
--- a/programs/random/gen_random_ctr_drbg.c
+++ b/programs/random/gen_random_ctr_drbg.c
@@ -54,17 +54,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/random/gen_random_havege.c b/programs/random/gen_random_havege.c
index ef888ff..5ea52ae 100644
--- a/programs/random/gen_random_havege.c
+++ b/programs/random/gen_random_havege.c
@@ -52,17 +52,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index cd2866a..cb2851b 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -82,17 +82,6 @@
 
 #define DEBUG_LEVEL 0
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index dd21fbf..7d19d69 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -91,17 +91,6 @@
 #define READ_TIMEOUT_MS 10000   /* 5 seconds */
 #define DEBUG_LEVEL 0
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
@@ -236,11 +225,11 @@
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
-#if defined(MBEDTLS_SSL_CACHE_C)
+#if defined(MBEDTLS_SSL_CACHE_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     mbedtls_ssl_conf_session_cache( &conf, &cache,
                                    mbedtls_ssl_cache_get,
                                    mbedtls_ssl_cache_set );
-#endif
+#endif /* MBEDTLS_SSL_CACHE_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
     mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
    if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c
index ff36128..4b8140e 100644
--- a/programs/ssl/mini_client.c
+++ b/programs/ssl/mini_client.c
@@ -166,17 +166,6 @@
     ssl_write_failed,
 };
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( void )
 {
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index d45a663..419be6b 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -274,6 +274,14 @@
     }
 #endif /* MBEDTLS_CHECK_PARAMS */
 
+#if defined(MBEDTLS_CHECK_PARAMS_ASSERT)
+    if( strcmp( "MBEDTLS_CHECK_PARAMS_ASSERT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CHECK_PARAMS_ASSERT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */
+
 #if defined(MBEDTLS_TIMING_ALT)
     if( strcmp( "MBEDTLS_TIMING_ALT", config ) == 0 )
     {
@@ -1410,6 +1418,22 @@
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_NO_SESSION_CACHE)
+    if( strcmp( "MBEDTLS_SSL_NO_SESSION_CACHE", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_NO_SESSION_CACHE );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_NO_SESSION_CACHE */
+
+#if defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
+    if( strcmp( "MBEDTLS_SSL_NO_SESSION_RESUMPTION", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_NO_SESSION_RESUMPTION );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_NO_SESSION_RESUMPTION */
+
 #if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( strcmp( "MBEDTLS_SSL_EXPORT_KEYS", config ) == 0 )
     {
@@ -1466,6 +1490,22 @@
     }
 #endif /* MBEDTLS_VERSION_FEATURES */
 
+#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
+    if( strcmp( "MBEDTLS_X509_ON_DEMAND_PARSING", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_X509_ON_DEMAND_PARSING );
+        return( 0 );
+    }
+#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
+
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
+    if( strcmp( "MBEDTLS_X509_ALWAYS_FLUSH", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_X509_ALWAYS_FLUSH );
+        return( 0 );
+    }
+#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
+
 #if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
     if( strcmp( "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", config ) == 0 )
     {
@@ -2578,6 +2618,94 @@
     }
 #endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */
 
+#if defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+    if( strcmp( "MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+
+#if defined(MBEDTLS_SSL_CONF_AUTHMODE)
+    if( strcmp( "MBEDTLS_SSL_CONF_AUTHMODE", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_AUTHMODE );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_AUTHMODE */
+
+#if defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
+    if( strcmp( "MBEDTLS_SSL_CONF_READ_TIMEOUT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_READ_TIMEOUT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_READ_TIMEOUT */
+
+#if defined(MBEDTLS_SSL_CONF_ENDPOINT)
+    if( strcmp( "MBEDTLS_SSL_CONF_ENDPOINT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_ENDPOINT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_ENDPOINT */
+
+#if defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
+    if( strcmp( "MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST */
+
+#if defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN)
+    if( strcmp( "MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN */
+
+#if defined(MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX)
+    if( strcmp( "MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX */
+
+#if defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
+    if( strcmp( "MBEDTLS_SSL_CONF_ANTI_REPLAY", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_ANTI_REPLAY );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_ANTI_REPLAY */
+
+#if defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
+    if( strcmp( "MBEDTLS_SSL_CONF_BADMAC_LIMIT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_BADMAC_LIMIT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_BADMAC_LIMIT */
+
+#if defined(MBEDTLS_SSL_CONF_CID_LEN)
+    if( strcmp( "MBEDTLS_SSL_CONF_CID_LEN", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_CID_LEN );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_CID_LEN */
+
+#if defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
+    if( strcmp( "MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
+
 #if defined(MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET)
     if( strcmp( "MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET", config ) == 0 )
     {
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index 375e5e3..28ecc21 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -72,17 +72,6 @@
 
 #define DEBUG_LEVEL 1
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 9828576..8d7ee0a 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -293,6 +293,27 @@
 #define USAGE_SERIALIZATION ""
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
+#define USAGE_AUTH_MODE \
+    "    auth_mode=%%s        default: (library default: none)\n" \
+    "                        options: none, optional, required\n"
+#else
+#define USAGE_AUTH_MODE ""
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+#define USAGE_ALLOW_LEGACY_RENEGO    "    allow_legacy=%%d     default: (library default: no)\n"
+#else
+#define USAGE_ALLOW_LEGACY_RENEGO ""
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
+#define USAGE_READ_TIMEOUT                              \
+    "    read_timeout=%%d     default: 0 ms (no timeout)\n"
+#else
+#define USAGE_READ_TIMEOUT ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_client2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -311,21 +332,20 @@
     "                        options: 1 (non-blocking), 2 (added delays)\n"   \
     "    event=%%d            default: 0 (loop)\n"                            \
     "                        options: 1 (level-triggered, implies nbio=1),\n" \
-    "    read_timeout=%%d     default: 0 ms (no timeout)\n"        \
+    USAGE_READ_TIMEOUT                                                  \
     "    max_resend=%%d       default: 0 (no resend on timeout)\n" \
     "\n"                                                    \
     USAGE_DTLS                                              \
     USAGE_CID                                               \
     "\n"                                                    \
-    "    auth_mode=%%s        default: (library default: none)\n" \
-    "                        options: none, optional, required\n" \
+    USAGE_AUTH_MODE                                         \
     USAGE_IO                                                \
     "\n"                                                    \
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
     USAGE_ECRESTART                                         \
     "\n"                                                    \
-    "    allow_legacy=%%d     default: (library default: no)\n"   \
+    USAGE_ALLOW_LEGACY_RENEGO                               \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     "    reconnect=%%d        number of reconnections using session resumption\n" \
@@ -363,17 +383,6 @@
 #define ALPN_LIST_SIZE  10
 #define CURVE_LIST_SIZE 20
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
@@ -908,8 +917,10 @@
             if( opt.event < 0 || opt.event > 2 )
                 goto usage;
         }
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
         else if( strcmp( p, "read_timeout" ) == 0 )
             opt.read_timeout = atoi( q );
+#endif
         else if( strcmp( p, "max_resend" ) == 0 )
         {
             opt.max_resend = atoi( q );
@@ -980,6 +991,7 @@
                 MBEDTLS_SSL_RENEGOTIATION_ENABLED :
                 MBEDTLS_SSL_RENEGOTIATION_DISABLED;
         }
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
             switch( atoi( q ) )
@@ -996,6 +1008,7 @@
                 default: goto usage;
             }
         }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
             opt.renegotiate = atoi( q );
@@ -1175,6 +1188,7 @@
             else
                 goto usage;
         }
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
         else if( strcmp( p, "auth_mode" ) == 0 )
         {
             if( strcmp( q, "none" ) == 0 )
@@ -1186,6 +1200,7 @@
             else
                 goto usage;
         }
+#endif
         else if( strcmp( p, "max_frag_len" ) == 0 )
         {
             if( strcmp( q, "512" ) == 0 )
@@ -1655,7 +1670,9 @@
     memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    !defined(MBEDTLS_SSL_CONF_CID_LEN) &&      \
+    !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
     if( opt.cid_enabled == 1 || opt.cid_enabled_renego == 1 )
     {
         if( opt.cid_enabled == 1        &&
@@ -1680,7 +1697,9 @@
             goto exit;
         }
     }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID &&
+          !MBEDTLS_SSL_CONF_CID_LEN &&
+          !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 
     if( opt.auth_mode != DFL_AUTH_MODE )
         mbedtls_ssl_conf_authmode( &conf, opt.auth_mode );
@@ -1748,7 +1767,9 @@
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
     mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout );
+#endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     mbedtls_ssl_conf_session_tickets( &conf, opt.tickets );
@@ -1762,8 +1783,10 @@
         mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 );
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     if( opt.allow_legacy != DFL_ALLOW_LEGACY )
         mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy );
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation );
 #endif
@@ -2545,12 +2568,14 @@
             }
         }
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION)
         if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 )
         {
             mbedtls_printf( " failed\n  ! mbedtls_ssl_set_session returned -0x%x\n\n",
                             -ret );
             goto exit;
         }
+#endif /* !MBEDTLS_SSL_NO_SESSION_RESUMPTION */
 
         if( ( ret = mbedtls_net_connect( &server_fd,
                         opt.server_addr, opt.server_port,
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index bbe61fd..b4a5414 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -89,17 +89,6 @@
 
 #define DEBUG_LEVEL 0
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index e5d9658..5880468 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -142,17 +142,6 @@
     "    force_ciphersuite=<name>    default: all enabled\n"  \
     " acceptable ciphersuite names:\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c
index 17f4584..11298a5 100644
--- a/programs/ssl/ssl_pthread_server.c
+++ b/programs/ssl/ssl_pthread_server.c
@@ -82,17 +82,6 @@
 #include "mbedtls/memory_buffer_alloc.h"
 #endif
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 #define HTTP_RESPONSE \
     "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
@@ -464,7 +453,6 @@
 
     mbedtls_printf( " ok\n" );
 
-
     /*
      * 2. Setup the listening TCP socket
      */
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index 9791856..f5fcfda 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -84,17 +84,6 @@
 
 #define DEBUG_LEVEL 0
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
@@ -224,11 +213,11 @@
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
-#if defined(MBEDTLS_SSL_CACHE_C)
+#if defined(MBEDTLS_SSL_CACHE_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     mbedtls_ssl_conf_session_cache( &conf, &cache,
                                    mbedtls_ssl_cache_get,
                                    mbedtls_ssl_cache_set );
-#endif
+#endif /* MBEDTLS_SSL_CACHE_C && !MBEDTLS_SSL_NO_SESSION_CACHE */
 
     mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
     if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 5d751b6..5135ad4 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -317,14 +317,16 @@
 #define USAGE_COOKIES ""
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
+    !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
 #define USAGE_ANTI_REPLAY \
     "    anti_replay=0/1     default: (library default: enabled)\n"
 #else
 #define USAGE_ANTI_REPLAY ""
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
+    !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
 #define USAGE_BADMAC_LIMIT \
     "    badmac_limit=%%d     default: (library default: disabled)\n"
 #else
@@ -398,6 +400,36 @@
 #define USAGE_SERIALIZATION ""
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
+#define USAGE_AUTH_MODE \
+    "    auth_mode=%%s        default: (library default: none)\n" \
+    "                        options: none, optional, required\n"
+#else
+#define USAGE_AUTH_MODE ""
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+#define USAGE_ALLOW_LEGACY_RENEGO  \
+    "    allow_legacy=%%d     default: (library default: no)\n"
+#else
+#define USAGE_ALLOW_LEGACY_RENEGO ""
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
+#define USAGE_READ_TIMEOUT                              \
+    "    read_timeout=%%d     default: 0 ms (no timeout)\n"
+#else
+#define USAGE_READ_TIMEOUT ""
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
+#define USAGE_CERT_REQ_CA_LIST                              \
+    "    cert_req_ca_list=%%d default: 1 (send ca list)\n"  \
+    "                        options: 1 (send ca list), 0 (don't send)\n"
+#else
+#define USAGE_CERT_REQ_CA_LIST ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_server2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -413,17 +445,15 @@
     "                        options: 1 (non-blocking), 2 (added delays)\n" \
     "    event=%%d            default: 0 (loop)\n"                            \
     "                        options: 1 (level-triggered, implies nbio=1),\n" \
-    "    read_timeout=%%d     default: 0 ms (no timeout)\n"    \
+    USAGE_READ_TIMEOUT                                                  \
     "\n"                                                    \
     USAGE_DTLS                                              \
     USAGE_COOKIES                                           \
     USAGE_ANTI_REPLAY                                       \
     USAGE_BADMAC_LIMIT                                      \
     "\n"                                                    \
-    "    auth_mode=%%s        default: (library default: none)\n"      \
-    "                        options: none, optional, required\n" \
-    "    cert_req_ca_list=%%d default: 1 (send ca list)\n"  \
-    "                        options: 1 (send ca list), 0 (don't send)\n" \
+    USAGE_AUTH_MODE                                         \
+    USAGE_CERT_REQ_CA_LIST                                  \
     USAGE_IO                                                \
     USAGE_SSL_ASYNC                                         \
     USAGE_SNI                                               \
@@ -431,7 +461,7 @@
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
     "\n"                                                    \
-    "    allow_legacy=%%d     default: (library default: no)\n"      \
+    USAGE_ALLOW_LEGACY_RENEGO                               \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     "\n"                                                    \
@@ -462,7 +492,6 @@
     USAGE_SERIALIZATION                                     \
     " acceptable ciphersuite names:\n"
 
-
 #define ALPN_LIST_SIZE  10
 #define CURVE_LIST_SIZE 20
 
@@ -478,17 +507,6 @@
     (out_be)[(i) + 7] = (unsigned char)( ( (in_le) >> 0  ) & 0xFF );    \
 }
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
@@ -617,6 +635,7 @@
     return( ret );
 }
 
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
 /*
  * Return authmode from string, or -1 on error
  */
@@ -631,6 +650,7 @@
 
     return( -1 );
 }
+#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
 
 /*
  * Used by sni_parse and psk_parse to handle coma-separated lists
@@ -1067,6 +1087,7 @@
                             const unsigned char *input,
                             size_t input_len )
 {
+    int ret;
     ssl_async_key_context_t *config_data =
         mbedtls_ssl_conf_get_async_config_data( ssl->conf );
     unsigned slot;
@@ -1075,9 +1096,17 @@
 
     {
         char dn[100];
-        if( mbedtls_x509_dn_gets( dn, sizeof( dn ), &cert->subject ) > 0 )
+        mbedtls_x509_name *subject;
+
+        ret = mbedtls_x509_crt_get_subject( cert, &subject );
+        if( ret != 0 )
+            return( ret );
+
+        if( mbedtls_x509_dn_gets( dn, sizeof( dn ), subject ) > 0 )
             mbedtls_printf( "Async %s callback: looking for DN=%s\n",
                             op_name, dn );
+
+        mbedtls_x509_name_free( subject );
     }
 
     /* Look for a private key that matches the public key in cert.
@@ -1086,8 +1115,14 @@
      * public key. */
     for( slot = 0; slot < config_data->slots_used; slot++ )
     {
-        if( mbedtls_pk_check_pair( &cert->pk,
-                                   config_data->slots[slot].pk ) == 0 )
+        mbedtls_pk_context *pk;
+        int match;
+        ret = mbedtls_x509_crt_pk_acquire( cert, &pk );
+        if( ret != 0 )
+            return( ret );
+        match = mbedtls_pk_check_pair( pk, config_data->slots[slot].pk );
+        mbedtls_x509_crt_pk_release( cert );
+        if( match == 0 )
             break;
     }
     if( slot == config_data->slots_used )
@@ -1557,8 +1592,10 @@
             if( opt.event < 0 || opt.event > 2 )
                 goto usage;
         }
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
         else if( strcmp( p, "read_timeout" ) == 0 )
             opt.read_timeout = atoi( q );
+#endif
         else if( strcmp( p, "buffer_size" ) == 0 )
         {
             opt.buffer_size = atoi( q );
@@ -1657,6 +1694,7 @@
                 MBEDTLS_SSL_RENEGOTIATION_ENABLED :
                 MBEDTLS_SSL_RENEGOTIATION_DISABLED;
         }
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
             switch( atoi( q ) )
@@ -1673,6 +1711,7 @@
                 default: goto usage;
             }
         }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
             opt.renegotiate = atoi( q );
@@ -1785,11 +1824,13 @@
             else
                 goto usage;
         }
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
         else if( strcmp( p, "auth_mode" ) == 0 )
         {
             if( ( opt.auth_mode = get_auth_mode( q ) ) < 0 )
                 goto usage;
         }
+#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
         else if( strcmp( p, "cert_req_ca_list" ) == 0 )
         {
             opt.cert_req_ca_list = atoi( q );
@@ -1889,18 +1930,22 @@
             if( opt.cookies < -1 || opt.cookies > 1)
                 goto usage;
         }
+#if !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
         else if( strcmp( p, "anti_replay" ) == 0 )
         {
             opt.anti_replay = atoi( q );
             if( opt.anti_replay < 0 || opt.anti_replay > 1)
                 goto usage;
         }
+#endif /* !MBEDTLS_SSL_CONF_ANTI_REPLAY */
+#if !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
         else if( strcmp( p, "badmac_limit" ) == 0 )
         {
             opt.badmac_limit = atoi( q );
             if( opt.badmac_limit < 0 )
                 goto usage;
         }
+#endif /* !MBEDTLS_SSL_CONF_BADMAC_LIMIT */
         else if( strcmp( p, "hs_timeout" ) == 0 )
         {
             if( ( p = strchr( q, '-' ) ) == NULL )
@@ -2439,11 +2484,15 @@
     }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
     if( opt.auth_mode != DFL_AUTH_MODE )
         mbedtls_ssl_conf_authmode( &conf, opt.auth_mode );
+#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
 
+#if !defined(MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST)
     if( opt.cert_req_ca_list != DFL_CERT_REQ_CA_LIST )
         mbedtls_ssl_conf_cert_req_ca_list( &conf, opt.cert_req_ca_list );
+#endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
@@ -2461,7 +2510,9 @@
     };
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    !defined(MBEDTLS_SSL_CONF_CID_LEN) &&      \
+    !defined(MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID)
     if( opt.cid_enabled == 1 || opt.cid_enabled_renego == 1 )
     {
         if( opt.cid_enabled == 1        &&
@@ -2486,7 +2537,9 @@
             goto exit;
         }
     }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID &&
+          !MBEDTLS_SSL_CONF_CID_LEN &&
+          !MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     if( opt.trunc_hmac != DFL_TRUNC_HMAC )
@@ -2527,9 +2580,11 @@
     if( opt.cache_timeout != -1 )
         mbedtls_ssl_cache_set_timeout( &cache, opt.cache_timeout );
 
+#if !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
     mbedtls_ssl_conf_session_cache( &conf, &cache,
                                    mbedtls_ssl_cache_get,
                                    mbedtls_ssl_cache_set );
+#endif /* !MBEDTLS_SSL_NO_SESSION_CACHE */
 #endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -2580,12 +2635,14 @@
             ; /* Nothing to do */
         }
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
+    !defined(MBEDTLS_SSL_CONF_ANTI_REPLAY)
         if( opt.anti_replay != DFL_ANTI_REPLAY )
             mbedtls_ssl_conf_dtls_anti_replay( &conf, opt.anti_replay );
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
+    !defined(MBEDTLS_SSL_CONF_BADMAC_LIMIT)
         if( opt.badmac_limit != DFL_BADMAC_LIMIT )
             mbedtls_ssl_conf_dtls_badmac_limit( &conf, opt.badmac_limit );
 #endif
@@ -2616,8 +2673,10 @@
                                           MBEDTLS_SSL_MINOR_VERSION_3 );
     }
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     if( opt.allow_legacy != DFL_ALLOW_LEGACY )
         mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy );
+#endif
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation );
 
@@ -2891,7 +2950,9 @@
         goto exit;
     }
 
+#if !defined(MBEDTLS_SSL_CONF_READ_TIMEOUT)
     mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout );
+#endif /* MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
     if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index e31faaf..2b86566 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -258,17 +258,6 @@
          rsa, dhm, ecdsa, ecdh;
 } todo_list;
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 int main( int argc, char *argv[] )
 {
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 9d3ea7e..727054e 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -77,17 +77,6 @@
 #include "mbedtls/memory_buffer_alloc.h"
 #endif
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
 {
diff --git a/programs/util/pem2der.c b/programs/util/pem2der.c
index 0cc9d06..f184939 100644
--- a/programs/util/pem2der.c
+++ b/programs/util/pem2der.c
@@ -65,17 +65,6 @@
 }
 #else
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#define mbedtls_exit            exit
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index fd52719..3fc093e 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -100,17 +100,6 @@
     "    permissive=%%d       default: 0 (disabled)\n"  \
     "\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#define mbedtls_exit            exit
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index b2052ec..f3d9157 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -107,16 +107,6 @@
     "                          SHA384, SHA512\n"       \
     "\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 497c337..ef40447 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -154,17 +154,6 @@
     "                            object_signing_ca\n"     \
     "\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#define mbedtls_exit            exit
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
@@ -524,6 +513,8 @@
     //
     if( !opt.selfsign && strlen( opt.issuer_crt ) )
     {
+        mbedtls_x509_name *subject;
+
         /*
          * 1.0.a. Load the certificates
          */
@@ -538,8 +529,17 @@
             goto exit;
         }
 
+        ret = mbedtls_x509_crt_get_subject( &issuer_crt, &subject );
+        if( ret != 0 )
+        {
+            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_get_subject "
+                            "returned -0x%04x - %s\n\n", -ret, buf );
+            goto exit;
+        }
+
         ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
-                                 &issuer_crt.subject );
+                                    subject );
         if( ret < 0 )
         {
             mbedtls_strerror( ret, buf, 1024 );
@@ -550,6 +550,8 @@
 
         opt.issuer_name = issuer_name;
 
+        mbedtls_x509_name_free( subject );
+
         mbedtls_printf( " ok\n" );
     }
 
@@ -627,12 +629,24 @@
     //
     if( strlen( opt.issuer_crt ) )
     {
-        if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key ) != 0 )
+        mbedtls_pk_context pk;
+        ret = mbedtls_x509_crt_get_pk( &issuer_crt, &pk );
+        if( ret != 0 )
+        {
+            mbedtls_strerror( ret, buf, 1024 );
+            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_get_pk "
+                            "returned -0x%04x - %s\n\n", -ret, buf );
+            goto exit;
+        }
+
+        if( mbedtls_pk_check_pair( &pk, issuer_key ) != 0 )
         {
             mbedtls_printf( " failed\n  !  issuer_key does not match "
                             "issuer certificate\n\n" );
             goto exit;
         }
+
+        mbedtls_pk_free( &pk );
     }
 
     mbedtls_printf( " ok\n" );
diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c
index 00b742c..fc22188 100644
--- a/programs/x509/crl_app.c
+++ b/programs/x509/crl_app.c
@@ -63,17 +63,6 @@
     "    filename=%%s         default: crl.pem\n"      \
     "\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#define mbedtls_exit            exit
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c
index be42175..ed80155 100644
--- a/programs/x509/req_app.c
+++ b/programs/x509/req_app.c
@@ -63,17 +63,6 @@
     "    filename=%%s         default: cert.req\n"      \
     "\n"
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#define mbedtls_exit            exit
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
 
 /*
  * global options
diff --git a/scripts/baremetal.sh b/scripts/baremetal.sh
index be5fd04..11b84f8 100755
--- a/scripts/baremetal.sh
+++ b/scripts/baremetal.sh
@@ -155,7 +155,7 @@
     echo "Create 32-bit library-only baremetal build (ARMC6, Config: $BAREMETAL_CONFIG)"
     armc6_ver=$($ARMC6_CC --version | sed -n 's/.*ARM Compiler \([^ ]*\)$/\1/p')
 
-    CFLAGS_BAREMETAL="-Os --target=arm-arm-none-eabi -mthumb -mcpu=cortex-m0plus -xc --std=c99"
+    CFLAGS_BAREMETAL="-Oz --target=arm-arm-none-eabi -mthumb -mcpu=cortex-m0plus -xc --std=c99"
     if [ $check -ne 0 ]; then
         CFLAGS_BAREMETAL="$CFLAGS_BAREMETAL -Werror"
     fi
@@ -213,7 +213,8 @@
     : ${CLI:=./programs/ssl/ssl_client2}
     : ${CLI_PARAMS:="dtls=1 cid=1 cid_val=beef"}
     : ${SRV:=./programs/ssl/ssl_server2}
-    : ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required cid=1 cid_val=dead"}
+    : ${SRV_PARAMS:="dtls=1 cid=1 cid_val=dead"} # renegotiation=1 auth_mode=required implicit
+                                                 # compile-time hardcoding of configuration
     : ${VALGRIND:=valgrind}
     : ${VALGRIND_MASSIF_PARAMS="--time-unit=B --threshold=0.01 --detailed-freq=1"}
 
@@ -271,7 +272,8 @@
     : ${CLI:=./programs/ssl/ssl_client2}
     : ${CLI_PARAMS:="dtls=1"}
     : ${SRV:=./programs/ssl/ssl_server2}
-    : ${SRV_PARAMS:="dtls=1 renegotiation=1 auth_mode=required"}
+    : ${SRV_PARAMS:="dtls=1"} # renegotiation=1 auth_mode=required implicit
+                              # compile-time hardcoding of configuration
     : ${VALGRIND:=valgrind}
     : ${VALGRIND_CALLGRIND_PARAMS:="--separate-callers=100"}
 
diff --git a/scripts/config.pl b/scripts/config.pl
index c10a3b3..1c7c736 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -32,6 +32,8 @@
 #   MBEDTLS_REMOVE_3DES_CIPHERSUITES
 #   MBEDTLS_SSL_HW_RECORD_ACCEL
 #   MBEDTLS_SSL_PROTO_NO_DTLS
+#   MBEDTLS_SSL_NO_SESSION_CACHE
+#   MBEDTLS_SSL_NO_SESSION_RESUMPTION
 #   MBEDTLS_RSA_NO_CRT
 #   MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
 #   MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
@@ -95,6 +97,8 @@
 MBEDTLS_REMOVE_3DES_CIPHERSUITES
 MBEDTLS_SSL_HW_RECORD_ACCEL
 MBEDTLS_SSL_PROTO_NO_TLS
+MBEDTLS_SSL_NO_SESSION_CACHE
+MBEDTLS_SSL_NO_SESSION_RESUMPTION
 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
 MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
 MBEDTLS_X509_REMOVE_INFO
diff --git a/scripts/data_files/vs2010-app-template.vcxproj b/scripts/data_files/vs2010-app-template.vcxproj
index fac9812..1db7ee4 100644
--- a/scripts/data_files/vs2010-app-template.vcxproj
+++ b/scripts/data_files/vs2010-app-template.vcxproj
Binary files differ
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a8e7523..5938a5f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,3 +1,5 @@
+option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF)
+
 set(libs
     mbedtls
 )
@@ -10,6 +12,10 @@
     set(libs ${libs} ${ZLIB_LIBRARIES})
 endif(ENABLE_ZLIB_SUPPORT)
 
+if(LINK_WITH_PTHREAD)
+    set(libs ${libs} pthread)
+endif(LINK_WITH_PTHREAD)
+
 find_package(Perl)
 if(NOT PERL_FOUND)
     message(FATAL_ERROR "Cannot build test suites without Perl")
diff --git a/tests/Makefile b/tests/Makefile
index 4ef7417..0db4963 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,7 +3,7 @@
 # To compile with PKCS11: add "-lpkcs11-helper" to LDFLAGS
 
 CFLAGS	?= -O2
-WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement -Wno-unused-function -Wno-unused-value
+WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement -Wunused
 LDFLAGS ?=
 
 LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64
@@ -53,11 +53,20 @@
 LOCAL_LDFLAGS += -lz
 endif
 
+# Pthread shared library extension
+ifdef PTHREAD
+LOCAL_LDFLAGS += -lpthread
+endif
+
 # A test application is built for each suites/test_suite_*.data file.
 # Application name is same as .data file's base name and can be
 # constructed by stripping path 'suites/' and extension .data.
 APPS = $(basename $(subst suites/,,$(wildcard suites/test_suite_*.data)))
 
+ifndef PTHREAD
+APPS := $(filter-out test_suite_x509parse_pthread, $(APPS))
+endif
+
 # Construct executable name by adding OS specific suffix $(EXEXT).
 BINARIES := $(addsuffix $(EXEXT),$(APPS))
 
@@ -136,4 +145,3 @@
 		-o ./TESTS/mbedtls/$*
 
 generate-target-tests: $(EMBEDDED_TESTS)
-
diff --git a/tests/compat.sh b/tests/compat.sh
index 35983cd..0eae1ea 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -21,7 +21,7 @@
 SKIPPED=0
 SRVMEM=0
 
-# default commands, can be overriden by the environment
+# default commands, can be overridden by the environment
 : ${M_SRV:=../programs/ssl/ssl_server2}
 : ${M_CLI:=../programs/ssl/ssl_client2}
 : ${OPENSSL_CMD:=openssl} # OPENSSL would conflict with the build system
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 2f1a1b5..f626b55 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -120,7 +120,7 @@
     FORCE=0
     KEEP_GOING=0
 
-    # Default commands, can be overriden by the environment
+    # Default commands, can be overridden by the environment
     : ${OPENSSL:="openssl"}
     : ${OPENSSL_LEGACY:="$OPENSSL"}
     : ${OPENSSL_NEXT:="$OPENSSL"}
@@ -682,6 +682,21 @@
     if_build_succeeded tests/compat.sh -t RSA
 }
 
+component_test_no_resumption () {
+    msg "build: Default + MBEDTLS_SSL_NO_SESSION_RESUMPTION (ASan build)" # ~ 6 min
+    scripts/config.pl unset MBEDTLS_SSL_SESSION_TICKETS
+    scripts/config.pl set MBEDTLS_SSL_NO_SESSION_CACHE
+    scripts/config.pl set MBEDTLS_SSL_NO_SESSION_RESUMPTION
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: MBEDTLS_SSL_NO_SESSION_RESUMPTION - main suites (inc. selftests) (ASan build)" # ~ 50s
+    make test
+
+    msg "test: MBEDTLS_SSL_NO_SESSION_RESUMPTION - ssl-opt.sh (ASan build)" # ~ 6 min
+    if_build_succeeded tests/ssl-opt.sh
+}
+
 component_test_small_ssl_out_content_len () {
     msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
     scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384
@@ -728,7 +743,7 @@
     msg "build: cmake, full config, clang" # ~ 50s
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
-    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
+    CC=clang cmake -D LINK_WITH_PTHREAD=1 -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
     make
 
     msg "test: main suites (full config)" # ~ 5s
@@ -750,7 +765,7 @@
     scripts/config.pl set MBEDTLS_DEPRECATED_WARNING
     # Build with -O -Wextra to catch a maximum of issues.
     make CC=gcc CFLAGS='-O -Werror -Wall -Wextra' lib programs
-    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
+    make PTHREAD=1 CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
 
     msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s
     # No cleanup, just tweak the configuration and rebuild
@@ -759,7 +774,7 @@
     scripts/config.pl set MBEDTLS_DEPRECATED_REMOVED
     # Build with -O -Wextra to catch a maximum of issues.
     make CC=clang CFLAGS='-O -Werror -Wall -Wextra' lib programs
-    make CC=clang CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
+    make PTHREAD=1 CC=clang CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
 }
 
 
@@ -794,9 +809,21 @@
     make TEST_CPP=1
 }
 
+component_test_check_params_functionality () {
+    msg "build+test: MBEDTLS_CHECK_PARAMS functionality"
+    scripts/config.pl full # includes CHECK_PARAMS
+    # Make MBEDTLS_PARAM_FAILED call mbedtls_param_failed().
+    scripts/config.pl unset MBEDTLS_CHECK_PARAMS_ASSERT
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    # Only build and run tests. Do not build sample programs, because
+    # they don't have a mbedtls_param_failed() function.
+    make CC=gcc CFLAGS='-Werror -O1' lib test
+}
+
 component_test_check_params_without_platform () {
     msg "build+test: MBEDTLS_CHECK_PARAMS without MBEDTLS_PLATFORM_C"
     scripts/config.pl full # includes CHECK_PARAMS
+    # Keep MBEDTLS_PARAM_FAILED as assert.
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
     scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl unset MBEDTLS_PLATFORM_EXIT_ALT
@@ -807,15 +834,16 @@
     scripts/config.pl unset MBEDTLS_PLATFORM_SNPRINTF_ALT
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.pl unset MBEDTLS_PLATFORM_C
-    make CC=gcc CFLAGS='-Werror -O1' all test
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -O1' all test
 }
 
 component_test_check_params_silent () {
     msg "build+test: MBEDTLS_CHECK_PARAMS with alternative MBEDTLS_PARAM_FAILED()"
     scripts/config.pl full # includes CHECK_PARAMS
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+    # Set MBEDTLS_PARAM_FAILED to nothing.
     sed -i 's/.*\(#define MBEDTLS_PARAM_FAILED( cond )\).*/\1/' "$CONFIG_H"
-    make CC=gcc CFLAGS='-Werror -O1' all test
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -O1' all test
 }
 
 component_test_no_platform () {
@@ -837,8 +865,8 @@
     scripts/config.pl unset MBEDTLS_FS_IO
     # Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19,
     # to re-enable platform integration features otherwise disabled in C99 builds
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' test
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' test
 }
 
 component_build_no_std_function () {
@@ -847,21 +875,21 @@
     scripts/config.pl full
     scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
 }
 
 component_build_no_ssl_srv () {
     msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_SSL_SRV_C
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
 }
 
 component_build_no_ssl_cli () {
     msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_SSL_CLI_C
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
 }
 
 component_build_no_sockets () {
@@ -871,7 +899,7 @@
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc.
     scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib
 }
 
 component_test_no_max_fragment_length () {
@@ -918,6 +946,22 @@
     if_build_succeeded tests/compat.sh
 }
 
+component_test_asan_on_demand_parsing_remove_peer_cert () {
+    msg "build: default config, no peer CRT, on-demand CRT parsing (ASan build)"
+    scripts/config.pl unset MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+    scripts/config.pl set MBEDTLS_X509_ON_DEMAND_PARSING
+    scripts/config.pl set MBEDTLS_THREADING_C
+    scripts/config.pl set MBEDTLS_THREADING_PTHREAD
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan -D LINK_WITH_PTHREAD=1 .
+    make
+
+    msg "test: !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE, MBEDTLS_X509_ON_DEMAND_PARSING"
+    make test
+
+    msg "test: ssl-opt.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE, MBEDTLS_X509_ON_DEMAND_PARSING"
+    if_build_succeeded tests/ssl-opt.sh
+}
+
 component_test_no_max_fragment_length_small_ssl_out_content_len () {
     msg "build: no MFL extension, small SSL_OUT_CONTENT_LEN (ASan build)"
     scripts/config.pl unset MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
@@ -1008,7 +1052,10 @@
     # Build once with -O0, to compile out the i386 specific inline assembly
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address'
+    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    scripts/config.pl unset MBEDTLS_MEMORY_DEBUG
+    make CC=gcc PTHREAD=1 CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32'
 
     msg "test: i386, make, gcc -O0 (ASan build)"
     make test
@@ -1027,7 +1074,7 @@
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
     scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl unset MBEDTLS_MEMORY_DEBUG
-    make CC=gcc CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address'
+    make CC=gcc PTHREAD=1 CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32'
 
     msg "test: i386, make, gcc -O1 (ASan build)"
     make test
@@ -1042,7 +1089,7 @@
 component_test_mx32 () {
     msg "build: 64-bit ILP32, make, gcc" # ~ 30s
     scripts/config.pl full
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -mx32'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -mx32' LDFLAGS='-mx32'
 
     msg "test: 64-bit ILP32, make, gcc"
     make test
@@ -1137,35 +1184,13 @@
 
 component_build_arm_none_eabi_gcc () {
     msg "build: arm-none-eabi-gcc, make" # ~ 10s
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_NET_C
-    scripts/config.pl unset MBEDTLS_TIMING_C
-    scripts/config.pl unset MBEDTLS_FS_IO
-    scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
-    # following things are not in the default config
-    scripts/config.pl unset MBEDTLS_HAVEGE_C # depends on timing.c
-    scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
-    scripts/config.pl unset MBEDTLS_THREADING_C
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
-    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
+    scripts/config.pl baremetal
     make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
 }
 
 component_build_arm_none_eabi_gcc_no_udbl_division () {
     msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_NET_C
-    scripts/config.pl unset MBEDTLS_TIMING_C
-    scripts/config.pl unset MBEDTLS_FS_IO
-    scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
-    # following things are not in the default config
-    scripts/config.pl unset MBEDTLS_HAVEGE_C # depends on timing.c
-    scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
-    scripts/config.pl unset MBEDTLS_THREADING_C
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
-    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
+    scripts/config.pl baremetal
     scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
     make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
     echo "Checking that software 64-bit division is not required"
@@ -1174,18 +1199,7 @@
 
 component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
     msg "build: arm-none-eabi-gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_NET_C
-    scripts/config.pl unset MBEDTLS_TIMING_C
-    scripts/config.pl unset MBEDTLS_FS_IO
-    scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
-    # following things are not in the default config
-    scripts/config.pl unset MBEDTLS_HAVEGE_C # depends on timing.c
-    scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
-    scripts/config.pl unset MBEDTLS_THREADING_C
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
-    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
+    scripts/config.pl baremetal
     scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
     make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib
     echo "Checking that software 64-bit multiplication is not required"
@@ -1194,22 +1208,7 @@
 
 component_build_armcc () {
     msg "build: ARM Compiler 5, make"
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_NET_C
-    scripts/config.pl unset MBEDTLS_TIMING_C
-    scripts/config.pl unset MBEDTLS_FS_IO
-    scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    scripts/config.pl unset MBEDTLS_HAVE_TIME
-    scripts/config.pl unset MBEDTLS_HAVE_TIME_DATE
-    scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
-    # following things are not in the default config
-    scripts/config.pl unset MBEDTLS_DEPRECATED_WARNING
-    scripts/config.pl unset MBEDTLS_HAVEGE_C # depends on timing.c
-    scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
-    scripts/config.pl unset MBEDTLS_THREADING_C
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
-    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
-    scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT # depends on MBEDTLS_HAVE_TIME
+    scripts/config.pl baremetal
 
     make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
     make clean
diff --git a/tests/scripts/test_zeroize.gdb b/tests/scripts/test_zeroize.gdb
index 2f995d2..c929c88 100644
--- a/tests/scripts/test_zeroize.gdb
+++ b/tests/scripts/test_zeroize.gdb
@@ -17,7 +17,7 @@
 # seem to be a mechanism to reliably check whether the zeroize calls are being
 # eliminated by compiler optimizations from within the compiled program. The
 # problem is that a compiler would typically remove what it considers to be
-# "unecessary" assignments as part of redundant code elimination. To identify
+# "unnecessary" assignments as part of redundant code elimination. To identify
 # such code, the compilar will create some form dependency graph between
 # reads and writes to variables (among other situations). It will then use this
 # data structure to remove redundant code that does not have an impact on the
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 7bcba24..5f9e2ec 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -26,7 +26,7 @@
     exit 1
 fi
 
-# default values, can be overriden by the environment
+# default values, can be overridden by the environment
 : ${P_SRV:=../programs/ssl/ssl_server2}
 : ${P_CLI:=../programs/ssl/ssl_client2}
 : ${P_PXY:=../programs/test/udp_proxy}
@@ -529,6 +529,34 @@
     fi
 }
 
+check_cmdline_authmode_compat() {
+    __VAL="$( get_config_value_or_default "MBEDTLS_SSL_CONF_AUTHMODE" )"
+    if [ ! -z "$__VAL" ]; then
+        extract_cmdline_argument "auth_mode"
+        if [ "$__ARG" = "none" ] && [ "$__VAL" != "0" ]; then
+            SKIP_NEXT="YES";
+        elif [ "$__ARG" = "optional" ] && [ "$__VAL" != "1" ]; then
+            SKIP_NEXT="YES"
+        elif [ "$__ARG" = "required" ] && [ "$__VAL" != "2" ]; then
+            SKIP_NEXT="YES"
+        fi
+    fi
+}
+
+check_cmdline_legacy_renego_compat() {
+    __VAL="$( get_config_value_or_default "MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION" )"
+    if [ ! -z "$__VAL" ]; then
+        extract_cmdline_argument "allow_legacy"
+        if [ "$__ARG" = "-1" ] && [ "$__VAL" != "2" ]; then
+            SKIP_NEXT="YES";
+        elif [ "$__ARG" = "0" ] && [ "$__VAL" != "0" ]; then
+            SKIP_NEXT="YES"
+        elif [ "$__ARG" = "1" ] && [ "$__VAL" != "1" ]; then
+            SKIP_NEXT="YES"
+        fi
+    fi
+}
+
 # Go through all options that can be hardcoded at compile-time and
 # detect whether the command line configures them in a conflicting
 # way. If so, skip the test. Otherwise, remove the corresponding
@@ -544,6 +572,20 @@
                                "MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET"
     check_cmdline_param_compat "enforce_extended_master_secret" \
                                "MBEDTLS_SSL_CONF_ENFORCE_EXTENDED_MASTER_SECRET"
+
+    # DTLS anti replay protection configuration
+    check_cmdline_param_compat "anti_replay" \
+                               "MBEDTLS_SSL_CONF_ANTI_REPLAY"
+
+    # DTLS bad MAC limit
+    check_cmdline_param_compat "badmac_limit" \
+                               "MBEDTLS_SSL_CONF_BADMAC_LIMIT"
+
+    # Authentication mode
+    check_cmdline_authmode_compat
+
+    # Legacy renegotiation
+    check_cmdline_legacy_renego_compat
 }
 
 # Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
@@ -738,7 +780,7 @@
 
                 # The filtering in the following two options (-u and -U) do the following
                 #   - ignore valgrind output
-                #   - filter out everything but lines right after the pattern occurances
+                #   - filter out everything but lines right after the pattern occurrences
                 #   - keep one of each non-unique line
                 #   - count how many lines remain
                 # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
@@ -2130,6 +2172,9 @@
             -s "inapropriate fallback"
 
 ## Here the expected response is a valid ServerHello prefix, up to the random.
+## Due to the way the clienthello was generated, this currently needs the
+## server to have support for session tickets.
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 requires_openssl_with_fallback_scsv
 run_test    "Fallback SCSV: not in list" \
             "$P_SRV debug_level=2" \
@@ -2206,6 +2251,8 @@
 
 # Tests for Session Tickets
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: basic" \
             "$P_SRV debug_level=3 tickets=1" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1" \
@@ -2220,6 +2267,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: cache disabled" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1" \
@@ -2234,6 +2283,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: timeout" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0 ticket_timeout=1" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1 reco_delay=2" \
@@ -2248,6 +2299,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: session copy" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1 reco_mode=0" \
@@ -2262,6 +2315,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: openssl server" \
             "$O_SRV" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1" \
@@ -2271,6 +2326,8 @@
             -c "parse new session ticket" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: openssl client" \
             "$P_SRV debug_level=3 tickets=1" \
             "( $O_CLI -sess_out $SESSION; \
@@ -2285,6 +2342,8 @@
 
 # Tests for Session Tickets with DTLS
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: basic" \
             "$P_SRV debug_level=3 dtls=1 tickets=1" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \
@@ -2299,6 +2358,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: cache disabled" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \
@@ -2313,6 +2374,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: timeout" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0 ticket_timeout=1" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 reco_delay=2" \
@@ -2327,6 +2390,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: session copy" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 reco_mode=0" \
@@ -2341,6 +2406,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: openssl server" \
             "$O_SRV -dtls1" \
             "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \
@@ -2350,6 +2417,8 @@
             -c "parse new session ticket" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
             "( $O_CLI -dtls1 -sess_out $SESSION; \
@@ -2364,6 +2433,9 @@
 
 # Tests for Session Resume based on session-ID and cache
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: tickets enabled on client" \
             "$P_SRV debug_level=3 tickets=0" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1" \
@@ -2378,6 +2450,9 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: tickets enabled on server" \
             "$P_SRV debug_level=3 tickets=1" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1" \
@@ -2392,6 +2467,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: cache_max=0" \
             "$P_SRV debug_level=3 tickets=0 cache_max=0" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1" \
@@ -2401,6 +2478,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: cache_max=1" \
             "$P_SRV debug_level=3 tickets=0 cache_max=1" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1" \
@@ -2410,6 +2489,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: timeout > delay" \
             "$P_SRV debug_level=3 tickets=0" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1 reco_delay=0" \
@@ -2419,6 +2500,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: timeout < delay" \
             "$P_SRV debug_level=3 tickets=0 cache_timeout=1" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
@@ -2428,6 +2511,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: no timeout" \
             "$P_SRV debug_level=3 tickets=0 cache_timeout=0" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
@@ -2437,6 +2522,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: session copy" \
             "$P_SRV debug_level=3 tickets=0" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1 reco_mode=0" \
@@ -2446,6 +2533,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: openssl client" \
             "$P_SRV debug_level=3 tickets=0" \
             "( $O_CLI -sess_out $SESSION; \
@@ -2458,6 +2547,8 @@
             -S "session successfully restored from ticket" \
             -s "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache: openssl server" \
             "$O_SRV" \
             "$P_CLI debug_level=3 tickets=0 reconnect=1" \
@@ -2468,6 +2559,9 @@
 
 # Tests for Session Resume based on session-ID and cache, DTLS
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: tickets enabled on client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \
@@ -2482,6 +2576,9 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: tickets enabled on server" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
@@ -2496,6 +2593,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: cache_max=0" \
             "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
@@ -2505,6 +2604,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: cache_max=1" \
             "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=1" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
@@ -2514,6 +2615,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: timeout > delay" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=0" \
@@ -2523,6 +2626,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: timeout < delay" \
             "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=1" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
@@ -2532,6 +2637,8 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: no timeout" \
             "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
@@ -2541,6 +2648,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: session copy" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_mode=0" \
@@ -2550,6 +2659,8 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "( $O_CLI -dtls1 -sess_out $SESSION; \
@@ -2562,6 +2673,8 @@
             -S "session successfully restored from ticket" \
             -s "a session has been resumed"
 
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "Session resume using cache, DTLS: openssl server" \
             "$O_SRV -dtls1" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
@@ -3546,7 +3659,7 @@
                     key_file=data_files/dir-maxpath/09.key" \
             "$P_CLI server_name=CA09 ca_file=data_files/dir-maxpath/00.crt" \
             0 \
-            -C "X509 - A fatal error occured"
+            -C "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client default" \
@@ -3554,7 +3667,7 @@
                     key_file=data_files/dir-maxpath/10.key" \
             "$P_CLI server_name=CA10 ca_file=data_files/dir-maxpath/00.crt" \
             1 \
-            -c "X509 - A fatal error occured"
+            -c "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client optional" \
@@ -3563,7 +3676,7 @@
             "$P_CLI server_name=CA10 ca_file=data_files/dir-maxpath/00.crt \
                     auth_mode=optional" \
             1 \
-            -c "X509 - A fatal error occured"
+            -c "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client none" \
@@ -3572,7 +3685,7 @@
             "$P_CLI server_name=CA10 ca_file=data_files/dir-maxpath/00.crt \
                     auth_mode=none" \
             0 \
-            -C "X509 - A fatal error occured"
+            -C "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server default" \
@@ -3580,7 +3693,7 @@
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
             0 \
-            -S "X509 - A fatal error occured"
+            -S "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server optional" \
@@ -3588,7 +3701,7 @@
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
             1 \
-            -s "X509 - A fatal error occured"
+            -s "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server required" \
@@ -3596,7 +3709,7 @@
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
             1 \
-            -s "X509 - A fatal error occured"
+            -s "X509 - A fatal error occurred"
 
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int chain, server required" \
@@ -3604,7 +3717,7 @@
             "$P_CLI crt_file=data_files/dir-maxpath/c09.pem \
                     key_file=data_files/dir-maxpath/09.key" \
             0 \
-            -S "X509 - A fatal error occured"
+            -S "X509 - A fatal error occurred"
 
 # Tests for CA list in CertificateRequest messages
 
@@ -7669,7 +7782,7 @@
 not_with_valgrind # spurious resend due to timeout
 run_test    "DTLS proxy: duplicate every packet" \
             -p "$P_PXY duplicate=1" \
-            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2 anti_replay=1" \
             "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
             0 \
             -c "replayed record" \
@@ -7864,6 +7977,8 @@
             -S "Injecting buffered CCS message" \
             -S "Remember CCS message"
 
+# This needs session tickets; otherwise CCS is the first message in its flight
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "DTLS reordering: Buffer out-of-order CCS message on client"\
             -p "$P_PXY delay_srv=NewSessionTicket" \
             "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
@@ -8006,6 +8121,9 @@
             -c "HTTP/1.0 200 OK"
 
 client_needs_more_time 4
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "DTLS proxy: 3d, min handshake, resumption" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
@@ -8020,6 +8138,9 @@
             -c "HTTP/1.0 200 OK"
 
 client_needs_more_time 4
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_RESUMPTION
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
+requires_config_disabled MBEDTLS_SSL_NO_SESSION_CACHE
 run_test    "DTLS proxy: 3d, min handshake, resumption, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 1255ff4..a33cc03 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -207,7 +207,7 @@
 #define TEST_VALID_PARAM( TEST )                                    \
     TEST_ASSERT( ( TEST, 1 ) );
 
-#define assert(a) if( !( a ) )                                      \
+#define TEST_HELPER_ASSERT(a) if( !( a ) )                                      \
 {                                                                   \
     mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n",   \
                              __FILE__, __LINE__, #a );              \
@@ -278,7 +278,7 @@
 /*----------------------------------------------------------------------------*/
 /* Helper Functions */
 
-static void test_fail( const char *test, int line_no, const char* filename )
+void test_fail( const char *test, int line_no, const char* filename )
 {
     test_info.failed = 1;
     test_info.test = test;
@@ -369,11 +369,11 @@
 }
 #endif /* __unix__ || __APPLE__ __MACH__ */
 
-static int unhexify( unsigned char *obuf, const char *ibuf )
+int unhexify( unsigned char *obuf, const char *ibuf )
 {
     unsigned char c, c2;
     int len = strlen( ibuf ) / 2;
-    assert( strlen( ibuf ) % 2 == 0 ); /* must be even number of bytes */
+    TEST_HELPER_ASSERT( strlen( ibuf ) % 2 == 0 ); /* must be even number of bytes */
 
     while( *ibuf != 0 )
     {
@@ -385,7 +385,7 @@
         else if( c >= 'A' && c <= 'F' )
             c -= 'A' - 10;
         else
-            assert( 0 );
+            TEST_HELPER_ASSERT( 0 );
 
         c2 = *ibuf++;
         if( c2 >= '0' && c2 <= '9' )
@@ -395,7 +395,7 @@
         else if( c2 >= 'A' && c2 <= 'F' )
             c2 -= 'A' - 10;
         else
-            assert( 0 );
+            TEST_HELPER_ASSERT( 0 );
 
         *obuf++ = ( c << 4 ) | c2;
     }
@@ -403,7 +403,7 @@
     return len;
 }
 
-static void hexify( unsigned char *obuf, const unsigned char *ibuf, int len )
+void hexify( unsigned char *obuf, const unsigned char *ibuf, int len )
 {
     unsigned char l, h;
 
@@ -440,7 +440,7 @@
     size_t actual_len = ( len != 0 ) ? len : 1;
 
     p = mbedtls_calloc( 1, actual_len );
-    assert( p != NULL );
+    TEST_HELPER_ASSERT( p != NULL );
 
     memset( p, 0x00, actual_len );
 
@@ -457,7 +457,7 @@
  *
  * For convenience, dies if allocation fails.
  */
-static unsigned char *unhexify_alloc( const char *ibuf, size_t *olen )
+unsigned char *unhexify_alloc( const char *ibuf, size_t *olen )
 {
     unsigned char *obuf;
 
@@ -467,7 +467,7 @@
         return( zero_alloc( *olen ) );
 
     obuf = mbedtls_calloc( 1, *olen );
-    assert( obuf != NULL );
+    TEST_HELPER_ASSERT( obuf != NULL );
 
     (void) unhexify( obuf, ibuf );
 
@@ -508,7 +508,7 @@
  *
  * rng_state shall be NULL.
  */
-static int rnd_zero_rand( void *rng_state, unsigned char *output, size_t len )
+int rnd_zero_rand( void *rng_state, unsigned char *output, size_t len )
 {
     if( rng_state != NULL )
         rng_state  = NULL;
@@ -535,7 +535,7 @@
  *
  * After the buffer is empty it will return rand();
  */
-static int rnd_buffer_rand( void *rng_state, unsigned char *output, size_t len )
+int rnd_buffer_rand( void *rng_state, unsigned char *output, size_t len )
 {
     rnd_buf_info *info = (rnd_buf_info *) rng_state;
     size_t use_len;
@@ -581,7 +581,7 @@
  *
  * rng_state shall be a pointer to a rnd_pseudo_info structure.
  */
-static int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len )
+int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len )
 {
     rnd_pseudo_info *info = (rnd_pseudo_info *) rng_state;
     uint32_t i, *k, sum, delta=0x9E3779B9;
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index 3c43032..fe6a2bc 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -179,7 +179,7 @@
             if( p + 1 < buf + len )
             {
                 cur = p + 1;
-                assert( cnt < params_len );
+                TEST_HELPER_ASSERT( cnt < params_len );
                 params[cnt++] = cur;
             }
             *p = '\0';
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
index 56abf29..e4c3e30 100644
--- a/tests/suites/target_test.function
+++ b/tests/suites/target_test.function
@@ -13,11 +13,11 @@
  */
 #define INCR_ASSERT(p, start, len, step) do                     \
 {                                                               \
-    assert( ( p ) >= ( start ) );                               \
-    assert( sizeof( *( p ) ) == sizeof( *( start ) ) );         \
+    TEST_HELPER_ASSERT( ( p ) >= ( start ) );                               \
+    TEST_HELPER_ASSERT( sizeof( *( p ) ) == sizeof( *( start ) ) );         \
     /* <= is checked to support use inside a loop where         \
        pointer is incremented after reading data.       */      \
-    assert( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
+    TEST_HELPER_ASSERT( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
     ( p ) += ( step );                                          \
 }                                                               \
 while( 0 )
@@ -127,7 +127,7 @@
     /* Read data length */
     *data_len = receive_uint32();
     data = (uint8_t *)malloc( *data_len );
-    assert( data != NULL );
+    TEST_HELPER_ASSERT( data != NULL );
 
     greentea_getc(); // read ';' received after key i.e. *data_len
 
@@ -221,7 +221,7 @@
     hex_count = find_hex_count(count, data, data_len);
 
     params = (void **)malloc( sizeof( void *) * ( count + hex_count ) );
-    assert( params != NULL );
+    TEST_HELPER_ASSERT( params != NULL );
     cur = params;
 
     p = data;
@@ -360,7 +360,7 @@
         {
             /* Read dependency count */
             count = *p;
-            assert( count < data_len );
+            TEST_HELPER_ASSERT( count < data_len );
             INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
             ret = verify_dependencies( count, p );
             if ( ret != DEPENDENCY_SUPPORTED )
diff --git a/tests/suites/test_suite_ccm.data b/tests/suites/test_suite_ccm.data
index ac9c565..46c172b 100644
--- a/tests/suites/test_suite_ccm.data
+++ b/tests/suites/test_suite_ccm.data
@@ -41,7 +41,7 @@
 CCM lengths #6 tag length not even
 ccm_lengths:5:10:5:7:MBEDTLS_ERR_CCM_BAD_INPUT
 
-CCM lenghts #7 AD too long (2^16 - 2^8 + 1)
+CCM lengths #7 AD too long (2^16 - 2^8 + 1)
 depends_on:!MBEDTLS_CCM_ALT
 ccm_lengths:5:10:65281:8:MBEDTLS_ERR_CCM_BAD_INPUT
 
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 9a9cf5f..1a33d81 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -387,7 +387,7 @@
         mbedtls_ecdh_enable_restart( &cli );
     }
 
-    /* server writes its paramaters */
+    /* server writes its parameters */
     memset( buf, 0x00, sizeof( buf ) );
     len = 0;
 
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 0b1cfe8..5a41b9a 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -48,7 +48,7 @@
  * This might break memory checks in the future if sources need 'free-ing' then
  * as well.
  */
-static void entropy_clear_sources( mbedtls_entropy_context *ctx )
+void entropy_clear_sources( mbedtls_entropy_context *ctx )
 {
     ctx->source_count = 0;
 }
@@ -58,7 +58,7 @@
  */
 static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
-static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
+int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
 {
     if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
         return( -1 );
@@ -67,7 +67,7 @@
     return( 0 );
 }
 
-static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
+int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
 {
     if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
         return( -1 );
@@ -79,7 +79,7 @@
 /*
  * NV seed read/write helpers that fill the base seedfile
  */
-static int write_nv_seed( unsigned char *buf, size_t buf_len )
+int write_nv_seed( unsigned char *buf, size_t buf_len )
 {
     FILE *f;
 
@@ -98,7 +98,7 @@
     return( 0 );
 }
 
-static int read_nv_seed( unsigned char *buf, size_t buf_len )
+int read_nv_seed( unsigned char *buf, size_t buf_len )
 {
     FILE *f;
 
diff --git a/tests/suites/test_suite_nist_kw.function b/tests/suites/test_suite_nist_kw.function
index ae3ef80..f1acde9 100644
--- a/tests/suites/test_suite_nist_kw.function
+++ b/tests/suites/test_suite_nist_kw.function
@@ -30,7 +30,7 @@
     memset( key, 0, sizeof( key ) );
 
     /*
-     * 1. Check wrap and unwrap with two seperate contexts
+     * 1. Check wrap and unwrap with two separate contexts
      */
     mbedtls_nist_kw_init( &ctx1 );
     mbedtls_nist_kw_init( &ctx2 );
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index 5f49ad6..953b1ff 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -478,7 +478,7 @@
 RSA Import (N,-,-,D,E)
 mbedtls_rsa_import:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"":16:"":16:"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":16:"3":0:1:0:0
 
-RSA Import (N,-,-,D,E), succesive
+RSA Import (N,-,-,D,E), successive
 mbedtls_rsa_import:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"":16:"":16:"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":16:"3":1:1:0:0
 
 RSA Import (N,P,Q,-,E)
@@ -565,7 +565,7 @@
 RSA Export (N,-,-,D,E)
 mbedtls_rsa_export:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"":16:"":16:"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":16:"3":1:0
 
-RSA Export (N,-,-,D,E), succesive
+RSA Export (N,-,-,D,E), successive
 mbedtls_rsa_export:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"":16:"":16:"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":16:"3":1:1
 
 RSA Export (N,P,Q,-,E)
@@ -586,7 +586,7 @@
 RSA Export Raw (N,-,-,D,E)
 mbedtls_rsa_export_raw:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"":"":"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":"03":1:0
 
-RSA Export Raw (N,-,-,D,E), succesive
+RSA Export Raw (N,-,-,D,E), successive
 mbedtls_rsa_export_raw:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"":"":"77B1D99300D6A54E864962DA09AE10CF19A7FB888456BC2672B72AEA52B204914493D16C184AD201EC3F762E1FBD8702BA796EF953D9EA2F26300D285264F11B0C8301D0207FEB1E2C984445C899B0ACEBAA74EF014DD1D4BDDB43202C08D2FF9692D8D788478DEC829EB52AFB5AE068FBDBAC499A27FACECC391E75C936D55F07BB45EE184DAB45808E15722502F279F89B38C1CB292557E5063597F52C75D61001EDC33F4739353E33E56AD273B067C1A2760208529EA421774A5FFFCB3423B1E0051E7702A55D80CBF2141569F18F87BFF538A1DA8EDBB2693A539F68E0D62D77743F89EACF3B1723BDB25CE2F333FA63CACF0E67DF1A431893BB9B352FCB":"03":1:1
 
 RSA Export Raw (N,P,Q,-,E)
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 40fc923..cd1cee4 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.16.1"
+check_compiletime_version:"2.16.2"
 
 Check runtime library version
-check_runtime_version:"2.16.1"
+check_runtime_version:"2.16.2"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index f8d7875..6536cc9 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -935,6 +935,10 @@
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_CERTS_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 x509_selftest:
 
+X509 nested acquire
+depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509_nested_acquire:"308196308180a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092a864886f70d010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d01010b0500030200ff"
+
 X509 CRT ASN1 (Empty Certificate)
 x509parse_crt:"":"":MBEDTLS_ERR_X509_INVALID_FORMAT
 
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index c9fe63f..25b0d7f 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -4,6 +4,7 @@
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/x509_crl.h"
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/pem.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/base64.h"
@@ -142,25 +143,48 @@
     verify_print_context *ctx = (verify_print_context *) data;
     char *p = ctx->p;
     size_t n = ctx->buf + sizeof( ctx->buf ) - ctx->p;
+    mbedtls_x509_crt_frame const *frame;
+    mbedtls_x509_name *subject;
     ((void) flags);
 
-    ret = mbedtls_snprintf( p, n, "depth %d - serial ", certificate_depth );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_crt_get_subject( crt, &subject );
+    if( ret != 0 )
+        return( ret );
 
-    ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_snprintf( p, n, "depth %d - serial ", certificate_depth );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+
+    {
+        mbedtls_x509_buf serial;
+        serial.p   = frame->serial.p;
+        serial.len = frame->serial.len;
+        ret = mbedtls_x509_serial_gets( p, n, &serial );
+        MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
+    }
 
     ret = mbedtls_snprintf( p, n, " - subject " );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
-    ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    ret = mbedtls_x509_dn_gets( p, n, subject );
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ret = mbedtls_snprintf( p, n, " - flags 0x%08x\n", *flags );
-    MBEDTLS_X509_SAFE_SNPRINTF;
+    MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
 
     ctx->p = p;
 
+cleanup:
+
+    mbedtls_x509_name_free( subject );
+    mbedtls_x509_crt_frame_release( crt );
+
+    if( ret < 0 )
+        return( ret );
+
     return( 0 );
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
@@ -428,15 +452,19 @@
     mbedtls_x509_crt   crt;
     char buf[2000];
     int res = 0;
+    mbedtls_x509_name *subject = NULL, *issuer = NULL;
 
     mbedtls_x509_crt_init( &crt );
     memset( buf, 0, 2000 );
 
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_get_subject( &crt, &subject ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_get_issuer( &crt, &issuer ) == 0 );
+
     if( strcmp( entity, "subject" ) == 0 )
-        res =  mbedtls_x509_dn_gets( buf, 2000, &crt.subject );
+        res =  mbedtls_x509_dn_gets( buf, 2000, subject );
     else if( strcmp( entity, "issuer" ) == 0 )
-        res =  mbedtls_x509_dn_gets( buf, 2000, &crt.issuer );
+        res =  mbedtls_x509_dn_gets( buf, 2000, issuer );
     else
         TEST_ASSERT( "Unknown entity" == 0 );
 
@@ -446,6 +474,8 @@
     TEST_ASSERT( strcmp( buf, result_str ) == 0 );
 
 exit:
+    mbedtls_x509_name_free( issuer );
+    mbedtls_x509_name_free( subject );
     mbedtls_x509_crt_free( &crt );
 }
 /* END_CASE */
@@ -453,16 +483,18 @@
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
 void mbedtls_x509_time_is_past( char * crt_file, char * entity, int result )
 {
-    mbedtls_x509_crt   crt;
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt_frame frame;
 
     mbedtls_x509_crt_init( &crt );
 
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_get_frame( &crt, &frame ) == 0 );
 
     if( strcmp( entity, "valid_from" ) == 0 )
-        TEST_ASSERT( mbedtls_x509_time_is_past( &crt.valid_from ) == result );
+        TEST_ASSERT( mbedtls_x509_time_is_past( &frame.valid_from ) == result );
     else if( strcmp( entity, "valid_to" ) == 0 )
-        TEST_ASSERT( mbedtls_x509_time_is_past( &crt.valid_to ) == result );
+        TEST_ASSERT( mbedtls_x509_time_is_past( &frame.valid_to ) == result );
     else
         TEST_ASSERT( "Unknown entity" == 0 );
 
@@ -474,16 +506,18 @@
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
 void mbedtls_x509_time_is_future( char * crt_file, char * entity, int result )
 {
-    mbedtls_x509_crt   crt;
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt_frame frame;
 
     mbedtls_x509_crt_init( &crt );
 
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_get_frame( &crt, &frame ) == 0 );
 
     if( strcmp( entity, "valid_from" ) == 0 )
-        TEST_ASSERT( mbedtls_x509_time_is_future( &crt.valid_from ) == result );
+        TEST_ASSERT( mbedtls_x509_time_is_future( &frame.valid_from ) == result );
     else if( strcmp( entity, "valid_to" ) == 0 )
-        TEST_ASSERT( mbedtls_x509_time_is_future( &crt.valid_to ) == result );
+        TEST_ASSERT( mbedtls_x509_time_is_future( &frame.valid_to ) == result );
     else
         TEST_ASSERT( "Unknown entity" == 0 );
 
@@ -563,6 +597,99 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */
+void x509_nested_acquire( data_t * buf )
+{
+    /* This tests exercises the behavior of the library when
+     * facing nested calls to mbedtls_x509_crt_xxx_acquire().
+     * This is allowed if !MBEDTLS_X509_ALWAYS_FLUSH or
+     * MBEDTLS_THREADING_C, but forbidden otherwise. */
+
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt_init( &crt );
+    TEST_ASSERT( mbedtls_x509_crt_parse_der( &crt, buf->x, buf->len ) == 0 );
+
+    /* Nested aquire for CRT frames */
+    {
+        int ret;
+        mbedtls_x509_crt_frame const *frame1;
+        mbedtls_x509_crt_frame const *frame2;
+
+        /* Perform a (hopefully) innocent acquire-release pair first. */
+
+        TEST_ASSERT( mbedtls_x509_crt_frame_acquire( &crt, &frame1 ) == 0 );
+        TEST_ASSERT( mbedtls_x509_crt_frame_release( &crt ) == 0 );
+
+        /* Perform two nested acquire calls. */
+
+        TEST_ASSERT( mbedtls_x509_crt_frame_acquire( &crt, &frame1 ) == 0 );
+
+        ret = mbedtls_x509_crt_frame_acquire( &crt, &frame2 );
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH) &&      \
+    !defined(MBEDTLS_THREADING_C)
+        TEST_ASSERT( ret == MBEDTLS_ERR_X509_FATAL_ERROR );
+#else
+        TEST_ASSERT( ret == 0 );
+        TEST_ASSERT( mbedtls_x509_crt_frame_release( &crt ) == 0 );
+#endif
+
+        TEST_ASSERT( mbedtls_x509_crt_frame_release( &crt ) == 0 );
+
+        ret = mbedtls_x509_crt_frame_release( &crt );
+
+        /* In contexts which use resource counting, we expect an
+         * error on an attempted release() without prior acquire(). */
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH) &&      \
+    !defined(MBEDTLS_THREADING_C)
+        TEST_ASSERT( ret == 0 );
+#else
+        TEST_ASSERT( ret == MBEDTLS_ERR_X509_FATAL_ERROR );
+#endif
+    }
+
+    /* Nested aquire for PK contexts */
+    {
+        int ret;
+        mbedtls_pk_context *pk1;
+        mbedtls_pk_context *pk2;
+
+        /* Perform a (hopefully) innocent acquire-release pair first. */
+
+        TEST_ASSERT( mbedtls_x509_crt_pk_acquire( &crt, &pk1 ) == 0 );
+        TEST_ASSERT( mbedtls_x509_crt_pk_release( &crt ) == 0 );
+
+        /* Perform two nested acquire calls. */
+
+        TEST_ASSERT( mbedtls_x509_crt_pk_acquire( &crt, &pk1 ) == 0 );
+
+        ret = mbedtls_x509_crt_pk_acquire( &crt, &pk2 );
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH) &&      \
+    !defined(MBEDTLS_THREADING_C)
+        TEST_ASSERT( ret == MBEDTLS_ERR_X509_FATAL_ERROR );
+#else
+        TEST_ASSERT( ret == 0 );
+        TEST_ASSERT( mbedtls_x509_crt_pk_release( &crt ) == 0 );
+#endif
+
+        TEST_ASSERT( mbedtls_x509_crt_pk_release( &crt ) == 0 );
+
+        ret = mbedtls_x509_crt_pk_release( &crt );
+
+        /* In contexts which use resource counting, we expect an
+         * error on an attempted release() without prior acquire(). */
+#if defined(MBEDTLS_X509_ALWAYS_FLUSH) &&      \
+    !defined(MBEDTLS_THREADING_C)
+        TEST_ASSERT( ret == 0 );
+#else
+        TEST_ASSERT( ret == MBEDTLS_ERR_X509_FATAL_ERROR );
+#endif
+    }
+
+exit:
+    mbedtls_x509_crt_free( &crt );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_X509_CRL_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
 void x509parse_crl( data_t * buf, char * result_str, int result )
 {
diff --git a/tests/suites/test_suite_x509parse_pthread.data b/tests/suites/test_suite_x509parse_pthread.data
new file mode 100644
index 0000000..7940b7f
--- /dev/null
+++ b/tests/suites/test_suite_x509parse_pthread.data
@@ -0,0 +1,19 @@
+X509 CRT concurrent verification #1 (RSA cert, RSA CA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA1_C
+x509_verify_thread:"data_files/server1.crt":"data_files/test-ca.crt":0:0:25:50
+
+X509 CRT concurrent verification #2 (EC cert, RSA CA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA1_C
+x509_verify_thread:"data_files/server3.crt":"data_files/test-ca.crt":0:0:25:50
+
+X509 CRT concurrent verification #3 (RSA cert, EC CA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_thread:"data_files/server4.crt":"data_files/test-ca2.crt":0:0:25:50
+
+X509 CRT concurrent verification #4 (EC cert, EC CA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_thread:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:25:50
+
+X509 CRT concurrent verification #5 (RSA cert, RSA CA, RSASSA-PSS)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_SHA1_C
+x509_verify_thread:"data_files/server9-with-ca.crt":"data_files/test-ca.crt":0:0:25:50
diff --git a/tests/suites/test_suite_x509parse_pthread.function b/tests/suites/test_suite_x509parse_pthread.function
new file mode 100644
index 0000000..2728e96
--- /dev/null
+++ b/tests/suites/test_suite_x509parse_pthread.function
@@ -0,0 +1,125 @@
+/* BEGIN_HEADER */
+#include "mbedtls/bignum.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/x509_csr.h"
+#include "mbedtls/x509_internal.h"
+#include "mbedtls/pem.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/base64.h"
+#include "string.h"
+
+/* Profile for backward compatibility. Allows SHA-1, unlike the default
+   profile. */
+const mbedtls_x509_crt_profile compat_profile =
+{
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
+    0xFFFFFFF, /* Any PK alg    */
+    0xFFFFFFF, /* Any curve     */
+    1024,
+};
+
+typedef struct
+{
+    mbedtls_x509_crt *crt;
+    mbedtls_x509_crt *ca;
+    uint32_t expected_flags;
+    unsigned id;
+    int expected_result;
+    int iter_total;
+    int result;
+} x509_verify_thread_ctx;
+
+void* x509_verify_thread_worker( void *p )
+{
+    unsigned iter_cnt;
+    x509_verify_thread_ctx *ctx = (x509_verify_thread_ctx *) p;
+
+    for( iter_cnt=0; iter_cnt < (unsigned) ctx->iter_total; iter_cnt++ )
+    {
+        uint32_t flags;
+        int res;
+
+        res = mbedtls_x509_crt_verify_with_profile( ctx->crt, ctx->ca,
+                                                    NULL, &compat_profile,
+                                                    NULL, &flags, NULL, NULL );
+        if( res   != ctx->expected_result ||
+            flags != ctx->expected_flags )
+        {
+            ctx->result = 1;
+            pthread_exit( NULL );
+        }
+    }
+
+    ctx->result = 0;
+    pthread_exit( NULL );
+    return( NULL );
+}
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_THREADING_PTHREAD:MBEDTLS_X509_CRT_PARSE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
+void x509_verify_thread( char *crt_file, char *ca_file,
+                         int result, int flags_result,
+                         int thread_total,
+                         int iterations_per_thread )
+{
+    x509_verify_thread_ctx *thread_ctx;
+    pthread_t *threads;
+    int cur_thread;
+
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt ca;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    TEST_ASSERT( psa_crypto_init() == 0 );
+#endif
+
+    mbedtls_x509_crt_init( &crt );
+    mbedtls_x509_crt_init( &ca );
+    threads = mbedtls_calloc( thread_total, sizeof( pthread_t ) );
+    thread_ctx = mbedtls_calloc( thread_total, sizeof( x509_verify_thread_ctx ) );
+
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
+    TEST_ASSERT( threads != NULL );
+
+    /* Start all verify threads */
+    for( cur_thread = 0; cur_thread < thread_total; cur_thread++ )
+    {
+        thread_ctx[ cur_thread ].id = (unsigned) cur_thread;
+        thread_ctx[ cur_thread ].ca  = &ca;
+        thread_ctx[ cur_thread ].crt = &crt;
+        thread_ctx[ cur_thread ].expected_result = result;
+        thread_ctx[ cur_thread ].expected_flags = flags_result;
+        thread_ctx[ cur_thread ].iter_total = iterations_per_thread;
+        TEST_ASSERT( pthread_create( &threads[ cur_thread ], NULL,
+                                     &x509_verify_thread_worker,
+                                     &thread_ctx[ cur_thread ] ) == 0 );
+    }
+
+    /* Wait for all threads to complete */
+    for( cur_thread = 0; cur_thread < thread_total; cur_thread++ )
+        TEST_ASSERT( pthread_join( threads[ cur_thread ], NULL ) == 0 );
+
+    /* Check their results */
+    for( cur_thread = 0; cur_thread < thread_total; cur_thread++ )
+        TEST_ASSERT( thread_ctx[ cur_thread ].result == 0 );
+
+exit:
+    mbedtls_free( threads );
+    mbedtls_free( thread_ctx );
+    mbedtls_x509_crt_free( &crt );
+    mbedtls_x509_crt_free( &ca );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 535807e..9237165 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -2,6 +2,7 @@
 #include "mbedtls/bignum.h"
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/x509_internal.h"
 #include "mbedtls/pem.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/rsa.h"
@@ -216,7 +217,7 @@
                                    )
 {
     int ret;
-    size_t len = 0;
+    size_t len;
     mbedtls_asn1_named_data *names = NULL;
     mbedtls_x509_name parsed, *parsed_cur, *parsed_prv;
     unsigned char buf[1024], out[1024], *c;
@@ -234,10 +235,9 @@
 
     ret = mbedtls_x509_write_names( &c, buf, names );
     TEST_ASSERT( ret > 0 );
+    len = (size_t) ret;
 
-    TEST_ASSERT( mbedtls_asn1_get_tag( &c, buf + sizeof( buf ), &len,
-                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) == 0 );
-    TEST_ASSERT( mbedtls_x509_get_name( &c, buf + sizeof( buf ), &parsed ) == 0 );
+    TEST_ASSERT( mbedtls_x509_get_name( c, len, &parsed ) == 0 );
 
     ret = mbedtls_x509_dn_gets( (char *) out, sizeof( out ), &parsed );
     TEST_ASSERT( ret > 0 );
diff --git a/visualc/VS2010/aescrypt2.vcxproj b/visualc/VS2010/aescrypt2.vcxproj
index db387f9..63a124a 100644
--- a/visualc/VS2010/aescrypt2.vcxproj
+++ b/visualc/VS2010/aescrypt2.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/benchmark.vcxproj b/visualc/VS2010/benchmark.vcxproj
index 934c844..ffbd1ad 100644
--- a/visualc/VS2010/benchmark.vcxproj
+++ b/visualc/VS2010/benchmark.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/cert_app.vcxproj b/visualc/VS2010/cert_app.vcxproj
index fef0efe..6f1c46e 100644
--- a/visualc/VS2010/cert_app.vcxproj
+++ b/visualc/VS2010/cert_app.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/cert_req.vcxproj b/visualc/VS2010/cert_req.vcxproj
index 7d8694b..1e7edd0 100644
--- a/visualc/VS2010/cert_req.vcxproj
+++ b/visualc/VS2010/cert_req.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/cert_write.vcxproj b/visualc/VS2010/cert_write.vcxproj
index 8891d8a..bed8728 100644
--- a/visualc/VS2010/cert_write.vcxproj
+++ b/visualc/VS2010/cert_write.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/crl_app.vcxproj b/visualc/VS2010/crl_app.vcxproj
index c51caef..9fbd408 100644
--- a/visualc/VS2010/crl_app.vcxproj
+++ b/visualc/VS2010/crl_app.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/crypt_and_hash.vcxproj b/visualc/VS2010/crypt_and_hash.vcxproj
index 99199d9..fb7ef77 100644
--- a/visualc/VS2010/crypt_and_hash.vcxproj
+++ b/visualc/VS2010/crypt_and_hash.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/dh_client.vcxproj b/visualc/VS2010/dh_client.vcxproj
index b2fae80..a0990e1 100644
--- a/visualc/VS2010/dh_client.vcxproj
+++ b/visualc/VS2010/dh_client.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/dh_genprime.vcxproj b/visualc/VS2010/dh_genprime.vcxproj
index d9c1900..fdd6c6f 100644
--- a/visualc/VS2010/dh_genprime.vcxproj
+++ b/visualc/VS2010/dh_genprime.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/dh_server.vcxproj b/visualc/VS2010/dh_server.vcxproj
index 6f87cb8..d1a7345 100644
--- a/visualc/VS2010/dh_server.vcxproj
+++ b/visualc/VS2010/dh_server.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/dtls_client.vcxproj b/visualc/VS2010/dtls_client.vcxproj
index 60715fe..72b2d4b 100644
--- a/visualc/VS2010/dtls_client.vcxproj
+++ b/visualc/VS2010/dtls_client.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/dtls_server.vcxproj b/visualc/VS2010/dtls_server.vcxproj
index 8789d7f..b975369 100644
--- a/visualc/VS2010/dtls_server.vcxproj
+++ b/visualc/VS2010/dtls_server.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ecdh_curve25519.vcxproj b/visualc/VS2010/ecdh_curve25519.vcxproj
index 1120111..748b6d1 100644
--- a/visualc/VS2010/ecdh_curve25519.vcxproj
+++ b/visualc/VS2010/ecdh_curve25519.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ecdsa.vcxproj b/visualc/VS2010/ecdsa.vcxproj
index 3718c9f..03418d0 100644
--- a/visualc/VS2010/ecdsa.vcxproj
+++ b/visualc/VS2010/ecdsa.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/gen_entropy.vcxproj b/visualc/VS2010/gen_entropy.vcxproj
index 4c57655..89b41c0 100644
--- a/visualc/VS2010/gen_entropy.vcxproj
+++ b/visualc/VS2010/gen_entropy.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/gen_key.vcxproj b/visualc/VS2010/gen_key.vcxproj
index a07e1aa..c8ea11f 100644
--- a/visualc/VS2010/gen_key.vcxproj
+++ b/visualc/VS2010/gen_key.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/gen_random_ctr_drbg.vcxproj b/visualc/VS2010/gen_random_ctr_drbg.vcxproj
index 11740c4..64200af 100644
--- a/visualc/VS2010/gen_random_ctr_drbg.vcxproj
+++ b/visualc/VS2010/gen_random_ctr_drbg.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/gen_random_havege.vcxproj b/visualc/VS2010/gen_random_havege.vcxproj
index 01253ce..70c8138 100644
--- a/visualc/VS2010/gen_random_havege.vcxproj
+++ b/visualc/VS2010/gen_random_havege.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/generic_sum.vcxproj b/visualc/VS2010/generic_sum.vcxproj
index 0f2ecb4..21bd90f 100644
--- a/visualc/VS2010/generic_sum.vcxproj
+++ b/visualc/VS2010/generic_sum.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/hello.vcxproj b/visualc/VS2010/hello.vcxproj
index c986b07..b5f6eb0 100644
--- a/visualc/VS2010/hello.vcxproj
+++ b/visualc/VS2010/hello.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/key_app.vcxproj b/visualc/VS2010/key_app.vcxproj
index f96a0b0..0fc246a 100644
--- a/visualc/VS2010/key_app.vcxproj
+++ b/visualc/VS2010/key_app.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/key_app_writer.vcxproj b/visualc/VS2010/key_app_writer.vcxproj
index 0e4af3a..e4ef62b 100644
--- a/visualc/VS2010/key_app_writer.vcxproj
+++ b/visualc/VS2010/key_app_writer.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 73c92bd..2ec9178 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -223,6 +223,7 @@
     <ClInclude Include="..\..\include\mbedtls\x509_crl.h" />

     <ClInclude Include="..\..\include\mbedtls\x509_crt.h" />

     <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />

+    <ClInclude Include="..\..\include\mbedtls\x509_internal.h" />

     <ClInclude Include="..\..\include\mbedtls\xtea.h" />

   </ItemGroup>

   <ItemGroup>

diff --git a/visualc/VS2010/mini_client.vcxproj b/visualc/VS2010/mini_client.vcxproj
index b5567bd..3756404 100644
--- a/visualc/VS2010/mini_client.vcxproj
+++ b/visualc/VS2010/mini_client.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/mpi_demo.vcxproj b/visualc/VS2010/mpi_demo.vcxproj
index d68bc75..d770d35 100644
--- a/visualc/VS2010/mpi_demo.vcxproj
+++ b/visualc/VS2010/mpi_demo.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/pem2der.vcxproj b/visualc/VS2010/pem2der.vcxproj
index 507c79a..2f1248c 100644
--- a/visualc/VS2010/pem2der.vcxproj
+++ b/visualc/VS2010/pem2der.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/pk_decrypt.vcxproj b/visualc/VS2010/pk_decrypt.vcxproj
index 5ccaf4f..168adf3 100644
--- a/visualc/VS2010/pk_decrypt.vcxproj
+++ b/visualc/VS2010/pk_decrypt.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/pk_encrypt.vcxproj b/visualc/VS2010/pk_encrypt.vcxproj
index d5ef208..bb09f06 100644
--- a/visualc/VS2010/pk_encrypt.vcxproj
+++ b/visualc/VS2010/pk_encrypt.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/pk_sign.vcxproj b/visualc/VS2010/pk_sign.vcxproj
index d21f17a..98941f4 100644
--- a/visualc/VS2010/pk_sign.vcxproj
+++ b/visualc/VS2010/pk_sign.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/pk_verify.vcxproj b/visualc/VS2010/pk_verify.vcxproj
index 637ddd6..6d3006e 100644
--- a/visualc/VS2010/pk_verify.vcxproj
+++ b/visualc/VS2010/pk_verify.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/query_compile_time_config.vcxproj b/visualc/VS2010/query_compile_time_config.vcxproj
index 83a29f0..e147647 100644
--- a/visualc/VS2010/query_compile_time_config.vcxproj
+++ b/visualc/VS2010/query_compile_time_config.vcxproj
@@ -55,7 +55,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/req_app.vcxproj b/visualc/VS2010/req_app.vcxproj
index 3ffcea5..992efcf 100644
--- a/visualc/VS2010/req_app.vcxproj
+++ b/visualc/VS2010/req_app.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_decrypt.vcxproj b/visualc/VS2010/rsa_decrypt.vcxproj
index 9e1d0a2..ffba32a 100644
--- a/visualc/VS2010/rsa_decrypt.vcxproj
+++ b/visualc/VS2010/rsa_decrypt.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_encrypt.vcxproj b/visualc/VS2010/rsa_encrypt.vcxproj
index c3b0371..9f5f327 100644
--- a/visualc/VS2010/rsa_encrypt.vcxproj
+++ b/visualc/VS2010/rsa_encrypt.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_genkey.vcxproj b/visualc/VS2010/rsa_genkey.vcxproj
index e6b5060..824e304 100644
--- a/visualc/VS2010/rsa_genkey.vcxproj
+++ b/visualc/VS2010/rsa_genkey.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_sign.vcxproj b/visualc/VS2010/rsa_sign.vcxproj
index c1147c3..dda4756 100644
--- a/visualc/VS2010/rsa_sign.vcxproj
+++ b/visualc/VS2010/rsa_sign.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_sign_pss.vcxproj b/visualc/VS2010/rsa_sign_pss.vcxproj
index adfee6d..31da8ca 100644
--- a/visualc/VS2010/rsa_sign_pss.vcxproj
+++ b/visualc/VS2010/rsa_sign_pss.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_verify.vcxproj b/visualc/VS2010/rsa_verify.vcxproj
index bb44b4f..b78dfc3 100644
--- a/visualc/VS2010/rsa_verify.vcxproj
+++ b/visualc/VS2010/rsa_verify.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/rsa_verify_pss.vcxproj b/visualc/VS2010/rsa_verify_pss.vcxproj
index 7781aa5..220ad2d 100644
--- a/visualc/VS2010/rsa_verify_pss.vcxproj
+++ b/visualc/VS2010/rsa_verify_pss.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/selftest.vcxproj b/visualc/VS2010/selftest.vcxproj
index 12ff76d..1f5e109 100644
--- a/visualc/VS2010/selftest.vcxproj
+++ b/visualc/VS2010/selftest.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_client1.vcxproj b/visualc/VS2010/ssl_client1.vcxproj
index 4ac15822..c36a8ed 100644
--- a/visualc/VS2010/ssl_client1.vcxproj
+++ b/visualc/VS2010/ssl_client1.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_client2.vcxproj b/visualc/VS2010/ssl_client2.vcxproj
index a960fac..aa9a0c3 100644
--- a/visualc/VS2010/ssl_client2.vcxproj
+++ b/visualc/VS2010/ssl_client2.vcxproj
@@ -55,7 +55,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_fork_server.vcxproj b/visualc/VS2010/ssl_fork_server.vcxproj
index 922a995..84c917d 100644
--- a/visualc/VS2010/ssl_fork_server.vcxproj
+++ b/visualc/VS2010/ssl_fork_server.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_mail_client.vcxproj b/visualc/VS2010/ssl_mail_client.vcxproj
index a9b01d0..a89e332 100644
--- a/visualc/VS2010/ssl_mail_client.vcxproj
+++ b/visualc/VS2010/ssl_mail_client.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_server.vcxproj b/visualc/VS2010/ssl_server.vcxproj
index ae28e18..7fb841e 100644
--- a/visualc/VS2010/ssl_server.vcxproj
+++ b/visualc/VS2010/ssl_server.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/ssl_server2.vcxproj b/visualc/VS2010/ssl_server2.vcxproj
index 06a91cb..b74bd65 100644
--- a/visualc/VS2010/ssl_server2.vcxproj
+++ b/visualc/VS2010/ssl_server2.vcxproj
@@ -55,7 +55,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/strerror.vcxproj b/visualc/VS2010/strerror.vcxproj
index d7ec570..c3ec8fa 100644
--- a/visualc/VS2010/strerror.vcxproj
+++ b/visualc/VS2010/strerror.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/udp_proxy.vcxproj b/visualc/VS2010/udp_proxy.vcxproj
index 30ae55e..e75dd9a 100644
--- a/visualc/VS2010/udp_proxy.vcxproj
+++ b/visualc/VS2010/udp_proxy.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/visualc/VS2010/zeroize.vcxproj b/visualc/VS2010/zeroize.vcxproj
index 9d311c7..dff71d3 100644
--- a/visualc/VS2010/zeroize.vcxproj
+++ b/visualc/VS2010/zeroize.vcxproj
@@ -54,7 +54,6 @@
     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">