Merge pull request #3301 from Patater/inline-mbedtls_ecc_group_to_psa

psa: Define mbedtls_ecc_group_to_psa() inline
diff --git a/.travis.yml b/.travis.yml
index 0685bdb..c67c0cd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,28 +1,60 @@
 language: c
-compiler:
-- clang
-- gcc
+compiler: gcc
 sudo: false
 cache: ccache
 
-script:
-- tests/scripts/recursion.pl library/*.c
-- tests/scripts/check-generated-files.sh
-- tests/scripts/check-doxy-blocks.pl
-- tests/scripts/check-names.sh
-- tests/scripts/check-files.py
-- tests/scripts/doxygen.sh
-- cmake -D CMAKE_BUILD_TYPE:String="Check" .
-- make
-- make test
-- programs/test/selftest
-- OSSL_NO_DTLS=1 tests/compat.sh
-- tests/ssl-opt.sh -e '\(DTLS\|SCSV\).*openssl'
-- tests/scripts/test-ref-configs.pl
-- tests/scripts/curves.pl
-- tests/scripts/key-exchanges.pl
+jobs:
+  include:
+    - name: basic checks and reference configurations
+      addons:
+        apt:
+          packages:
+          - gnutls-bin
+          - doxygen
+          - graphviz
+          - gcc-arm-none-eabi
+          - libnewlib-arm-none-eabi
+      language: python # Needed to get pip for Python 3
+      python: 3.5 # version from Ubuntu 16.04
+      install:
+        - pip install pylint==2.4.4
+      script:
+        - tests/scripts/all.sh -k 'check_*'
+        - tests/scripts/all.sh -k test_default_out_of_box
+        - tests/scripts/test-ref-configs.pl
+        - tests/scripts/all.sh -k build_arm_none_eabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus
+
+    - name: full configuration
+      script:
+        - tests/scripts/all.sh -k test_full_cmake_gcc_asan
+
+    - name: check compilation guards
+      script:
+        - tests/scripts/all.sh -k 'test_depends_*' 'build_key_exchanges'
+
+    - name: macOS
+      os: osx
+      compiler: clang
+      script:
+        - tests/scripts/all.sh -k test_default_out_of_box
+
+    - name: Windows
+      os: windows
+      before_install:
+        - choco install python --version=3.5.4
+      env:
+        # Add the directory where the Choco package goes
+        - PATH=/c/Python35:/c/Python35/Scripts:$PATH
+      script:
+        - type python; python --version
+        - python scripts/generate_psa_constants.py
+        # Logs appear out of sequence on Windows. Give time to catch up.
+        - sleep 5
+        - scripts/windows_msbuild.bat v141 # Visual Studio 2017
+
 after_failure:
 - tests/scripts/travis-log-failure.sh
+
 env:
   global:
     - SEED=1
@@ -31,8 +63,7 @@
 addons:
   apt:
     packages:
-    - doxygen
-    - graphviz
+    - gnutls-bin
   coverity_scan:
     project:
       name: "ARMmbed/mbedtls"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c1ae452..7a0d95d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,7 +14,7 @@
 
 Making a Contribution
 ---------------------
-1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug.
+1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls) around a feature idea or a bug.
 1. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/ARMmbed/mbedtls/tree/development) as a basis.
 1. Write a test which shows that the bug was fixed or that the feature works as expected.
 1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :)
diff --git a/ChangeLog.d/fix-masked-hw-record-init-error.txt b/ChangeLog.d/fix-masked-hw-record-init-error.txt
new file mode 100644
index 0000000..2ef80da
--- /dev/null
+++ b/ChangeLog.d/fix-masked-hw-record-init-error.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix issue with a detected HW accelerated record error not being exposed
+     due to shadowed variable. Contributed by Sander Visser in #3310.
diff --git a/ChangeLog.d/fix-null-ptr-deref-in-mbedtls_ssl_free.txt b/ChangeLog.d/fix-null-ptr-deref-in-mbedtls_ssl_free.txt
new file mode 100644
index 0000000..9554aa0
--- /dev/null
+++ b/ChangeLog.d/fix-null-ptr-deref-in-mbedtls_ssl_free.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Avoid NULL pointer dereferencing if mbedtls_ssl_free() is called with a
+     NULL pointer argument. Contributed by Sander Visser in #3312.
\ No newline at end of file
diff --git a/ChangeLog.d/psa-lifetime-locations.txt b/ChangeLog.d/psa-lifetime-locations.txt
new file mode 100644
index 0000000..6ac02bc
--- /dev/null
+++ b/ChangeLog.d/psa-lifetime-locations.txt
@@ -0,0 +1,8 @@
+Default behavior changes
+   * In the experimental PSA secure element interface, change the encoding of
+     key lifetimes to encode a persistence level and the location. Although C
+     prototypes do not effectively change, code calling
+     psa_register_se_driver() must be modified to pass the driver's location
+     instead of the keys' lifetime. If the library is upgraded on an existing
+     device, keys created with the old lifetime value will not be readable or
+     removable through Mbed TLS after the upgrade.
diff --git a/ChangeLog.d/unified-exit-in-examples.txt b/ChangeLog.d/unified-exit-in-examples.txt
new file mode 100644
index 0000000..3ef9798
--- /dev/null
+++ b/ChangeLog.d/unified-exit-in-examples.txt
@@ -0,0 +1,4 @@
+Changes
+   * Unify the example programs termination to call mbedtls_exit() instead of
+     using a return command. This has been done to enable customization of the
+     behavior in bare metal environments.
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index 7ac1ed1..0c28579 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -119,8 +119,10 @@
  * \param[in,out] drv_context       The driver context structure.
  * \param[in,out] persistent_data   A pointer to the persistent data
  *                                  that allows writing.
- * \param lifetime                  The lifetime value for which this driver
- *                                  is registered.
+ * \param location                  The location value for which this driver
+ *                                  is registered. The driver will be invoked
+ *                                  for all keys whose lifetime is in this
+ *                                  location.
  *
  * \retval #PSA_SUCCESS
  *         The driver is operational.
@@ -132,7 +134,7 @@
  */
 typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context,
                                           void *persistent_data,
-                                          psa_key_lifetime_t lifetime);
+                                          psa_key_location_t location);
 
 #if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C)
 /* Mbed Crypto with secure element support enabled defines this type in
@@ -1341,17 +1343,19 @@
  * after psa_crypto_init().
  *
  * \note Implementations store metadata about keys including the lifetime
- *       value. Therefore, from one instantiation of the PSA Cryptography
+ *       value, which contains the driver's location indicator. Therefore,
+ *       from one instantiation of the PSA Cryptography
  *       library to the next one, if there is a key in storage with a certain
  *       lifetime value, you must always register the same driver (or an
  *       updated version that communicates with the same secure element)
- *       with the same lifetime value.
+ *       with the same location value.
  *
- * \param lifetime      The lifetime value through which this driver will
+ * \param location      The location value through which this driver will
  *                      be exposed to applications.
- *                      The values #PSA_KEY_LIFETIME_VOLATILE and
- *                      #PSA_KEY_LIFETIME_PERSISTENT are reserved and
- *                      may not be used for drivers. Implementations
+ *                      This driver will be used for all keys such that
+ *                      `location == PSA_KEY_LIFETIME_LOCATION( lifetime )`.
+ *                      The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved
+ *                      and may not be used for drivers. Implementations
  *                      may reserve other values.
  * \param[in] methods   The method table of the driver. This structure must
  *                      remain valid for as long as the cryptography
@@ -1376,7 +1380,7 @@
  * \return PSA_ERROR_NOT_PERMITTED
  */
 psa_status_t psa_register_se_driver(
-    psa_key_lifetime_t lifetime,
+    psa_key_location_t location,
     const psa_drv_se_t *methods);
 
 /**@}*/
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index d96c66e..41f1bea 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -108,18 +108,117 @@
  * The lifetime of a key indicates where it is stored and what system actions
  * may create and destroy it.
  *
- * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically
- * destroyed when the application terminates or on a power reset.
+ * Lifetime values have the following structure:
+ * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)):
+ *   persistence level. This value indicates what device management
+ *   actions can cause it to be destroyed. In particular, it indicates
+ *   whether the key is _volatile_ or _persistent_.
+ *   See ::psa_key_persistence_t for more information.
+ * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)):
+ *   location indicator. This value indicates where the key is stored
+ *   and where operations on the key are performed.
+ *   See ::psa_key_location_t for more information.
  *
- * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said
- * to be _persistent_.
- * Persistent keys are preserved if the application or the system restarts.
+ * Volatile keys are automatically destroyed when the application instance
+ * terminates or on a power reset of the device. Persistent keys are
+ * preserved until the application explicitly destroys them or until an
+ * implementation-specific device management event occurs (for example,
+ * a factory reset).
+ *
  * Persistent keys have a key identifier of type #psa_key_id_t.
+ * This identifier remains valid throughout the lifetime of the key,
+ * even if the application instance that created the key terminates.
  * The application can call psa_open_key() to open a persistent key that
  * it created previously.
+ *
+ * This specification defines two basic lifetime values:
+ * - Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are volatile.
+ *   All implementations should support this lifetime.
+ * - Keys with the lifetime #PSA_KEY_LIFETIME_PERSISTENT are persistent.
+ *   All implementations that have access to persistent storage with
+ *   appropriate security guarantees should support this lifetime.
  */
 typedef uint32_t psa_key_lifetime_t;
 
+/** Encoding of key persistence levels.
+ *
+ * What distinguishes different persistence levels is what device management
+ * events may cause keys to be destroyed. _Volatile_ keys are destroyed
+ * by a power reset. Persistent keys may be destroyed by events such as
+ * a transfer of ownership or a factory reset. What management events
+ * actually affect persistent keys at different levels is outside the
+ * scope of the PSA Cryptography specification.
+ *
+ * This specification defines the following values of persistence levels:
+ * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key.
+ *   A volatile key is automatically destroyed by the implementation when
+ *   the application instance terminates. In particular, a volatile key
+ *   is automatically destroyed on a power reset of the device.
+ * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT:
+ *   persistent key with a default lifetime.
+ *   Implementations should support this value if they support persistent
+ *   keys at all.
+ *   Applications should use this value if they have no specific needs that
+ *   are only met by implementation-specific features.
+ * - \c 2-127: persistent key with a PSA-specified lifetime.
+ *   The PSA Cryptography specification does not define the meaning of these
+ *   values, but other PSA specifications may do so.
+ * - \c 128-254: persistent key with a vendor-specified lifetime.
+ *   No PSA specification will define the meaning of these values, so
+ *   implementations may choose the meaning freely.
+ *   As a guideline, higher persistence levels should cause a key to survive
+ *   more management events than lower levels.
+ * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY:
+ *   read-only or write-once key.
+ *   A key with this persistence level cannot be destroyed.
+ *   Implementations that support such keys may either allow their creation
+ *   through the PSA Cryptography API, preferably only to applications with
+ *   the appropriate privilege, or only expose keys created through
+ *   implementation-specific means such as a factory ROM engraving process.
+ *   Note that keys that are read-only due to policy restrictions
+ *   rather than due to physical limitations should not have this
+ *   persistence levels.
+ *
+ * \note Key persistence levels are 8-bit values. Key management
+ *       interfaces operate on lifetimes (type ::psa_key_lifetime_t) which
+ *       encode the persistence as the lower 8 bits of a 32-bit value.
+ */
+typedef uint8_t psa_key_persistence_t;
+
+/** Encoding of key location indicators.
+ *
+ * If an implementation of this API can make calls to external
+ * cryptoprocessors such as secure elements, the location of a key
+ * indicates which secure element performs the operations on the key.
+ * If an implementation offers multiple physical locations for persistent
+ * storage, the location indicator reflects at which physical location
+ * the key is stored.
+ *
+ * This specification defines the following values of location indicators:
+ * - \c 0: primary local storage.
+ *   All implementations should support this value.
+ *   The primary local storage is typically the same storage area that
+ *   contains the key metadata.
+ * - \c 1: primary secure element.
+ *   Implementations should support this value if there is a secure element
+ *   attached to the operating environment.
+ *   As a guideline, secure elements may provide higher resistance against
+ *   side channel and physical attacks than the primary local storage, but may
+ *   have restrictions on supported key types, sizes, policies and operations
+ *   and may have different performance characteristics.
+ * - \c 2-0x7fffff: other locations defined by a PSA specification.
+ *   The PSA Cryptography API does not currently assign any meaning to these
+ *   locations, but future versions of this specification or other PSA
+ *   specifications may do so.
+ * - \c 0x800000-0xffffff: vendor-defined locations.
+ *   No PSA specification will assign a meaning to locations in this range.
+ *
+ * \note Key location indicators are 24-bit values. Key management
+ *       interfaces operate on lifetimes (type ::psa_key_lifetime_t) which
+ *       encode the location as the upper 24 bits of a 32-bit value.
+ */
+typedef uint32_t psa_key_location_t;
+
 /** Encoding of identifiers of persistent keys.
  *
  * - Applications may freely choose key identifiers in the range
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index baaabff..18b2d5a 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1539,12 +1539,20 @@
  * @{
  */
 
-/** A volatile key only exists as long as the handle to it is not closed.
+/** The default lifetime for volatile keys.
+ *
+ * A volatile key only exists as long as the handle to it is not closed.
  * The key material is guaranteed to be erased on a power reset.
+ *
+ * A key with this lifetime is typically stored in the RAM area of the
+ * PSA Crypto subsystem. However this is an implementation choice.
+ * If an implementation stores data about the key in a non-volatile memory,
+ * it must release all the resources associated with the key and erase the
+ * key material if the calling application terminates.
  */
 #define PSA_KEY_LIFETIME_VOLATILE               ((psa_key_lifetime_t)0x00000000)
 
-/** The default storage area for persistent keys.
+/** The default lifetime for persistent keys.
  *
  * A persistent key remains in storage until it is explicitly destroyed or
  * until the corresponding storage area is wiped. This specification does
@@ -1555,9 +1563,77 @@
  * This lifetime value is the default storage area for the calling
  * application. Implementations may offer other storage areas designated
  * by other lifetime values as implementation-specific extensions.
+ * See ::psa_key_lifetime_t for more information.
  */
 #define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t)0x00000001)
 
+/** The persistence level of volatile keys.
+ *
+ * See ::psa_key_persistence_t for more information.
+ */
+#define PSA_KEY_PERSISTENCE_VOLATILE            ((psa_key_persistence_t)0x00)
+
+/** The default persistence level for persistent keys.
+ *
+ * See ::psa_key_persistence_t for more information.
+ */
+#define PSA_KEY_PERSISTENCE_DEFAULT             ((psa_key_persistence_t)0x01)
+
+/** A persistence level indicating that a key is never destroyed.
+ *
+ * See ::psa_key_persistence_t for more information.
+ */
+#define PSA_KEY_PERSISTENCE_READ_ONLY           ((psa_key_persistence_t)0xff)
+
+#define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime)      \
+    ((psa_key_persistence_t)((lifetime) & 0x000000ff))
+
+#define PSA_KEY_LIFETIME_GET_LOCATION(lifetime)      \
+    ((psa_key_location_t)((lifetime) >> 8))
+
+/** Whether a key lifetime indicates that the key is volatile.
+ *
+ * A volatile key is automatically destroyed by the implementation when
+ * the application instance terminates. In particular, a volatile key
+ * is automatically destroyed on a power reset of the device.
+ *
+ * A key that is not volatile is persistent. Persistent keys are
+ * preserved until the application explicitly destroys them or until an
+ * implementation-specific device management event occurs (for example,
+ * a factory reset).
+ *
+ * \param lifetime      The lifetime value to query (value of type
+ *                      ::psa_key_lifetime_t).
+ *
+ * \return \c 1 if the key is volatile, otherwise \c 0.
+ */
+#define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)  \
+    (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \
+     PSA_KEY_LIFETIME_PERSISTENCE_VOLATILE)
+
+/** Construct a lifetime from a persistence level and a location.
+ *
+ * \param persistence   The persistence level
+ *                      (value of type ::psa_key_persistence_t).
+ * \param location      The location indicator
+ *                      (value of type ::psa_key_location_t).
+ *
+ * \return The constructed lifetime value.
+ */
+#define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \
+    ((location) << 8 | (persistence))
+
+/** The local storage area for persistent keys.
+ *
+ * This storage area is available on all systems that can store persistent
+ * keys without delegating the storage to a third-party cryptoprocessor.
+ *
+ * See ::psa_key_location_t for more information.
+ */
+#define PSA_KEY_LOCATION_LOCAL_STORAGE          ((psa_key_location_t)0x000000)
+
+#define PSA_KEY_LOCATION_VENDOR_FLAG            ((psa_key_location_t)0x800000)
+
 /** The minimum value for a key identifier chosen by the application.
  */
 #define PSA_KEY_ID_USER_MIN                     ((psa_app_key_id_t)0x00000001)
diff --git a/library/net_sockets.c b/library/net_sockets.c
index dbde510..5c1e665 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -54,8 +54,7 @@
 
 #define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
 
-#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
-#undef _WIN32_WINNT
+#if !defined(_WIN32_WINNT)
 /* Enables getaddrinfo() & Co */
 #define _WIN32_WINNT 0x0501
 #endif
@@ -64,6 +63,9 @@
 
 #include <winsock2.h>
 #include <windows.h>
+#if (_WIN32_WINNT < 0x0501)
+#include <wspiapi.h>
+#endif
 
 #if defined(_MSC_VER)
 #if defined(_WIN32_WCE)
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index b7fa0c5..087c768 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -64,16 +64,16 @@
     uintptr_t transient_data;
 } psa_drv_se_internal_context_t;
 
-typedef struct psa_se_drv_table_entry_s
+struct psa_se_drv_table_entry_s
 {
-    psa_key_lifetime_t lifetime;
+    psa_key_location_t location;
     const psa_drv_se_t *methods;
     union
     {
         psa_drv_se_internal_context_t internal;
         psa_drv_se_context_t context;
-    };
-} psa_se_drv_table_entry_t;
+    } u;
+};
 
 static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
 
@@ -81,15 +81,16 @@
     psa_key_lifetime_t lifetime )
 {
     size_t i;
-    /* In the driver table, lifetime=0 means an entry that isn't used.
-     * No driver has a lifetime of 0 because it's a reserved value
-     * (which designates volatile keys). Make sure we never return
-     * a driver entry for lifetime 0. */
-    if( lifetime == 0 )
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
+    /* In the driver table, location=0 means an entry that isn't used.
+     * No driver has a location of 0 because it's a reserved value
+     * (which designates transparent keys). Make sure we never return
+     * a driver entry for location 0. */
+    if( location == 0 )
         return( NULL );
     for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
     {
-        if( driver_table[i].lifetime == lifetime )
+        if( driver_table[i].location == location )
             return( &driver_table[i] );
     }
     return( NULL );
@@ -104,7 +105,7 @@
 psa_drv_se_context_t *psa_get_se_driver_context(
     psa_se_drv_table_entry_t *driver )
 {
-    return( &driver->context );
+    return( &driver->u.context );
 }
 
 int psa_get_se_driver( psa_key_lifetime_t lifetime,
@@ -115,7 +116,7 @@
     if( p_methods != NULL )
         *p_methods = ( driver ? driver->methods : NULL );
     if( p_drv_context != NULL )
-        *p_drv_context = ( driver ? &driver->context : NULL );
+        *p_drv_context = ( driver ? &driver->u.context : NULL );
     return( driver != NULL );
 }
 
@@ -129,17 +130,17 @@
     const psa_se_drv_table_entry_t *driver,
     psa_storage_uid_t *uid )
 {
-    if( driver->lifetime > PSA_MAX_SE_LIFETIME )
+    if( driver->location > PSA_MAX_SE_LOCATION )
         return( PSA_ERROR_NOT_SUPPORTED );
 
 #if SIZE_MAX > UINT32_MAX
     /* ITS file sizes are limited to 32 bits. */
-    if( driver->internal.persistent_data_size > UINT32_MAX )
+    if( driver->u.internal.persistent_data_size > UINT32_MAX )
         return( PSA_ERROR_NOT_SUPPORTED );
 #endif
 
     /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
-    *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime;
+    *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
     return( PSA_SUCCESS );
 }
 
@@ -162,8 +163,8 @@
      * persistent_data_size is in range, but compilers don't know that,
      * so cast to reassure them. */
     return( psa_its_get( uid, 0,
-                         (uint32_t) driver->internal.persistent_data_size,
-                         driver->internal.persistent_data,
+                         (uint32_t) driver->u.internal.persistent_data_size,
+                         driver->u.internal.persistent_data,
                          &length ) );
 }
 
@@ -181,17 +182,17 @@
      * persistent_data_size is in range, but compilers don't know that,
      * so cast to reassure them. */
     return( psa_its_set( uid,
-                         (uint32_t) driver->internal.persistent_data_size,
-                         driver->internal.persistent_data,
+                         (uint32_t) driver->u.internal.persistent_data_size,
+                         driver->u.internal.persistent_data,
                          0 ) );
 }
 
-psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime )
+psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location )
 {
     psa_storage_uid_t uid;
-    if( lifetime > PSA_MAX_SE_LIFETIME )
+    if( location > PSA_MAX_SE_LOCATION )
         return( PSA_ERROR_NOT_SUPPORTED );
-    uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime;
+    uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
     return( psa_its_remove( uid ) );
 }
 
@@ -202,9 +203,11 @@
     psa_key_slot_number_t *slot_number )
 {
     psa_status_t status;
+    psa_key_location_t key_location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) );
 
-    /* If the lifetime is wrong, it's a bug in the library. */
-    if( driver->lifetime != psa_get_key_lifetime( attributes ) )
+    /* If the location is wrong, it's a bug in the library. */
+    if( driver->location != key_location )
         return( PSA_ERROR_CORRUPTION_DETECTED );
 
     /* If the driver doesn't support key creation in any way, give up now. */
@@ -221,8 +224,8 @@
             driver->methods->key_management->p_validate_slot_number;
         if( p_validate_slot_number == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
-        status = p_validate_slot_number( &driver->context,
-                                         driver->internal.persistent_data,
+        status = p_validate_slot_number( &driver->u.context,
+                                         driver->u.internal.persistent_data,
                                          attributes, method,
                                          *slot_number );
     }
@@ -240,8 +243,8 @@
             driver->methods->key_management->p_allocate;
         if( p_allocate == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
-        status = p_allocate( &driver->context,
-                             driver->internal.persistent_data,
+        status = p_allocate( &driver->u.context,
+                             driver->u.internal.persistent_data,
                              attributes, method,
                              slot_number );
     }
@@ -265,8 +268,8 @@
         driver->methods->key_management->p_destroy == NULL )
         return( PSA_ERROR_NOT_PERMITTED );
     status = driver->methods->key_management->p_destroy(
-        &driver->context,
-        driver->internal.persistent_data,
+        &driver->u.context,
+        driver->u.internal.persistent_data,
         slot_number );
     storage_status = psa_save_se_persistent_data( driver );
     return( status == PSA_SUCCESS ? storage_status : status );
@@ -278,15 +281,15 @@
     for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
     {
         psa_se_drv_table_entry_t *driver = &driver_table[i];
-        if( driver->lifetime == 0 )
+        if( driver->location == 0 )
             continue; /* skipping unused entry */
         const psa_drv_se_t *methods = psa_get_se_driver_methods( driver );
         if( methods->p_init != NULL )
         {
             psa_status_t status = methods->p_init(
-                &driver->context,
-                driver->internal.persistent_data,
-                driver->lifetime );
+                &driver->u.context,
+                driver->u.internal.persistent_data,
+                driver->location );
             if( status != PSA_SUCCESS )
                 return( status );
             status = psa_save_se_persistent_data( driver );
@@ -304,7 +307,7 @@
 /****************************************************************/
 
 psa_status_t psa_register_se_driver(
-    psa_key_lifetime_t lifetime,
+    psa_key_location_t location,
     const psa_drv_se_t *methods)
 {
     size_t i;
@@ -313,42 +316,39 @@
     if( methods->hal_version != PSA_DRV_SE_HAL_VERSION )
         return( PSA_ERROR_NOT_SUPPORTED );
     /* Driver table entries are 0-initialized. 0 is not a valid driver
-     * lifetime because it means a volatile key. */
+     * location because it means a transparent key. */
 #if defined(static_assert)
-    static_assert( PSA_KEY_LIFETIME_VOLATILE == 0,
-                   "Secure element support requires 0 to mean a volatile key" );
+    static_assert( PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
+                   "Secure element support requires 0 to mean a local key" );
 #endif
-    if( lifetime == PSA_KEY_LIFETIME_VOLATILE ||
-        lifetime == PSA_KEY_LIFETIME_PERSISTENT )
-    {
+    if( location == PSA_KEY_LOCATION_LOCAL_STORAGE )
         return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-    if( lifetime > PSA_MAX_SE_LIFETIME )
+    if( location > PSA_MAX_SE_LOCATION )
         return( PSA_ERROR_NOT_SUPPORTED );
 
     for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
     {
-        if( driver_table[i].lifetime == 0 )
+        if( driver_table[i].location == 0 )
             break;
-        /* Check that lifetime isn't already in use up to the first free
+        /* Check that location isn't already in use up to the first free
          * entry. Since entries are created in order and never deleted,
          * there can't be a used entry after the first free entry. */
-        if( driver_table[i].lifetime == lifetime )
+        if( driver_table[i].location == location )
             return( PSA_ERROR_ALREADY_EXISTS );
     }
     if( i == PSA_MAX_SE_DRIVERS )
         return( PSA_ERROR_INSUFFICIENT_MEMORY );
 
-    driver_table[i].lifetime = lifetime;
+    driver_table[i].location = location;
     driver_table[i].methods = methods;
-    driver_table[i].internal.persistent_data_size =
+    driver_table[i].u.internal.persistent_data_size =
         methods->persistent_data_size;
 
     if( methods->persistent_data_size != 0 )
     {
-        driver_table[i].internal.persistent_data =
+        driver_table[i].u.internal.persistent_data =
             mbedtls_calloc( 1, methods->persistent_data_size );
-        if( driver_table[i].internal.persistent_data == NULL )
+        if( driver_table[i].u.internal.persistent_data == NULL )
         {
             status = PSA_ERROR_INSUFFICIENT_MEMORY;
             goto error;
@@ -373,8 +373,8 @@
     size_t i;
     for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
     {
-        if( driver_table[i].internal.persistent_data != NULL )
-            mbedtls_free( driver_table[i].internal.persistent_data );
+        if( driver_table[i].u.internal.persistent_data != NULL )
+            mbedtls_free( driver_table[i].u.internal.persistent_data );
     }
     memset( driver_table, 0, sizeof( driver_table ) );
 }
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 86bf7a7..c145065 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -31,31 +31,30 @@
 #include "psa/crypto.h"
 #include "psa/crypto_se_driver.h"
 
-/** The maximum lifetime value that this implementation supports
+/** The maximum location value that this implementation supports
  * for a secure element.
  *
  * This is not a characteristic that each PSA implementation has, but a
  * limitation of the current implementation due to the constraints imposed
  * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE.
  *
- * The minimum lifetime value for a secure element is 2, like on any
- * PSA implementation (0=volatile and 1=internal-storage are taken).
+ * The minimum location value for a secure element is 1, like on any
+ * PSA implementation (0 means a transparent key).
  */
-#define PSA_MAX_SE_LIFETIME 255
+#define PSA_MAX_SE_LOCATION 255
 
 /** The base of the range of ITS file identifiers for secure element
  * driver persistent data.
  *
  * We use a slice of the implemenation reserved range 0xffff0000..0xffffffff,
  * specifically the range 0xfffffe00..0xfffffeff. The length of this range
- * drives the value of #PSA_MAX_SE_LIFETIME.
- * The identifiers 0xfffffe00 and 0xfffffe01 are actually not used since
- * they correspond to #PSA_KEY_LIFETIME_VOLATILE and
- * #PSA_KEY_LIFETIME_PERSISTENT which don't have a driver.
+ * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is
+ * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE
+ * which doesn't have a driver.
  */
 #define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 )
 
-/** The maximum number of registered secure element driver lifetimes. */
+/** The maximum number of registered secure element driver locations. */
 #define PSA_MAX_SE_DRIVERS 4
 
 /** Unregister all secure element drivers.
@@ -173,10 +172,10 @@
  *
  * This is currently only used for testing.
  *
- * \param[in] lifetime  The driver lifetime whose persistent data should
- *                      be erased.
+ * \param[in] location  The location identifier for the driver whose
+ *                      persistent data is to be erased.
  */
-psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime );
+psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location );
 
 
 /** The storage representation of a key whose data is in a secure element.
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index ccfc4bd..fd0c8a7 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -863,7 +863,7 @@
     unsigned char *key2;
     unsigned char *mac_enc;
     unsigned char *mac_dec;
-    size_t mac_key_len;
+    size_t mac_key_len = 0;
     size_t iv_copy_len;
     unsigned keylen;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
@@ -1175,7 +1175,7 @@
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_init != NULL )
     {
-        int ret = 0;
+        ret = 0;
 
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) );
 
@@ -6661,14 +6661,6 @@
  */
 void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
 {
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    size_t in_buf_len = ssl->in_buf_len;
-    size_t out_buf_len = ssl->out_buf_len;
-#else
-    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
-    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
-#endif
-
     if( ssl == NULL )
         return;
 
@@ -6676,6 +6668,12 @@
 
     if( ssl->out_buf != NULL )
     {
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+        size_t out_buf_len = ssl->out_buf_len;
+#else
+        size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
+#endif
+
         mbedtls_platform_zeroize( ssl->out_buf, out_buf_len );
         mbedtls_free( ssl->out_buf );
         ssl->out_buf = NULL;
@@ -6683,6 +6681,12 @@
 
     if( ssl->in_buf != NULL )
     {
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+        size_t in_buf_len = ssl->in_buf_len;
+#else
+        size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
+#endif
+
         mbedtls_platform_zeroize( ssl->in_buf, in_buf_len );
         mbedtls_free( ssl->in_buf );
         ssl->in_buf = NULL;
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index 8edf85f..f17c641 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -76,7 +76,7 @@
     mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_SHA256_C "
                     "and/or MBEDTLS_FS_IO and/or MBEDTLS_MD_C "
                     "not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -465,6 +465,6 @@
     mbedtls_aes_free( &aes_ctx );
     mbedtls_md_free( &sha_ctx );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_SHA256_C && MBEDTLS_FS_IO */
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index e2949f2..1e03d43 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -78,14 +78,15 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_CIPHER_C and/or MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
 
 int main( int argc, char *argv[] )
 {
-    int ret = 1, i, n;
+    int ret = 1, i;
+    unsigned n;
     int exit_code = MBEDTLS_EXIT_FAILURE;
     int mode;
     size_t keylen, ilen, olen;
@@ -562,6 +563,6 @@
     mbedtls_cipher_free( &cipher_ctx );
     mbedtls_md_free( &md_ctx );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_CIPHER_C && MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/hash/generic_sum.c b/programs/hash/generic_sum.c
index 709a149..97f7a46 100644
--- a/programs/hash/generic_sum.c
+++ b/programs/hash/generic_sum.c
@@ -48,7 +48,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -203,7 +203,7 @@
         fflush( stdout ); getchar();
 #endif
 
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     /*
@@ -213,12 +213,12 @@
     if( md_info == NULL )
     {
         mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
     if( mbedtls_md_setup( &md_ctx, md_info, 0 ) )
     {
         mbedtls_fprintf( stderr, "Failed to initialize context.\n" );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     ret = 0;
@@ -237,6 +237,6 @@
 exit:
     mbedtls_md_free( &md_ctx );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/hash/hello.c b/programs/hash/hello.c
index 55a0c7e..66fd315 100644
--- a/programs/hash/hello.c
+++ b/programs/hash/hello.c
@@ -44,7 +44,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_MD5_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -58,7 +58,7 @@
     mbedtls_printf( "\n  MD5('%s') = ", str );
 
     if( ( ret = mbedtls_md5_ret( (unsigned char *) str, 13, digest ) ) != 0 )
-        return( MBEDTLS_EXIT_FAILURE );
+        mbedtls_exit( MBEDTLS_EXIT_FAILURE );
 
     for( i = 0; i < 16; i++ )
         mbedtls_printf( "%02x", digest[i] );
@@ -70,6 +70,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( MBEDTLS_EXIT_SUCCESS );
+    mbedtls_exit( MBEDTLS_EXIT_SUCCESS );
 }
 #endif /* MBEDTLS_MD5_C */
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index 86b260c..90fc4e5 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -68,7 +68,7 @@
            "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -307,7 +307,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index bf5482e..5293f89 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -45,7 +45,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_FS_IO and/or MBEDTLS_CTR_DRBG_C and/or "
            "MBEDTLS_GENPRIME not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -91,7 +91,7 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     for( i = 1; i < argc; i++ )
@@ -197,7 +197,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_FS_IO &&
           MBEDTLS_CTR_DRBG_C && MBEDTLS_GENPRIME */
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index c011774..06676c0 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -68,7 +68,7 @@
            "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -330,7 +330,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/ecdh_curve25519.c b/programs/pkey/ecdh_curve25519.c
index 9f849dd..e79dce0 100644
--- a/programs/pkey/ecdh_curve25519.c
+++ b/programs/pkey/ecdh_curve25519.c
@@ -45,7 +45,7 @@
                     "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or "
                     "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
                     "not defined\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -238,7 +238,7 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c
index 9feb160..72744e7 100644
--- a/programs/pkey/ecdsa.c
+++ b/programs/pkey/ecdsa.c
@@ -66,7 +66,7 @@
 {
     mbedtls_printf("MBEDTLS_ECDSA_C and/or MBEDTLS_SHA256_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C not defined\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 #if defined(VERBOSE)
@@ -248,7 +248,7 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
           ECPARAMS */
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 9c1a91c..c5d8ac9 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -133,7 +133,7 @@
             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
             "MBEDTLS_PEM_WRITE_C"
             "not defined.\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -446,7 +446,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
         * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c
index 345b7b8..d7387f3 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -70,7 +70,7 @@
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -311,6 +311,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 937fe90..46cb704 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -94,7 +94,7 @@
 int main( void )
 {
     mbedtls_printf( "MBEDTLS_PK_PARSE_C and/or MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO not defined.\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -436,6 +436,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/mpi_demo.c b/programs/pkey/mpi_demo.c
index ecdcd32..8163781 100644
--- a/programs/pkey/mpi_demo.c
+++ b/programs/pkey/mpi_demo.c
@@ -46,7 +46,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -112,6 +112,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/pk_decrypt.c b/programs/pkey/pk_decrypt.c
index bccfde0..494bb80 100644
--- a/programs/pkey/pk_decrypt.c
+++ b/programs/pkey/pk_decrypt.c
@@ -56,7 +56,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_PK_PARSE_C and/or "
            "MBEDTLS_FS_IO and/or MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -64,7 +64,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret = 1, c;
+    int ret = 1;
+    unsigned c;
     int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i, olen = 0;
     mbedtls_pk_context pk;
@@ -171,7 +172,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_encrypt.c b/programs/pkey/pk_encrypt.c
index 16cd3f0..673e2cb 100644
--- a/programs/pkey/pk_encrypt.c
+++ b/programs/pkey/pk_encrypt.c
@@ -57,7 +57,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_PK_PARSE_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -176,7 +176,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 4e755c0..3504bff 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -47,7 +47,7 @@
            "MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -173,7 +173,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c
index 2e08763..b1374b6 100644
--- a/programs/pkey/pk_verify.c
+++ b/programs/pkey/pk_verify.c
@@ -45,7 +45,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_MD_C and/or "
            "MBEDTLS_SHA256_C and/or MBEDTLS_PK_PARSE_C and/or "
            "MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -147,7 +147,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_SHA256_C &&
           MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_decrypt.c b/programs/pkey/rsa_decrypt.c
index 3327909..6aca217 100644
--- a/programs/pkey/rsa_decrypt.c
+++ b/programs/pkey/rsa_decrypt.c
@@ -55,7 +55,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_FS_IO and/or MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -65,7 +65,7 @@
     FILE *f;
     int ret = 1;
     int exit_code = MBEDTLS_EXIT_FAILURE;
-    int c;
+    unsigned c;
     size_t i;
     mbedtls_rsa_context rsa;
     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
@@ -207,6 +207,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_encrypt.c b/programs/pkey/rsa_encrypt.c
index 4a71c15..48f01ab 100644
--- a/programs/pkey/rsa_encrypt.c
+++ b/programs/pkey/rsa_encrypt.c
@@ -55,7 +55,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -184,7 +184,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_genkey.c b/programs/pkey/rsa_genkey.c
index f2b7b50..719923a 100644
--- a/programs/pkey/rsa_genkey.c
+++ b/programs/pkey/rsa_genkey.c
@@ -59,7 +59,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_RSA_C and/or MBEDTLS_GENPRIME and/or "
            "MBEDTLS_FS_IO and/or MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -172,7 +172,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
           MBEDTLS_GENPRIME && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
index 78ab176..38a1f3d 100644
--- a/programs/pkey/rsa_sign.c
+++ b/programs/pkey/rsa_sign.c
@@ -46,7 +46,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
             "MBEDTLS_MD_C and/or "
             "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -188,7 +188,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c
index 5019f28..938b93a 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -47,7 +47,7 @@
            "MBEDTLS_RSA_C and/or MBEDTLS_SHA256_C and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -175,7 +175,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
           MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
index b531775..8ea5d51 100644
--- a/programs/pkey/rsa_verify.c
+++ b/programs/pkey/rsa_verify.c
@@ -45,7 +45,7 @@
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
             "MBEDTLS_MD_C and/or "
             "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -59,7 +59,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret = 1, c;
+    int ret = 1;
+    unsigned c;
     int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_rsa_context rsa;
@@ -161,7 +162,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c
index de28337..5e4e98e 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -47,7 +47,7 @@
            "MBEDTLS_RSA_C and/or MBEDTLS_SHA256_C and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -151,7 +151,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/random/gen_entropy.c b/programs/random/gen_entropy.c
index c60aec9..e981b9a 100644
--- a/programs/random/gen_entropy.c
+++ b/programs/random/gen_entropy.c
@@ -47,7 +47,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -63,13 +63,13 @@
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     mbedtls_entropy_init( &entropy );
@@ -99,6 +99,6 @@
     fclose( f );
     mbedtls_entropy_free( &entropy );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_ENTROPY_C */
diff --git a/programs/random/gen_random_ctr_drbg.c b/programs/random/gen_random_ctr_drbg.c
index 59df34b..b088276 100644
--- a/programs/random/gen_random_ctr_drbg.c
+++ b/programs/random/gen_random_ctr_drbg.c
@@ -50,7 +50,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_CTR_DRBG_C and/or MBEDTLS_ENTROPY_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -69,13 +69,13 @@
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     mbedtls_entropy_init( &entropy );
@@ -132,6 +132,6 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_CTR_DRBG_C && MBEDTLS_ENTROPY_C */
diff --git a/programs/random/gen_random_havege.c b/programs/random/gen_random_havege.c
index 5ea52ae..6a65de0 100644
--- a/programs/random/gen_random_havege.c
+++ b/programs/random/gen_random_havege.c
@@ -48,7 +48,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_HAVEGE_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -65,13 +65,13 @@
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     mbedtls_havege_init( &hs );
@@ -104,6 +104,6 @@
 exit:
     mbedtls_havege_free( &hs );
     fclose( f );
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_HAVEGE_C */
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index ce1056f..a0f4a5f 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -29,6 +29,7 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
+#include <stdlib.h>
 #define mbedtls_printf     printf
 #define mbedtls_fprintf    fprintf
 #define mbedtls_exit            exit
@@ -48,7 +49,7 @@
             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
             "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
             "MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined.\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -355,7 +356,7 @@
     if( ret < 0 )
         ret = 1;
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_NET_C &&
           MBEDTLD_TIMING_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index f63741f..dd88f95 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -29,6 +29,7 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
+#include <stdlib.h>
 #define mbedtls_printf     printf
 #define mbedtls_fprintf    fprintf
 #define mbedtls_time_t     time_t
@@ -61,7 +62,7 @@
             "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
             "MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C and/or "
             "MBEDTLS_TIMING_C not defined.\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -430,7 +431,7 @@
     if( ret < 0 )
         ret = 1;
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS &&
           MBEDTLS_SSL_COOKIE_C && MBEDTLS_NET_C && MBEDTLS_ENTROPY_C &&
diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c
index b4346bb..5a153cc 100644
--- a/programs/ssl/mini_client.c
+++ b/programs/ssl/mini_client.c
@@ -60,7 +60,7 @@
     mbedtls_printf( "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_ENTROPY_C and/or "
             "MBEDTLS_NET_C and/or MBEDTLS_SSL_CLI_C and/or UNIX "
             "not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -296,6 +296,6 @@
     mbedtls_x509_crt_free( &ca );
 #endif
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index 3724c64..00fbe7f 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -51,7 +51,7 @@
            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
            "not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -312,7 +312,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 6b09a89..486b6a6 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -50,7 +50,7 @@
     mbedtls_printf("MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
            "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -377,7 +377,9 @@
 #define USAGE_SERIALIZATION ""
 #endif
 
-#define USAGE \
+/* USAGE is arbitrarily split to stay under the portable string literal
+ * length limit: 4095 bytes in C99. */
+#define USAGE1 \
     "\n usage: ssl_client2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
     "    server_name=%%s      default: localhost\n"         \
@@ -401,7 +403,8 @@
     "\n"                                                    \
     USAGE_DTLS                                              \
     USAGE_CID                                               \
-    "\n"                                                    \
+    "\n"
+#define USAGE2 \
     "    auth_mode=%%s        default: (library default: none)\n" \
     "                        options: none, optional, required\n" \
     USAGE_IO                                                \
@@ -411,7 +414,8 @@
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
     USAGE_ECRESTART                                         \
-    "\n"                                                    \
+    "\n"
+#define USAGE3 \
     "    allow_legacy=%%d     default: (library default: no)\n"   \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
@@ -434,7 +438,8 @@
     USAGE_CURVES                                            \
     USAGE_RECSPLIT                                          \
     USAGE_DHMLEN                                            \
-    "\n"                                                    \
+    "\n"
+#define USAGE4 \
     "    arc4=%%d             default: (library default: 0)\n" \
     "    allow_sha1=%%d       default: 0\n"                             \
     "    min_version=%%s      default: (library default: tls1)\n"       \
@@ -1244,7 +1249,10 @@
         if( ret == 0 )
             ret = 1;
 
-        mbedtls_printf( USAGE );
+        mbedtls_printf( USAGE1 );
+        mbedtls_printf( USAGE2 );
+        mbedtls_printf( USAGE3 );
+        mbedtls_printf( USAGE4 );
 
         list = mbedtls_ssl_list_ciphersuites();
         while( *list )
@@ -1710,7 +1718,7 @@
         }
         else if( strcmp( p, "query_config" ) == 0 )
         {
-            return query_config( q );
+            mbedtls_exit( query_config( q ) );
         }
         else if( strcmp( p, "serialize") == 0 )
         {
@@ -3417,7 +3425,7 @@
     if( ret < 0 )
         ret = 1;
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 851bc05..d36aacb 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -54,14 +54,14 @@
            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
            "MBEDTLS_TIMING_C and/or MBEDTLS_PEM_PARSE_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #elif defined(_WIN32)
 int main( void )
 {
     mbedtls_printf("_WIN32 defined. This application requires fork() and signals "
            "to work correctly.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -417,7 +417,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 3163e21..08ff025 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -56,7 +56,7 @@
            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
            "not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -853,7 +853,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C **
diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c
index 0624d33..3496ef6 100644
--- a/programs/ssl/ssl_pthread_server.c
+++ b/programs/ssl/ssl_pthread_server.c
@@ -54,7 +54,7 @@
            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
            "MBEDTLS_THREADING_C and/or MBEDTLS_THREADING_PTHREAD "
            "and/or MBEDTLS_PEM_PARSE_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -524,7 +524,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C &&
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index 9668cf9..9cba887 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -52,7 +52,7 @@
            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
            "and/or MBEDTLS_PEM_PARSE_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -397,7 +397,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index ca557ca..5dd1871 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -50,7 +50,7 @@
     mbedtls_printf("MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
            "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -463,7 +463,9 @@
 #define USAGE_SERIALIZATION ""
 #endif
 
-#define USAGE \
+/* USAGE is arbitrarily split to stay under the portable string literal
+ * length limit: 4095 bytes in C99. */
+#define USAGE1 \
     "\n usage: ssl_server2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
     "    server_addr=%%s      default: (all interfaces)\n"  \
@@ -484,7 +486,8 @@
     USAGE_COOKIES                                           \
     USAGE_ANTI_REPLAY                                       \
     USAGE_BADMAC_LIMIT                                      \
-    "\n"                                                    \
+    "\n"
+#define USAGE2 \
     "    auth_mode=%%s        default: (library default: none)\n"      \
     "                        options: none, optional, required\n" \
     "    cert_req_ca_list=%%d default: 1 (send ca list)\n"  \
@@ -496,7 +499,8 @@
     USAGE_PSK                                               \
     USAGE_CA_CALLBACK                                       \
     USAGE_ECJPAKE                                           \
-    "\n"                                                    \
+    "\n"
+#define USAGE3 \
     "    allow_legacy=%%d     default: (library default: no)\n"      \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
@@ -513,7 +517,8 @@
     USAGE_EMS                                               \
     USAGE_ETM                                               \
     USAGE_CURVES                                            \
-    "\n"                                                    \
+    "\n"
+#define USAGE4 \
     "    arc4=%%d             default: (library default: 0)\n" \
     "    allow_sha1=%%d       default: 0\n"                             \
     "    min_version=%%s      default: (library default: tls1)\n"       \
@@ -1910,7 +1915,10 @@
         if( ret == 0 )
             ret = 1;
 
-        mbedtls_printf( USAGE );
+        mbedtls_printf( USAGE1 );
+        mbedtls_printf( USAGE2 );
+        mbedtls_printf( USAGE3 );
+        mbedtls_printf( USAGE4 );
 
         list = mbedtls_ssl_list_ciphersuites();
         while( *list )
@@ -2409,7 +2417,7 @@
         }
         else if( strcmp( p, "query_config" ) == 0 )
         {
-            return query_config( q );
+            mbedtls_exit( query_config( q ) );
         }
         else if( strcmp( p, "serialize") == 0 )
         {
@@ -4376,7 +4384,7 @@
     if( ret < 0 )
         ret = 1;
 
-    return( ret );
+    mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 1575930..0c04cd8 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -38,7 +38,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_TIMING_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -101,7 +101,7 @@
 #define OPTIONS                                                         \
     "md4, md5, ripemd160, sha1, sha256, sha512,\n"                      \
     "arc4, des3, des, camellia, blowfish, chacha20,\n"                  \
-    "aes_cbc, aes_gcm, aes_ccm, aes_ctx, chachapoly,\n"                 \
+    "aes_cbc, aes_gcm, aes_ccm, aes_xts, chachapoly,\n"                 \
     "aes_cmac, des3_cmac, poly1305\n"                                   \
     "havege, ctr_drbg, hmac_drbg\n"                                     \
     "rsa, dhm, ecdsa, ecdh.\n"
@@ -1065,7 +1065,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 
 #endif /* MBEDTLS_TIMING_C */
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index bd28e9a..3fa05f3 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -500,7 +500,5 @@
     if( suites_failed > 0)
         mbedtls_exit( MBEDTLS_EXIT_FAILURE );
 
-    /* return() is here to prevent compiler warnings */
-    return( MBEDTLS_EXIT_SUCCESS );
+    mbedtls_exit( MBEDTLS_EXIT_SUCCESS );
 }
-
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index d601dcc..94bae43 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -42,6 +42,7 @@
 #define mbedtls_printf          printf
 #define mbedtls_calloc          calloc
 #define mbedtls_free            free
+#define mbedtls_exit            exit
 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
 #endif /* MBEDTLS_PLATFORM_C */
@@ -50,7 +51,7 @@
 int main( void )
 {
     mbedtls_printf( "MBEDTLS_NET_C not defined.\n" );
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -181,7 +182,7 @@
         mbedtls_printf( " option %s: illegal value: %s\n", name, value );
 
     mbedtls_printf( USAGE );
-    exit( 1 );
+    mbedtls_exit( 1 );
 }
 
 static void get_options( int argc, char *argv[] )
@@ -1019,7 +1020,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 
 #endif /* MBEDTLS_NET_C */
diff --git a/programs/test/zeroize.c b/programs/test/zeroize.c
index 29cc0ac..c670a6b 100644
--- a/programs/test/zeroize.c
+++ b/programs/test/zeroize.c
@@ -42,6 +42,7 @@
 #else
 #include <stdlib.h>
 #define mbedtls_printf     printf
+#define mbedtls_exit       exit
 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
 #endif
@@ -72,14 +73,14 @@
     {
         mbedtls_printf( "This program takes exactly 1 agument\n" );
         usage();
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     fp = fopen( argv[1], "r" );
     if( fp == NULL )
     {
         mbedtls_printf( "Could not open file '%s'\n", argv[1] );
-        return( exit_code );
+        mbedtls_exit( exit_code );
     }
 
     while( ( c = fgetc( fp ) ) != EOF && p < end - 1 )
@@ -97,5 +98,5 @@
     fclose( fp );
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
diff --git a/programs/util/pem2der.c b/programs/util/pem2der.c
index f184939..f1961a1 100644
--- a/programs/util/pem2der.c
+++ b/programs/util/pem2der.c
@@ -61,7 +61,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_BASE64_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -290,6 +290,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */
diff --git a/programs/util/strerror.c b/programs/util/strerror.c
index b0487c0..45ddd4e 100644
--- a/programs/util/strerror.c
+++ b/programs/util/strerror.c
@@ -29,7 +29,9 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
+#include <stdlib.h>
 #define mbedtls_printf     printf
+#define mbedtls_exit       exit
 #endif
 
 #if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
@@ -48,7 +50,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_ERROR_C and/or MBEDTLS_ERROR_STRERROR_DUMMY not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 int main( int argc, char *argv[] )
@@ -59,7 +61,7 @@
     if( argc != 2 )
     {
         mbedtls_printf( USAGE );
-        return( 0 );
+        mbedtls_exit( 0 );
     }
 
     val = strtol( argv[1], &end, 10 );
@@ -87,6 +89,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( val );
+    mbedtls_exit( val );
 }
 #endif /* MBEDTLS_ERROR_C */
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 7723a37..1b364dd 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -51,7 +51,7 @@
            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -497,7 +497,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index f3d9157..81e0d8c 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -46,7 +46,7 @@
             "MBEDTLS_PK_PARSE_C and/or MBEDTLS_SHA256_C and/or "
             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
             "not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -444,7 +444,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 9a7dc59..318f226 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -47,7 +47,7 @@
             "MBEDTLS_FS_IO and/or MBEDTLS_SHA256_C and/or "
             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
             "MBEDTLS_ERROR_C not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -815,7 +815,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
           MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c
index 127320a..cebc724 100644
--- a/programs/x509/crl_app.c
+++ b/programs/x509/crl_app.c
@@ -42,7 +42,7 @@
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_X509_CRL_PARSE_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -147,7 +147,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CRL_PARSE_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c
index 3bb4277..3182d30 100644
--- a/programs/x509/req_app.c
+++ b/programs/x509/req_app.c
@@ -42,7 +42,7 @@
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
            "MBEDTLS_X509_CSR_PARSE_C and/or MBEDTLS_FS_IO not defined.\n");
-    return( 0 );
+    mbedtls_exit( 0 );
 }
 #else
 
@@ -147,7 +147,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_code );
+    mbedtls_exit( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CSR_PARSE_C &&
           MBEDTLS_FS_IO */
diff --git a/scripts/config.py b/scripts/config.py
index 20521a5..7f94587 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -159,45 +159,68 @@
         return active
     return True
 
+# The goal of the full configuration is to have everything that can be tested
+# together. This includes deprecated or insecure options. It excludes:
+# * Options that require additional build dependencies or unusual hardware.
+# * Options that make testing less effective.
+# * Options that are incompatible with other options, or more generally that
+#   interact with other parts of the code in such a way that a bulk enabling
+#   is not a good way to test them.
+# * Options that remove features.
+EXCLUDE_FROM_FULL = frozenset([
+    #pylint: disable=line-too-long
+    'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY', # interacts with ENTROPY_FORCE_SHA256
+    'MBEDTLS_DEPRECATED_REMOVED', # conflicts with deprecated options
+    'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
+    'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', # influences the use of ECDH in TLS
+    'MBEDTLS_ECP_RESTARTABLE', # incompatible with USE_PSA_CRYPTO
+    'MBEDTLS_ENTROPY_FORCE_SHA256', # interacts with CTR_DRBG_128_BIT_KEY
+    'MBEDTLS_HAVE_SSE2', # hardware dependency
+    'MBEDTLS_MEMORY_BACKTRACE', # depends on MEMORY_BUFFER_ALLOC_C
+    'MBEDTLS_MEMORY_BUFFER_ALLOC_C', # makes sanitizers (e.g. ASan) less effective
+    'MBEDTLS_MEMORY_DEBUG', # depends on MEMORY_BUFFER_ALLOC_C
+    'MBEDTLS_NO_64BIT_MULTIPLICATION', # influences anything that uses bignum
+    'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES', # removes a feature
+    'MBEDTLS_NO_PLATFORM_ENTROPY', # removes a feature
+    'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum
+    'MBEDTLS_PKCS11_C', # build dependency (libpkcs11-helper)
+    'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
+    'MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER', # platform dependency (PSA SPM) (at this time)
+    'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
+    'MBEDTLS_PSA_INJECT_ENTROPY', # build dependency (hook functions)
+    'MBEDTLS_REMOVE_3DES_CIPHERSUITES', # removes a feature
+    'MBEDTLS_REMOVE_ARC4_CIPHERSUITES', # removes a feature
+    'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS
+    'MBEDTLS_SHA512_NO_SHA384', # removes a feature
+    'MBEDTLS_SSL_HW_RECORD_ACCEL', # build dependency (hook functions)
+    'MBEDTLS_TEST_NULL_ENTROPY', # removes a feature
+    'MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION', # influences the use of X.509 in TLS
+    'MBEDTLS_ZLIB_SUPPORT', # build dependency (libz)
+])
+
+def is_seamless_alt(name):
+    """Whether the xxx_ALT symbol should be included in the full configuration.
+
+    Include alternative implementations of platform functions, which are
+    configurable function pointers that default to the built-in function.
+    This way we test that the function pointers exist and build correctly
+    without changing the behavior, and tests can verify that the function
+    pointers are used by modifying those pointers.
+
+    Exclude alternative implementations of library functions since they require
+    an implementation of the relevant functions and an xxx_alt.h header.
+    """
+    if name == 'MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT':
+        # Similar to non-platform xxx_ALT, requires platform_alt.h
+        return False
+    return name.startswith('MBEDTLS_PLATFORM_')
+
 def include_in_full(name):
     """Rules for symbols in the "full" configuration."""
-    if re.search(r'PLATFORM_[A-Z0-9]+_ALT', name):
-        return True
-    if name in [
-            'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY',
-            'MBEDTLS_DEPRECATED_REMOVED',
-            'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED',
-            'MBEDTLS_ECP_RESTARTABLE',
-            'MBEDTLS_ENTROPY_FORCE_SHA256', # Variant toggle, tested separately
-            'MBEDTLS_HAVE_SSE2',
-            'MBEDTLS_MEMORY_BACKTRACE',
-            'MBEDTLS_MEMORY_BUFFER_ALLOC_C',
-            'MBEDTLS_MEMORY_DEBUG',
-            'MBEDTLS_NO_64BIT_MULTIPLICATION',
-            'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES',
-            'MBEDTLS_NO_PLATFORM_ENTROPY',
-            'MBEDTLS_NO_UDBL_DIVISION',
-            'MBEDTLS_PKCS11_C',
-            'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS',
-            'MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER',
-            'MBEDTLS_PSA_CRYPTO_SE_C',
-            'MBEDTLS_PSA_CRYPTO_SPM',
-            'MBEDTLS_PSA_INJECT_ENTROPY',
-            'MBEDTLS_REMOVE_3DES_CIPHERSUITES',
-            'MBEDTLS_REMOVE_ARC4_CIPHERSUITES',
-            'MBEDTLS_RSA_NO_CRT',
-            'MBEDTLS_SHA512_NO_SHA384',
-            'MBEDTLS_SSL_HW_RECORD_ACCEL',
-            'MBEDTLS_SSL_PROTO_SSL3',
-            'MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO',
-            'MBEDTLS_TEST_NULL_ENTROPY',
-            'MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3',
-            'MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION',
-            'MBEDTLS_ZLIB_SUPPORT',
-    ]:
+    if name in EXCLUDE_FROM_FULL:
         return False
     if name.endswith('_ALT'):
-        return False
+        return is_seamless_alt(name)
     return True
 
 def full_adapter(name, active, section):
@@ -206,25 +229,33 @@
         return active
     return include_in_full(name)
 
+# The baremetal configuration excludes options that require a library or
+# operating system feature that is typically not present on bare metal
+# systems. Features that are excluded from "full" won't be in "baremetal"
+# either (unless explicitly turned on in baremetal_adapter) so they don't
+# need to be repeated here.
+EXCLUDE_FROM_BAREMETAL = frozenset([
+    #pylint: disable=line-too-long
+    'MBEDTLS_ENTROPY_NV_SEED', # requires a filesystem and FS_IO or alternate NV seed hooks
+    'MBEDTLS_FS_IO', # requires a filesystem
+    'MBEDTLS_HAVEGE_C', # requires a clock
+    'MBEDTLS_HAVE_TIME', # requires a clock
+    'MBEDTLS_HAVE_TIME_DATE', # requires a clock
+    'MBEDTLS_NET_C', # requires POSIX-like networking
+    'MBEDTLS_PLATFORM_FPRINTF_ALT', # requires FILE* from stdio.h
+    'MBEDTLS_PLATFORM_NV_SEED_ALT', # requires a filesystem and ENTROPY_NV_SEED
+    'MBEDTLS_PLATFORM_TIME_ALT', # requires a clock and HAVE_TIME
+    'MBEDTLS_PSA_CRYPTO_SE_C', # requires a filesystem and PSA_CRYPTO_STORAGE_C
+    'MBEDTLS_PSA_CRYPTO_STORAGE_C', # requires a filesystem
+    'MBEDTLS_PSA_ITS_FILE_C', # requires a filesystem
+    'MBEDTLS_THREADING_C', # requires a threading interface
+    'MBEDTLS_THREADING_PTHREAD', # requires pthread
+    'MBEDTLS_TIMING_C', # requires a clock
+])
+
 def keep_in_baremetal(name):
     """Rules for symbols in the "baremetal" configuration."""
-    if name in [
-            'MBEDTLS_DEPRECATED_WARNING',
-            'MBEDTLS_ENTROPY_NV_SEED',
-            'MBEDTLS_FS_IO',
-            'MBEDTLS_HAVEGE_C',
-            'MBEDTLS_HAVE_TIME',
-            'MBEDTLS_HAVE_TIME_DATE',
-            'MBEDTLS_NET_C',
-            'MBEDTLS_PLATFORM_FPRINTF_ALT',
-            'MBEDTLS_PLATFORM_TIME_ALT',
-            'MBEDTLS_PSA_CRYPTO_SE_C',
-            'MBEDTLS_PSA_CRYPTO_STORAGE_C',
-            'MBEDTLS_PSA_ITS_FILE_C',
-            'MBEDTLS_THREADING_C',
-            'MBEDTLS_THREADING_PTHREAD',
-            'MBEDTLS_TIMING_C',
-    ]:
+    if name in EXCLUDE_FROM_BAREMETAL:
         return False
     return True
 
@@ -233,6 +264,7 @@
     if not is_full_section(section):
         return active
     if name == 'MBEDTLS_NO_PLATFORM_ENTROPY':
+        # No OS-provided entropy source
         return True
     return include_in_full(name) and keep_in_baremetal(name)
 
@@ -243,10 +275,10 @@
        name.startswith('MBEDTLS_KEY_EXCHANGE_'):
         return False
     if name in [
-            'MBEDTLS_CERTS_C',
-            'MBEDTLS_DEBUG_C',
-            'MBEDTLS_NET_C',
-            'MBEDTLS_PKCS11_C',
+            'MBEDTLS_CERTS_C', # part of libmbedx509
+            'MBEDTLS_DEBUG_C', # part of libmbedtls
+            'MBEDTLS_NET_C', # part of libmbedtls
+            'MBEDTLS_PKCS11_C', # part of libmbedx509
     ]:
         return False
     return True
@@ -265,6 +297,28 @@
         return adapter(name, active, section)
     return continuation
 
+DEPRECATED = frozenset([
+    'MBEDTLS_SSL_PROTO_SSL3',
+    'MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO',
+])
+
+def no_deprecated_adapter(adapter):
+    """Modify an adapter to disable deprecated symbols.
+
+    ``no_deprecated_adapter(adapter)(name, active, section)`` is like
+    ``adapter(name, active, section)``, but unsets all deprecated symbols
+    and sets ``MBEDTLS_DEPRECATED_REMOVED``.
+    """
+    def continuation(name, active, section):
+        if name == 'MBEDTLS_DEPRECATED_REMOVED':
+            return True
+        if name in DEPRECATED:
+            return False
+        if adapter is None:
+            return active
+        return adapter(name, active, section)
+    return continuation
+
 class ConfigFile(Config):
     """Representation of the Mbed TLS configuration read for a file.
 
@@ -430,6 +484,10 @@
                     Exclude alternative implementations and platform support
                     options, as well as some options that are awkward to test.
                     """)
+        add_adapter('full_no_deprecated', no_deprecated_adapter(full_adapter),
+                    """Uncomment most non-deprecated features.
+                    Like "full", but without deprecated features.
+                    """)
         add_adapter('realfull', realfull_adapter,
                     """Uncomment all boolean #defines.
                     Suitable for generating documentation, but not for building.""")
diff --git a/scripts/windows_msbuild.bat b/scripts/windows_msbuild.bat
new file mode 100644
index 0000000..e419931
--- /dev/null
+++ b/scripts/windows_msbuild.bat
@@ -0,0 +1,20 @@
+@rem Build and test Mbed TLS with Visual Studio using msbuild.

+@rem Usage: windows_msbuild [RETARGET]

+@rem   RETARGET: version of Visual Studio to emulate

+@rem             https://docs.microsoft.com/en-us/cpp/build/how-to-modify-the-target-framework-and-platform-toolset

+

+@rem These parameters are hard-coded for now.

+set "arch=x64" & @rem "x86" or "x64"

+set "cfg=Release" & @rem "Debug" or "Release"

+set "vcvarsall=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"

+

+if not "%~1"=="" set "retarget=,PlatformToolset=%1"

+

+@rem If the %USERPROFILE%\Source directory exists, then running

+@rem vcvarsall.bat will silently change the directory to that directory.

+@rem Setting the VSCMD_START_DIR environment variable causes it to change

+@rem to that directory instead.

+set "VSCMD_START_DIR=%~dp0\..\visualc\VS2010"

+

+"%vcvarsall%" x64 && ^

+msbuild /t:Rebuild /p:Configuration=%cfg%%retarget% /m mbedTLS.sln

diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 5b70caa..5ea1c35 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -138,6 +138,7 @@
     : ${OUT_OF_SOURCE_DIR:=./mbedtls_out_of_source_build}
     : ${ARMC5_BIN_DIR:=/usr/bin}
     : ${ARMC6_BIN_DIR:=/usr/bin}
+    : ${ARM_NONE_EABI_GCC_PREFIX:=arm-none-eabi-}
 
     # if MAKEFLAGS is not set add the -j option to speed up invocations of make
     if [ -z "${MAKEFLAGS+set}" ]; then
@@ -203,6 +204,9 @@
   -k|--keep-going       Run all tests and report errors at the end.
   -m|--memory           Additional optional memory tests.
      --append-outcome   Append to the outcome file (if used).
+     --arm-none-eabi-gcc-prefix=<string>
+                        Prefix for a cross-compiler for arm-none-eabi
+                        (default: "${ARM_NONE_EABI_GCC_PREFIX}")
      --armcc            Run ARM Compiler builds (on by default).
      --except           Exclude the COMPONENTs listed on the command line,
                         instead of running only those.
@@ -295,9 +299,13 @@
 {
     FLAGS="$1"
 
-    msg "build: ARM Compiler 6 ($FLAGS), make"
+    msg "build: ARM Compiler 6 ($FLAGS)"
     ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \
                     WARNING_CFLAGS='-xc -std=c99' make lib
+
+    msg "size: ARM Compiler 6 ($FLAGS)"
+    "$ARMC6_FROMELF" -z library/*.o
+
     make clean
 }
 
@@ -335,6 +343,7 @@
     while [ $# -gt 0 ]; do
         case "$1" in
             --append-outcome) append_outcome=1;;
+            --arm-none-eabi-gcc-prefix) shift; ARM_NONE_EABI_GCC_PREFIX="$1";;
             --armcc) no_armcc=;;
             --armc5-bin-dir) shift; ARMC5_BIN_DIR="$1";;
             --armc6-bin-dir) shift; ARMC6_BIN_DIR="$1";;
@@ -547,7 +556,7 @@
     esac
 
     case " $RUN_COMPONENTS " in
-        *_arm_none_eabi_gcc[_\ ]*) check_tools "arm-none-eabi-gcc";;
+        *_arm_none_eabi_gcc[_\ ]*) check_tools "${ARM_NONE_EABI_GCC_PREFIX}gcc";;
     esac
 
     case " $RUN_COMPONENTS " in
@@ -562,9 +571,12 @@
         *_armcc*)
             ARMC5_CC="$ARMC5_BIN_DIR/armcc"
             ARMC5_AR="$ARMC5_BIN_DIR/armar"
+            ARMC5_FROMELF="$ARMC5_BIN_DIR/fromelf"
             ARMC6_CC="$ARMC6_BIN_DIR/armclang"
             ARMC6_AR="$ARMC6_BIN_DIR/armar"
-            check_tools "$ARMC5_CC" "$ARMC5_AR" "$ARMC6_CC" "$ARMC6_AR";;
+            ARMC6_FROMELF="$ARMC6_BIN_DIR/fromelf"
+            check_tools "$ARMC5_CC" "$ARMC5_AR" "$ARMC5_FROMELF" \
+                        "$ARMC6_CC" "$ARMC6_AR" "$ARMC6_FROMELF";;
     esac
 
     msg "info: output_env.sh"
@@ -645,7 +657,7 @@
     make test
 
     msg "selftest: make, default config (out-of-box)" # ~10s
-    programs/test/selftest
+    if_build_succeeded programs/test/selftest
 
     export MBEDTLS_TEST_OUTCOME_FILE="$SAVE_MBEDTLS_TEST_OUTCOME_FILE"
     unset SAVE_MBEDTLS_TEST_OUTCOME_FILE
@@ -659,6 +671,9 @@
     msg "test: main suites (inc. selftests) (ASan build)" # ~ 50s
     make test
 
+    msg "test: selftest (ASan build)" # ~ 10s
+    if_build_succeeded programs/test/selftest
+
     msg "test: ssl-opt.sh (ASan build)" # ~ 1 min
     if_build_succeeded tests/ssl-opt.sh
 
@@ -678,6 +693,9 @@
     msg "test: main suites (inc. selftests) (full config, ASan build)"
     make test
 
+    msg "test: selftest (ASan build)" # ~ 10s
+    if_build_succeeded programs/test/selftest
+
     msg "test: ssl-opt.sh (full config, ASan build)"
     if_build_succeeded tests/ssl-opt.sh
 
@@ -909,26 +927,58 @@
     if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
-component_build_deprecated () {
-    msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
+component_test_default_no_deprecated () {
+    # Test that removing the deprecated features from the default
+    # configuration leaves something consistent.
+    msg "build: make, default + MBEDTLS_DEPRECATED_REMOVED" # ~ 30s
+    scripts/config.py set MBEDTLS_DEPRECATED_REMOVED
+    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra'
+
+    msg "test: make, default + MBEDTLS_DEPRECATED_REMOVED" # ~ 5s
+    make test
+}
+
+component_test_full_no_deprecated () {
+    msg "build: make, full_no_deprecated config" # ~ 30s
+    scripts/config.py full_no_deprecated
+    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra'
+
+    msg "test: make, full_no_deprecated config" # ~ 5s
+    make test
+}
+
+component_test_full_no_deprecated_deprecated_warning () {
+    # Test that there is nothing deprecated in "full_no_deprecated".
+    # A deprecated feature would trigger a warning (made fatal) from
+    # MBEDTLS_DEPRECATED_WARNING.
+    msg "build: make, full_no_deprecated config, MBEDTLS_DEPRECATED_WARNING" # ~ 30s
+    scripts/config.py full_no_deprecated
+    scripts/config.py unset MBEDTLS_DEPRECATED_REMOVED
+    scripts/config.py set MBEDTLS_DEPRECATED_WARNING
+    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra'
+
+    msg "test: make, full_no_deprecated config, MBEDTLS_DEPRECATED_WARNING" # ~ 5s
+    make test
+}
+
+component_test_full_deprecated_warning () {
+    # Test that when MBEDTLS_DEPRECATED_WARNING is enabled, the build passes
+    # with only certain whitelisted types of warnings.
+    msg "build: make, full config + MBEDTLS_DEPRECATED_WARNING, expect warnings" # ~ 30s
     scripts/config.py full
     scripts/config.py 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
+    # Expect warnings from '#warning' directives in check_config.h.
+    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-error=cpp' lib programs
 
-    msg "test: make, full config + DEPRECATED_WARNING, expect warnings" # ~ 30s
-    make -C tests clean
-    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-error=deprecated-declarations -DMBEDTLS_TEST_DEPRECATED' tests
+    msg "build: make tests, full config + MBEDTLS_DEPRECATED_WARNING, expect warnings" # ~ 30s
+    # Set MBEDTLS_TEST_DEPRECATED to enable tests for deprecated features.
+    # By default those are disabled when MBEDTLS_DEPRECATED_WARNING is set.
+    # Expect warnings from '#warning' directives in check_config.h and
+    # from the use of deprecated functions in test suites.
+    make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-error=deprecated-declarations -Wno-error=cpp -DMBEDTLS_TEST_DEPRECATED' tests
 
-    msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s
-    # No cleanup, just tweak the configuration and rebuild
-    make clean
-    scripts/config.py unset MBEDTLS_DEPRECATED_WARNING
-    scripts/config.py 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
+    msg "test: full config + MBEDTLS_TEST_DEPRECATED" # ~ 30s
+    make test
 }
 
 # Check that the specified libraries exist and are empty.
@@ -997,6 +1047,7 @@
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
     scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
     scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
@@ -1035,6 +1086,7 @@
     scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_FPRINTF_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_MEMORY
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_PRINTF_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
@@ -1064,6 +1116,7 @@
     scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.py unset MBEDTLS_FS_IO
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
@@ -1081,6 +1134,7 @@
     scripts/config.py full
     scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
     make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
 }
 
@@ -1270,6 +1324,7 @@
     scripts/config.py set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
     scripts/config.py set MBEDTLS_ENTROPY_C
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
     scripts/config.py unset MBEDTLS_ENTROPY_HARDWARE_ALT
     scripts/config.py unset MBEDTLS_HAVEGE_C
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan -D UNSAFE_BUILD=ON .
@@ -1387,16 +1442,6 @@
     make test
 }
 
-component_test_se_full () {
-    msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C"
-    scripts/config.py full
-    scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
-
-    msg "test: full config + MBEDTLS_PSA_CRYPTO_SE_C"
-    make test
-}
-
 component_test_make_shared () {
     msg "build/test: make shared" # ~ 40s
     make SHARED=1 all check
@@ -1415,7 +1460,7 @@
     info=$1 cc=$2; shift 2
     for opt in "$@"; do
           msg "build/test: $cc $opt, $info" # ~ 30s
-          make CC="$cc" CFLAGS="$opt -Wall -Wextra -Werror"
+          make CC="$cc" CFLAGS="$opt -std=c99 -pedantic -Wall -Wextra -Werror"
           # We're confident enough in compilers to not run _all_ the tests,
           # but at least run the unit tests. In particular, runs with
           # optimizations use inline assembly whereas runs with -O0
@@ -1566,45 +1611,63 @@
 }
 
 component_build_arm_none_eabi_gcc () {
-    msg "build: arm-none-eabi-gcc, make" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1" # ~ 10s
     scripts/config.py baremetal
-    make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra -O1' lib
+
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1"
+    ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
 component_build_arm_none_eabi_gcc_arm5vte () {
-    msg "build: arm-none-eabi-gcc -march=arm5vte, make" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
     scripts/config.py baremetal
     # Build for a target platform that's close to what Debian uses
     # for its "armel" distribution (https://wiki.debian.org/ArmEabiPort).
     # See https://github.com/ARMmbed/mbedtls/pull/2169 and comments.
     # It would be better to build with arm-linux-gnueabi-gcc but
     # we don't have that on our CI at this time.
-    make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
+
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1"
+    ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
+}
+
+component_build_arm_none_eabi_gcc_m0plus () {
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus" # ~ 10s
+    scripts/config.py baremetal
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra -mthumb -mcpu=cortex-m0plus -Os' lib
+
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os"
+    ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
 component_build_arm_none_eabi_gcc_no_udbl_division () {
-    msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
     scripts/config.py baremetal
     scripts/config.py 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
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra' lib
     echo "Checking that software 64-bit division is not required"
     if_build_succeeded not grep __aeabi_uldiv library/*.o
 }
 
 component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
-    msg "build: arm-none-eabi-gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
     scripts/config.py baremetal
     scripts/config.py 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
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib
     echo "Checking that software 64-bit multiplication is not required"
     if_build_succeeded not grep __aeabi_lmul library/*.o
 }
 
 component_build_armcc () {
-    msg "build: ARM Compiler 5, make"
+    msg "build: ARM Compiler 5"
     scripts/config.py baremetal
-
     make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
+
+    msg "size: ARM Compiler 5"
+    "$ARMC5_FROMELF" -z library/*.o
+
     make clean
 
     # ARM Compiler 6 - Target ARMv7-A
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index aca2f11..08c1410 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -68,10 +68,6 @@
 make clean
 cp "$CONFIG_H" "$CONFIG_BAK"
 scripts/config.py full
-# Enable some deprecated or experimental features that are not in the
-# full config, but are compatible with it and have tests.
-scripts/config.py set MBEDTLS_SSL_PROTO_SSL3
-scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C
 make -j
 
 
diff --git a/tests/scripts/check-files.py b/tests/scripts/check-files.py
index 7474ac7..e8abd75 100755
--- a/tests/scripts/check-files.py
+++ b/tests/scripts/check-files.py
@@ -103,7 +103,7 @@
 
 def is_windows_file(filepath):
     _root, ext = os.path.splitext(filepath)
-    return ext in ('.dsp', '.sln', '.vcxproj')
+    return ext in ('.bat', '.dsp', '.sln', '.vcxproj')
 
 
 class PermissionIssueTracker(FileIssueTracker):
@@ -224,6 +224,7 @@
         self.logger = None
         self.setup_logger(log_file)
         self.extensions_to_check = (
+            ".bat",
             ".c",
             ".data",
             ".dsp",
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index 5986758..ff4cf20 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -19,6 +19,12 @@
  *  This file is part of Mbed TLS (https://tls.mbed.org)
  */
 
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 1 // for fileno() from <stdio.h>
+#endif
+#endif
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include <mbedtls/config.h>
 #else
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 9f10a90..d9ea441 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -1,6 +1,7 @@
 /* BEGIN_HEADER */
 #include "mbedtls/entropy.h"
 #include "mbedtls/entropy_poll.h"
+#include "mbedtls/md.h"
 #include "string.h"
 
 typedef enum
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index 0c2411b..55c3426 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -6,14 +6,11 @@
 Register SE driver: good, again
 register_one:2:PSA_DRV_SE_HAL_VERSION:PSA_SUCCESS
 
-Register SE driver: invalid lifetime (0)
+Register SE driver: invalid location (0)
 register_one:0:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
 
-Register SE driver: invalid lifetime (VOLATILE)
-register_one:PSA_KEY_LIFETIME_VOLATILE:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
-
-Register SE driver: invalid lifetime (PERSISTENT)
-register_one:PSA_KEY_LIFETIME_PERSISTENT:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
+Register SE driver: invalid location (local)
+register_one:PSA_KEY_LOCATION_LOCAL_STORAGE:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
 
 Register SE driver: invalid version (ancient)
 register_one:2:0x00000003:PSA_ERROR_NOT_SUPPORTED
@@ -121,7 +118,7 @@
 generate_key_smoke:PSA_KEY_TYPE_HMAC:256:PSA_ALG_HMAC( PSA_ALG_SHA_256 )
 
 Key registration: smoke test
-register_key_smoke_test:MIN_DRIVER_LIFETIME:1:PSA_SUCCESS
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:1:PSA_SUCCESS
 
 Key registration: invalid lifetime (volatile)
 register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
@@ -130,13 +127,13 @@
 register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: invalid lifetime (no registered driver)
-register_key_smoke_test:MIN_DRIVER_LIFETIME + 1:1:PSA_ERROR_INVALID_ARGUMENT
+register_key_smoke_test:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION + 1 ):1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: rejected
-register_key_smoke_test:MIN_DRIVER_LIFETIME:0:PSA_ERROR_NOT_PERMITTED
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:0:PSA_ERROR_NOT_PERMITTED
 
 Key registration: not supported
-register_key_smoke_test:MIN_DRIVER_LIFETIME:-1:PSA_ERROR_NOT_SUPPORTED
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:-1:PSA_ERROR_NOT_SUPPORTED
 
 Import-sign-verify: sign in driver, ECDSA
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index b468d5e..f95f7e5 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -18,8 +18,14 @@
 /* Test driver helpers */
 /****************************************************************/
 
-/** The minimum valid lifetime value for a secure element driver. */
-#define MIN_DRIVER_LIFETIME 2
+/** The minimum valid location value for a secure element driver. */
+#define MIN_DRIVER_LOCATION 1
+
+/** The location and lifetime used for tests that use a single driver. */
+#define TEST_DRIVER_LOCATION 1
+#define TEST_SE_PERSISTENT_LIFETIME                             \
+    ( PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(           \
+        PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION ) )
 
 /** The driver detected a condition that shouldn't happen.
  * This is probably a bug in the library. */
@@ -547,7 +553,7 @@
             psa_get_key_lifetime( &actual_attributes );
         psa_status_t status = psa_get_key_slot_number( &actual_attributes,
                                                        &actual_slot_number );
-        if( lifetime < MIN_DRIVER_LIFETIME )
+        if( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) < MIN_DRIVER_LOCATION )
         {
             /* The key is not in a secure element. */
             TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
@@ -571,23 +577,23 @@
     return( ok );
 }
 
-/* Get the file UID corresponding to the specified lifetime.
+/* Get the file UID corresponding to the specified location.
  * If this changes, the storage format version must change.
  * See psa_get_se_driver_its_file_uid() in psa_crypto_se.c.
  */
-psa_storage_uid_t file_uid_for_lifetime( psa_key_lifetime_t lifetime )
+psa_storage_uid_t file_uid_for_location( psa_key_location_t location )
 {
-    if( lifetime > PSA_MAX_SE_LIFETIME )
+    if( location > PSA_MAX_SE_LOCATION )
         return( 0 );
-    return( 0xfffffe00 + lifetime );
+    return( 0xfffffe00 + location );
 }
 
 /* Check that the persistent data of a driver has its expected content. */
-static int check_persistent_data( psa_key_lifetime_t lifetime,
+static int check_persistent_data( psa_key_location_t location,
                                   const void *expected_data,
                                   size_t size )
 {
-    psa_storage_uid_t uid = file_uid_for_lifetime( lifetime );
+    psa_storage_uid_t uid = file_uid_for_location( location );
     struct psa_storage_info_t info;
     uint8_t *loaded = NULL;
     int ok = 0;
@@ -737,7 +743,7 @@
 static void psa_purge_storage( void )
 {
     psa_key_id_t id;
-    psa_key_lifetime_t lifetime;
+    psa_key_location_t location;
     /* The tests may have potentially created key ids from 1 to
      * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
      * 0, which file-based storage uses as a temporary file. */
@@ -746,8 +752,8 @@
     /* Purge the transaction file. */
     psa_crypto_stop_transaction( );
     /* Purge driver persistent data. */
-    for( lifetime = 0; lifetime < PSA_MAX_SE_LIFETIME; lifetime++ )
-        psa_destroy_se_persistent_data( lifetime );
+    for( location = 0; location < PSA_MAX_SE_LOCATION; location++ )
+        psa_destroy_se_persistent_data( location );
 }
 
 /* END_HEADER */
@@ -758,7 +764,7 @@
  */
 
 /* BEGIN_CASE */
-void register_one( int lifetime, int version, int expected_status_arg )
+void register_one( int location, int version, int expected_status_arg )
 {
     psa_status_t expected_status = expected_status_arg;
     psa_drv_se_t driver;
@@ -766,7 +772,7 @@
     memset( &driver, 0, sizeof( driver ) );
     driver.hal_version = version;
 
-    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+    TEST_EQUAL( psa_register_se_driver( location, &driver ),
                 expected_status );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -780,16 +786,16 @@
 void register_twice( int count )
 {
     psa_drv_se_t driver;
-    psa_key_lifetime_t lifetime;
-    psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + count;
+    psa_key_location_t location;
+    psa_key_location_t max = MIN_DRIVER_LOCATION + count;
 
     memset( &driver, 0, sizeof( driver ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
 
-    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
-        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
-    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
-        TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+    for( location = MIN_DRIVER_LOCATION; location < max; location++ )
+        PSA_ASSERT( psa_register_se_driver( location, &driver ) );
+    for( location = MIN_DRIVER_LOCATION; location < max; location++ )
+        TEST_EQUAL( psa_register_se_driver( location, &driver ),
                     PSA_ERROR_ALREADY_EXISTS );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -803,16 +809,16 @@
 void register_max( )
 {
     psa_drv_se_t driver;
-    psa_key_lifetime_t lifetime;
-    psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + PSA_MAX_SE_DRIVERS;
+    psa_key_location_t location;
+    psa_key_location_t max = MIN_DRIVER_LOCATION + PSA_MAX_SE_DRIVERS;
 
     memset( &driver, 0, sizeof( driver ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
 
-    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
-        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    for( location = MIN_DRIVER_LOCATION; location < max; location++ )
+        PSA_ASSERT( psa_register_se_driver( location, &driver ) );
 
-    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+    TEST_EQUAL( psa_register_se_driver( location, &driver ),
                 PSA_ERROR_INSUFFICIENT_MEMORY );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -827,7 +833,8 @@
 {
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -846,7 +853,7 @@
     key_management.p_export = ram_export;
     ram_min_slot = min_slot;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Create a key. */
@@ -857,7 +864,7 @@
     PSA_ASSERT( psa_import_key( &attributes,
                                 key_material, sizeof( key_material ),
                                 &handle ) );
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &ram_shadow_slot_usage,
                                  sizeof( ram_shadow_slot_usage ) ) )
         goto exit;
@@ -866,9 +873,9 @@
     if( restart )
     {
         mbedtls_psa_crypto_free( );
-        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+        PSA_ASSERT( psa_register_se_driver( location, &driver ) );
         PSA_ASSERT( psa_crypto_init( ) );
-        if( ! check_persistent_data( lifetime,
+        if( ! check_persistent_data( location,
                                      &ram_shadow_slot_usage,
                                      sizeof( ram_shadow_slot_usage ) ) )
             goto exit;
@@ -894,7 +901,7 @@
 
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &ram_shadow_slot_usage,
                                  sizeof( ram_shadow_slot_usage ) ) )
         goto exit;
@@ -921,7 +928,8 @@
     psa_status_t status;
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -937,7 +945,7 @@
     key_management.p_destroy = ram_destroy;
     key_management.p_export = ram_export;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Create a key. */
@@ -953,7 +961,7 @@
 
     if( status != PSA_SUCCESS )
         goto exit;
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &ram_shadow_slot_usage,
                                  sizeof( ram_shadow_slot_usage ) ) )
         goto exit;
@@ -962,9 +970,9 @@
     if( restart )
     {
         mbedtls_psa_crypto_free( );
-        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+        PSA_ASSERT( psa_register_se_driver( location, &driver ) );
         PSA_ASSERT( psa_crypto_init( ) );
-        if( ! check_persistent_data( lifetime,
+        if( ! check_persistent_data( location,
                                      &ram_shadow_slot_usage,
                                      sizeof( ram_shadow_slot_usage ) ) )
             goto exit;
@@ -980,7 +988,7 @@
 
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &ram_shadow_slot_usage,
                                  sizeof( ram_shadow_slot_usage ) ) )
         goto exit;
@@ -1002,7 +1010,8 @@
     psa_algorithm_t alg = alg_arg;
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1016,7 +1025,7 @@
     key_management.p_import = null_import;
     key_management.p_destroy = null_destroy;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Create a key. */
@@ -1031,7 +1040,7 @@
     PSA_ASSERT( psa_import_key( &attributes,
                                 key_material->x, key_material->len,
                                 &handle ) );
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
 
@@ -1041,9 +1050,9 @@
 
     /* Restart and try again. */
     mbedtls_psa_crypto_free( );
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
     PSA_ASSERT( psa_open_key( id, &handle ) );
@@ -1053,7 +1062,7 @@
     /* We're done. */
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
@@ -1073,7 +1082,8 @@
     size_t bits = bits_arg;
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1086,7 +1096,7 @@
     key_management.p_allocate = counter_allocate;
     /* No p_generate method */
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -1111,7 +1121,8 @@
     psa_algorithm_t alg = alg_arg;
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1125,7 +1136,7 @@
     key_management.p_generate = null_generate;
     key_management.p_destroy = null_destroy;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Create a key. */
@@ -1139,7 +1150,7 @@
     psa_set_key_type( &attributes, type );
     psa_set_key_bits( &attributes, bits );
     PSA_ASSERT( psa_generate_key( &attributes, &handle ) );
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
 
@@ -1149,9 +1160,9 @@
 
     /* Restart and try again. */
     mbedtls_psa_crypto_free( );
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
     PSA_ASSERT( psa_open_key( id, &handle ) );
@@ -1161,7 +1172,7 @@
     /* We're done. */
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
-    if( ! check_persistent_data( lifetime,
+    if( ! check_persistent_data( location,
                                  &shadow_counter, sizeof( shadow_counter ) ) )
         goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
@@ -1190,7 +1201,8 @@
     psa_drv_se_key_management_t key_management;
     psa_drv_se_asymmetric_t asymmetric;
 
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t drv_handle = 0; /* key managed by the driver */
     psa_key_handle_t sw_handle = 0; /* transparent key */
@@ -1229,7 +1241,7 @@
     }
     asymmetric.p_verify = ram_verify;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Prepare to create two keys with the same key material: a transparent
@@ -1347,6 +1359,7 @@
                               int expected_status_arg )
 {
     psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_status_t expected_status = expected_status_arg;
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
@@ -1371,7 +1384,7 @@
             ( validate > 0 ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED );
     }
 
-    PSA_ASSERT( psa_register_se_driver( MIN_DRIVER_LIFETIME, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( MIN_DRIVER_LOCATION, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -1395,7 +1408,7 @@
 
     /* Restart and try again. */
     PSA_DONE( );
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
     PSA_ASSERT( psa_open_key( id, &handle ) );
     if( ! check_key_attributes( handle, &attributes ) )
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
index f60bd76..23e035a 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
@@ -1,11 +1,14 @@
 SE init mock test: success
-mock_init:2:PSA_SUCCESS:PSA_SUCCESS:PSA_SUCCESS:1
+mock_init:1:PSA_SUCCESS:PSA_SUCCESS:PSA_SUCCESS:1
 
 SE init mock test: failure
-mock_init:2:PSA_SUCCESS:PSA_ERROR_HARDWARE_FAILURE:PSA_ERROR_HARDWARE_FAILURE:1
+mock_init:1:PSA_SUCCESS:PSA_ERROR_HARDWARE_FAILURE:PSA_ERROR_HARDWARE_FAILURE:1
 
-SE init mock test: invalid lifetime
-mock_init:1:PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_BAD_STATE:PSA_SUCCESS:0
+SE init mock test: invalid location (0)
+mock_init:0:PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_BAD_STATE:PSA_SUCCESS:0
+
+SE init mock test: location not supported (INT_MAX)
+mock_init:INT_MAX:PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_BAD_STATE:PSA_SUCCESS:0
 
 SE key importing mock test
 mock_import:PSA_SUCCESS:PSA_SUCCESS:0:PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index 9f17b84..f6acb07 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -5,10 +5,16 @@
 #include "psa_crypto_se.h"
 #include "psa_crypto_storage.h"
 
+/** The location and lifetime used for tests that use a single driver. */
+#define TEST_DRIVER_LOCATION 1
+#define TEST_SE_PERSISTENT_LIFETIME                             \
+    ( PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(           \
+        PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION ) )
+
 static struct
 {
     uint16_t called;
-    psa_key_lifetime_t lifetime;
+    psa_key_location_t location;
     psa_status_t return_value;
 } mock_init_data;
 
@@ -84,7 +90,7 @@
 static void psa_purge_storage( void )
 {
     psa_key_id_t id;
-    psa_key_lifetime_t lifetime;
+    psa_key_location_t location;
     /* The tests may have potentially created key ids from 1 to
      * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
      * 0, which file-based storage uses as a temporary file. */
@@ -93,8 +99,8 @@
     /* Purge the transaction file. */
     psa_crypto_stop_transaction( );
     /* Purge driver persistent data. */
-    for( lifetime = 0; lifetime < PSA_MAX_SE_LIFETIME; lifetime++ )
-        psa_destroy_se_persistent_data( lifetime );
+    for( location = 0; location < PSA_MAX_SE_LOCATION; location++ )
+        psa_destroy_se_persistent_data( location );
 }
 
 static void mock_teardown( void )
@@ -113,13 +119,13 @@
 
 static psa_status_t mock_init( psa_drv_se_context_t *drv_context,
                                void *persistent_data,
-                               psa_key_lifetime_t lifetime )
+                               psa_key_location_t location )
 {
     (void) drv_context;
     (void) persistent_data;
 
     mock_init_data.called++;
-    mock_init_data.lifetime = lifetime;
+    mock_init_data.location = location;
     return( mock_init_data.return_value );
 }
 
@@ -279,13 +285,13 @@
  */
 
 /* BEGIN_CASE */
-void mock_init( int lifetime_arg,
+void mock_init( int location_arg,
                 int expected_register_status_arg,
                 int driver_status_arg,
                 int expected_psa_status_arg,
                 int expected_called )
 {
-    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_location_t location = location_arg;
     psa_status_t expected_register_status = expected_register_status_arg;
     psa_status_t driver_status = driver_status_arg;
     psa_status_t expected_psa_status = expected_psa_status_arg;
@@ -297,7 +303,7 @@
 
     mock_init_data.return_value = driver_status;
 
-    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+    TEST_EQUAL( psa_register_se_driver( location, &driver ),
                 expected_register_status );
 
     psa_crypto_init_called = 1;
@@ -305,7 +311,7 @@
 
     TEST_EQUAL( mock_init_data.called, expected_called );
     if( expected_called )
-        TEST_EQUAL( mock_init_data.lifetime, lifetime );
+        TEST_EQUAL( mock_init_data.location, location );
 
 exit:
     if( psa_crypto_init_called )
@@ -322,7 +328,8 @@
 {
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -339,7 +346,7 @@
     key_management.p_destroy = mock_destroy;
     key_management.p_allocate = mock_allocate;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -378,7 +385,8 @@
 {
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -397,7 +405,7 @@
     key_management.p_destroy = mock_destroy;
     key_management.p_allocate = mock_allocate;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -431,7 +439,8 @@
 {
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -446,7 +455,7 @@
     key_management.p_destroy = mock_destroy;
     key_management.p_allocate = mock_allocate;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -485,7 +494,8 @@
 {
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -503,7 +513,7 @@
     key_management.p_destroy = mock_destroy;
     key_management.p_allocate = mock_allocate;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -534,7 +544,8 @@
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
     psa_drv_se_asymmetric_t asymmetric;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -559,7 +570,7 @@
     driver.asymmetric = &asymmetric;
     asymmetric.p_sign = mock_sign;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -594,7 +605,8 @@
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
     psa_drv_se_asymmetric_t asymmetric;
-    psa_key_lifetime_t lifetime = 2;
+    psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
     psa_key_id_t id = 1;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -618,7 +630,7 @@
     driver.asymmetric = &asymmetric;
     asymmetric.p_verify = mock_verify;
 
-    PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 7012e8e..23a9932 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -176,7 +176,7 @@
 
 X509 certificate v1 with extension
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_SHA1_C
-x509_cert_info:"data_files/cert_v1_with_ext.crt":"cert. version     \: 1\nserial number     \: BD\:ED\:44\:C7\:D2\:3E\:C2\:A4\nissuer name       \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nsubject name      \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nissued  on        \: 2013-07-04 16\:17\:02\nexpires on        \: 2014-07-04 16\:17\:02\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nsubject alt name  \:\n    dNSName \: identity-check.org\n    dNSName \: www.identity-check.org\n"
+x509_cert_info:"data_files/cert_v1_with_ext.crt":"cert. version     \: 1\nserial number     \: BD\:ED\:44\:C7\:D2\:3E\:C2\:A4\nissuer name       \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nsubject name      \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nissued  on        \: 2013-07-04 16\:17\:02\nexpires on        \: 2014-07-04 16\:17\:02\nsigned using      \: RSA with SHA1\nRSA key size      \: 2048 bits\nsubject alt name  \:\n    dNSName \: identity-check.org\n    dNSName \: www.identity-check.org\n    <unsupported>\n"
 
 X509 SAN parsing otherName
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
@@ -1563,7 +1563,7 @@
 x509parse_crt:"308198308182a0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRT ASN1 (TBS, valid IssuerID, inv SubjectID, inv tag)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+depends_on:!MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"30819a308184a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa1000500300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 X509 CRT ASN1 (TBSCertificate v3, ext SubjectAlternativeName malformed)
@@ -1583,13 +1583,21 @@
 x509parse_crt:"30819a308184a0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa100a201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRT ASN1 (TBS, IssuerID unsupported in v1 CRT)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+depends_on:!MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"30819a308184a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa100a201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
+X509 CRT ASN1 (TBS, IssuerID unsupported in v1 CRT, ALLOW_EXTENSIONS_NON_V3)
+depends_on:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509parse_crt:"30819a308184a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa100a201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
 X509 CRT ASN1 (TBS, SubjectID unsupported in v1 CRT)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+depends_on:!MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"30819a308184a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa200a201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
+X509 CRT ASN1 (TBS, SubjectID unsupported in v1 CRT, ALLOW_EXTENSIONS_NON_V3)
+depends_on:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509parse_crt:"30819a308184a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa200a201300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
 X509 CRT ASN1 (TBS, inv v3Ext, inv tag)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"30819c308186a0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa100a2000500300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
@@ -1838,12 +1846,24 @@
 depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"3081dc3081c6a0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa100a200a321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
-X509 CRT ASN1 (TBS, valid v3Ext in v1 CRT)
+X509 CRT (TBS, valid v3Ext in v1 CRT, ALLOW_EXTENSIONS_NON_V3)
+depends_on:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509parse_crt:"3081b93081a3a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"cert. version     \: 1\nserial number     \: DE\:AD\:BE\:EF\nissuer name       \: ??=Test\nsubject name      \: ??=Test\nissued  on        \: 2009-01-01 00\:00\:00\nexpires on        \: 2009-12-31 23\:59\:59\nsigned using      \: RSA with SHA-256\nRSA key size      \: 128 bits\nsubject alt name  \:\n    dNSName \: foo.test\n    dNSName \: bar.test\n":0
+
+X509 CRT (TBS, valid v3Ext in v2 CRT, ALLOW_EXTENSIONS_NON_V3)
+depends_on:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509parse_crt:"3081b93081a3a0030201018204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"cert. version     \: 2\nserial number     \: DE\:AD\:BE\:EF\nissuer name       \: ??=Test\nsubject name      \: ??=Test\nissued  on        \: 2009-01-01 00\:00\:00\nexpires on        \: 2009-12-31 23\:59\:59\nsigned using      \: RSA with SHA-256\nRSA key size      \: 128 bits\nsubject alt name  \:\n    dNSName \: foo.test\n    dNSName \: bar.test\n":0
+
+X509 CRT (TBS, valid v3Ext in v3 CRT)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+x509parse_crt:"3081b93081a3a0030201028204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"cert. version     \: 3\nserial number     \: DE\:AD\:BE\:EF\nissuer name       \: ??=Test\nsubject name      \: ??=Test\nissued  on        \: 2009-01-01 00\:00\:00\nexpires on        \: 2009-12-31 23\:59\:59\nsigned using      \: RSA with SHA-256\nRSA key size      \: 128 bits\nsubject alt name  \:\n    dNSName \: foo.test\n    dNSName \: bar.test\n":0
+
+X509 CRT ASN1 (TBS, valid v3Ext in v1 CRT)
+depends_on:!MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"3081b93081a3a0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 X509 CRT ASN1 (TBS, valid v3Ext in v2 CRT)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
+depends_on:!MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
 x509parse_crt:"3081b93081a3a0030201018204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa321301f301d0603551d11041630148208666f6f2e7465737482086261722e74657374300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 X509 CRT ASN1 (TBS, valid SubjectID, valid IssuerID, inv v3Ext, SubjectAltName repeated outside Extensions, inv SubjectAltNames tag)