Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: mbed...@packages.debian.org
Control: affects -1 + src:mbedtls

Please unblock package mbedtls

[ Reason ]
Upstream released a new LTS bugfix version, and I'd like to have it in
bookworm. Since mbedtls is a crypto library and backporting single commits can
be dangerous, importing new versions is the safest and most appropriate thing
to do, especially since the upstream developers do a pretty good job in
maintaining LTS versions for a long time.

[ Impact ]
If not granted, Debian will release with a somewhat vulnerable/buggy version of
a widely used crypto library.

[ Tests ]
I've manually reviewed the changelog and diffs of the new release, tested it
locally with the upstream test suite and autopkgtest, and it has passed all the
CI checks on Salsa (repo available at
<https://salsa.debian.org/debian/mbedtls>).

[ Risks ]
Risks should be low, as upstream usually does a good job with backporting. The
"only" issue is that between 2.28.2 and 2.28.3 they have adopted a new code
style, and reformatted the whole codebase accordingly; this means that the
debdiff is huge, even though the changes are only a few. To make reviewing
easier for me and you too, I've prepared three git diffs that exclude the
upstream commits that reformatted the code, and another one that adds the
string "\emptydescription" to many documentation strings in the source files.
As upstream also always backports test code along with fixes, these diffs only
include changes from the include/ and library/ directories, since that's where
the code that gets into the binary packages resides.
.
The diffs were generated with these commands:
.
    $ git clone https://github.com/Mbed-TLS/mbedtls.git
    $ cd mbedtls
    $ git diff v2.28.2..160df1d13621ca3ee70e1fa19d0da88398da9683~1 include/
library/
    $ git diff
b37f6c1b95815d39fea26b2a17e318602eefe709..b361e04207831f753a29d6036361d4447aaaa3bc~1
include/ library/
    $ git diff 7a5168e90db359e17e72591cb5ddb06ef5f0388f..v2.28.3 include/
library/

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
I mistakenly uploaded the new mbedtls version to unstable because I didn't
realize it was a key package, and thought that a regular 20 days of waiting
would suffice. This is also my first unblock request, so please be clement with
me, thanks! :D

Also, the debdiff is not directly attached to this email to avoid hitting the
size limit of the mailing list. You can find it here:
<https://bin.snopyta.org/?b47ce8f3107c9a0a#92ZuUuxNvi8AWA1bVTPXCDFxakvxG1XUgcguoLnQKVcw>

unblock mbedtls/2.28.2-1
diff --git a/include/mbedtls/bn_mul.h b/include/mbedtls/bn_mul.h
index a3fc36381..bce9ce38c 100644
--- a/include/mbedtls/bn_mul.h
+++ b/include/mbedtls/bn_mul.h
@@ -84,6 +84,7 @@
 
 #endif /* bits in mbedtls_mpi_uint */
 
+/* *INDENT-OFF* */
 #if defined(MBEDTLS_HAVE_ASM)
 
 #ifndef asm
@@ -1001,4 +1002,5 @@
 #endif /* C (generic)  */
 #endif /* C (longlong) */
 
+/* *INDENT-ON* */
 #endif /* bn_mul.h */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 7ae1ff94d..2ab99823e 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -28,6 +28,7 @@
 #ifndef MBEDTLS_CHECK_CONFIG_H
 #define MBEDTLS_CHECK_CONFIG_H
 
+/* *INDENT-OFF* */
 /*
  * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
  * target platforms, so not an issue, but let's just be extra sure.
@@ -143,6 +144,11 @@
 #error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but 
MBEDTLS_ECDH_LEGACY_CONTEXT not disabled"
 #endif
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)           && \
+    !defined(MBEDTLS_ECP_C)
+#error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
 #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
 #endif
@@ -955,4 +961,5 @@
  */
 typedef int mbedtls_iso_c_forbids_empty_translation_units;
 
+/* *INDENT-ON* */
 #endif /* MBEDTLS_CHECK_CONFIG_H */
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 6d83da882..ce100d3ed 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -917,13 +917,13 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
  *                      parameter-verification failure.
  * \return              A cipher-specific error code on failure.
  */
-int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         unsigned char *tag, size_t tag_len )
-                         MBEDTLS_DEPRECATED;
+int MBEDTLS_DEPRECATED mbedtls_cipher_auth_encrypt(
+        mbedtls_cipher_context_t *ctx,
+        const unsigned char *iv, size_t iv_len,
+        const unsigned char *ad, size_t ad_len,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output, size_t *olen,
+        unsigned char *tag, size_t tag_len );
 
 /**
  * \brief               The generic authenticated decryption (AEAD) function.
@@ -976,13 +976,13 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t 
*ctx,
  * \return              #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not 
authentic.
  * \return              A cipher-specific error code on failure.
  */
-int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         const unsigned char *tag, size_t tag_len )
-                         MBEDTLS_DEPRECATED;
+int MBEDTLS_DEPRECATED mbedtls_cipher_auth_decrypt(
+        mbedtls_cipher_context_t *ctx,
+        const unsigned char *iv, size_t iv_len,
+        const unsigned char *ad, size_t ad_len,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output, size_t *olen,
+        const unsigned char *tag, size_t tag_len );
 #undef MBEDTLS_DEPRECATED
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_CIPHER_MODE_AEAD */
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 61db79362..9a2de676d 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -859,12 +859,37 @@
  * This is useful in non-threaded environments if you want to avoid blocking
  * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
  *
- * Uncomment this macro to enable restartable ECC computations.
+ * This option:
+ * - Adds xxx_restartable() variants of existing operations in the
+ *   following modules, with corresponding restart context types:
+ *   - ECP (for Short Weierstrass curves only): scalar multiplication (mul),
+ *     linear combination (muladd);
+ *   - ECDSA: signature generation & verification;
+ *   - PK: signature generation & verification;
+ *   - X509: certificate chain verification.
+ * - Adds mbedtls_ecdh_enable_restart() in the ECDH module.
+ * - Changes the behaviour of TLS 1.2 clients (not servers) when using the
+ *   ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC
+ *   computations restartable:
+ *   - ECDH operations from the key exchange, only for Short Weierstass
+ *     curves;
+ *   - verification of the server's key exchange signature;
+ *   - verification of the server's certificate chain;
+ *   - generation of the client's signature if client authentication is used,
+ *     with an ECC key/certificate.
+ *
+ * \note  In the cases above, the usual SSL/TLS functions, such as
+ *        mbedtls_ssl_handshake(), can now return
+ *        MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS.
  *
  * \note  This option only works with the default software implementation of
  *        elliptic curve functionality. It is incompatible with
- *        MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT
- *        and MBEDTLS_ECDH_LEGACY_CONTEXT.
+ *        MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT,
+ *        MBEDTLS_ECDH_LEGACY_CONTEXT, and MBEDTLS_USE_PSA_CRYPTO.
+ *
+ * Requires: MBEDTLS_ECP_C
+ *
+ * Uncomment this macro to enable restartable ECC computations.
  */
 //#define MBEDTLS_ECP_RESTARTABLE
 
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index faa3b9e3f..b75947cdb 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -2861,7 +2861,7 @@ psa_status_t psa_aead_abort(psa_aead_operation_t 
*operation);
  *
  * \note To perform a multi-part hash-and-sign signature algorithm, first use
  *       a multi-part hash operation and then pass the resulting hash to
- *       psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the
+ *       psa_sign_hash(). PSA_ALG_SIGN_GET_HASH(\p alg) can be used to 
determine the
  *       hash algorithm to use.
  *
  * \param[in]  key              Identifier of the key to use for the operation.
@@ -2927,7 +2927,7 @@ psa_status_t psa_sign_message( mbedtls_svc_key_id_t key,
  * \note To perform a multi-part hash-and-sign signature verification
  *       algorithm, first use a multi-part hash operation to hash the message
  *       and then pass the resulting hash to psa_verify_hash().
- *       PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm
+ *       PSA_ALG_SIGN_GET_HASH(\p alg) can be used to determine the hash 
algorithm
  *       to use.
  *
  * \param[in]  key              Identifier of the key to use for the operation.
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index a4b4927e9..a9fddb797 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -57,6 +57,13 @@
  * value, check with the Arm PSA framework group to pick one that other
  * domains aren't already using. */
 
+/* Tell uncrustify not to touch the constant definitions, otherwise
+ * it might change the spacing to something that is not PSA-compliant
+ * (e.g. adding a space after casts).
+ *
+ * *INDENT-OFF*
+ */
+
 /** The action was completed successfully. */
 #define PSA_SUCCESS ((psa_status_t)0)
 
@@ -327,6 +334,8 @@
  */
 #define PSA_ERROR_DATA_INVALID          ((psa_status_t)-153)
 
+/* *INDENT-ON* */
+
 /**@}*/
 
 /** \defgroup crypto_types Key and algorithm types
@@ -819,7 +828,9 @@
     (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
 
 /** An invalid algorithm identifier value. */
+/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */
 #define PSA_ALG_NONE                            ((psa_algorithm_t)0)
+/* *INDENT-ON* */
 
 #define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
 /** MD2 */
@@ -1690,7 +1701,7 @@
 #define PSA_ALG_HKDF_BASE                       ((psa_algorithm_t)0x08000100)
 /** Macro to build an HKDF algorithm.
  *
- * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256.
+ * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256.
  *
  * This key derivation algorithm uses the following inputs:
  * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step.
@@ -1743,7 +1754,7 @@
  * concatenation of ServerHello.Random + ClientHello.Random,
  * and the label is "key expansion".
  *
- * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the
+ * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the
  * TLS 1.2 PRF using HMAC-SHA-256.
  *
  * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
@@ -1789,7 +1800,7 @@
  * ClientHello.Random + ServerHello.Random,
  * and the label is "master secret" or "extended master secret".
  *
- * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the
+ * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the
  * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256.
  *
  * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
@@ -2085,7 +2096,9 @@
 
 /** The null key identifier.
  */
+/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */
 #define PSA_KEY_ID_NULL                         ((psa_key_id_t)0)
+/* *INDENT-ON* */
 /** The minimum value for a key identifier chosen by the application.
  */
 #define PSA_KEY_ID_USER_MIN                     ((psa_key_id_t)0x00000001)
diff --git a/library/aesni.c b/library/aesni.c
index 996292ff6..4b16d9250 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -36,9 +36,11 @@
 
 #include <string.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(MBEDTLS_HAVE_X86_64)
 
diff --git a/library/bignum.c b/library/bignum.c
index 37193f55a..32038f8eb 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1559,9 +1559,9 @@ static mbedtls_mpi_uint mbedtls_int_div_int( 
mbedtls_mpi_uint u1,
      */
     if( 0 == d || u1 >= d )
     {
-        if (r != NULL) *r = ~0;
+        if (r != NULL) *r = ~(mbedtls_mpi_uint)0u;
 
-        return ( ~0 );
+        return ( ~(mbedtls_mpi_uint)0u );
     }
 
 #if defined(MBEDTLS_HAVE_UDBL)
@@ -1700,7 +1700,7 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, 
const mbedtls_mpi *A,
     for( i = n; i > t ; i-- )
     {
         if( X.p[i] >= Y.p[t] )
-            Z.p[i - t - 1] = ~0;
+            Z.p[i - t - 1] = ~(mbedtls_mpi_uint)0u;
         else
         {
             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
diff --git a/library/entropy.c b/library/entropy.c
index e3b337ff3..77e2bfdd5 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -590,7 +590,7 @@ static int mbedtls_entropy_source_self_test_check_bits( 
const unsigned char *buf
 }
 
 /*
- * A test to ensure hat the entropy sources are functioning correctly
+ * A test to ensure that the entropy sources are functioning correctly
  * and there is no obvious failure. The test performs the following checks:
  *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
  *    bits set).
diff --git a/library/padlock.c b/library/padlock.c
index 837337413..12ea2472d 100644
--- a/library/padlock.c
+++ b/library/padlock.c
@@ -31,9 +31,11 @@
 
 #include <string.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(MBEDTLS_HAVE_X86)
 
diff --git a/library/psa_crypto_aead.h b/library/psa_crypto_aead.h
index aab0f835c..e18e85d1c 100644
--- a/library/psa_crypto_aead.h
+++ b/library/psa_crypto_aead.h
@@ -148,4 +148,4 @@ psa_status_t mbedtls_psa_aead_decrypt(
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
 
-#endif /* PSA_CRYPTO_AEAD */
+#endif /* PSA_CRYPTO_AEAD_H */
diff --git a/library/psa_crypto_driver_wrappers.c 
b/library/psa_crypto_driver_wrappers.c
index c455ecb93..c9b86fe81 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -275,7 +275,7 @@ psa_status_t psa_driver_wrapper_sign_hash(
                     alg, hash, hash_length,
                     signature, signature_size, signature_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
@@ -359,7 +359,7 @@ psa_status_t psa_driver_wrapper_verify_hash(
                     alg, hash, hash_length,
                     signature, signature_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
@@ -579,7 +579,7 @@ psa_status_t psa_driver_wrapper_import_key(
 
         return( PSA_SUCCESS );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     switch( location )
     {
@@ -641,7 +641,7 @@ psa_status_t psa_driver_wrapper_export_key(
                      *( (psa_key_slot_number_t *)key_buffer ),
                      data, data_size, data_length ) );
     }
-#endif /* PSA_CRYPTO_SE_C */
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     switch( location )
     {
diff --git a/library/psa_crypto_its.h b/library/psa_crypto_its.h
index 3a3f49a72..90e761237 100644
--- a/library/psa_crypto_its.h
+++ b/library/psa_crypto_its.h
@@ -54,11 +54,6 @@ struct psa_storage_info_t
 /** Flag indicating that \ref psa_storage_create and \ref 
psa_storage_set_extended are supported */
 #define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0)
 
-/** \brief PSA storage specific error codes
- */
-#define PSA_ERROR_INVALID_SIGNATURE     ((psa_status_t)-149)
-#define PSA_ERROR_DATA_CORRUPT          ((psa_status_t)-152)
-
 #define PSA_ITS_API_VERSION_MAJOR  1  /**< The major version number of the PSA 
ITS API. It will be incremented on significant updates that may include 
breaking changes */
 #define PSA_ITS_API_VERSION_MINOR  1  /**< The minor version number of the PSA 
ITS API. It will be incremented in small updates that are unlikely to include 
breaking changes */
 
@@ -73,7 +68,7 @@ struct psa_storage_info_t
  * \return      A status indicating the success/failure of the operation
  *
  * \retval      #PSA_SUCCESS                     The operation completed 
successfully
- * \retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because 
the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because 
the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE
  * \retval      #PSA_ERROR_NOT_SUPPORTED         The operation failed because 
one or more of the flags provided in `create_flags` is not supported or is not 
valid
  * \retval      #PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because 
there was insufficient space on the storage medium
  * \retval      #PSA_ERROR_STORAGE_FAILURE       The operation failed because 
the physical storage has failed (Fatal error)
@@ -137,7 +132,7 @@ psa_status_t psa_its_get_info(psa_storage_uid_t uid,
  *
  * \retval      #PSA_SUCCESS                  The operation completed 
successfully
  * \retval      #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the 
provided key value was not found in the storage
- * \retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the 
provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the 
provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE
  * \retval      #PSA_ERROR_STORAGE_FAILURE    The operation failed because the 
physical storage has failed (Fatal error)
  */
 psa_status_t psa_its_remove(psa_storage_uid_t uid);
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 0563c0b59..8efccce55 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1363,10 +1363,23 @@ static int ssl_parse_client_hello_v2( 
mbedtls_ssl_context *ssl )
 #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
     for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
         for( i = 0; ciphersuites[i] != 0; i++ )
+        {
+            if( p[0] != 0 ||
+                MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] )
+                continue;
+
+            got_common_suite = 1;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite_v2;
+        }
 #else
     for( i = 0; ciphersuites[i] != 0; i++ )
         for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
-#endif
         {
             if( p[0] != 0 ||
                 MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] )
@@ -1381,6 +1394,7 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context 
*ssl )
             if( ciphersuite_info != NULL )
                 goto have_ciphersuite_v2;
         }
+#endif
 
     if( got_common_suite )
     {
@@ -2233,10 +2247,22 @@ read_record_header:
 #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
     for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
         for( i = 0; ciphersuites[i] != 0; i++ )
+        {
+            if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] )
+                continue;
+
+            got_common_suite = 1;
+
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
+
+            if( ciphersuite_info != NULL )
+                goto have_ciphersuite;
+        }
 #else
     for( i = 0; ciphersuites[i] != 0; i++ )
         for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
-#endif
         {
             if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] )
                 continue;
@@ -2250,6 +2276,7 @@ read_record_header:
             if( ciphersuite_info != NULL )
                 goto have_ciphersuite;
         }
+#endif
 
     if( got_common_suite )
     {
diff --git a/library/timing.c b/library/timing.c
index 6c14a4fd0..7f559bebd 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -33,9 +33,11 @@
 #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in 
config.h"
 #endif
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
@@ -223,7 +225,7 @@ unsigned long mbedtls_timing_hardclock( void )
     }
 
     gettimeofday( &tv_cur, NULL );
-    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
+    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000U
           + ( tv_cur.tv_usec - tv_init.tv_usec ) );
 }
 #endif /* !HAVE_HARDCLOCK */
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 02421e4c8..aa155d7bf 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -83,16 +83,16 @@ extern "C" {
 /**
  * \brief     Supported cipher types.
  *
- * \warning   RC4 and DES are considered weak ciphers and their use
- *            constitutes a security risk. Arm recommends considering stronger
+ * \warning   RC4 and DES/3DES are considered weak ciphers and their use
+ *            constitutes a security risk. We recommend considering stronger
  *            ciphers instead.
  */
 typedef enum {
     MBEDTLS_CIPHER_ID_NONE = 0,  /**< Placeholder to mark the end of cipher ID 
lists. */
     MBEDTLS_CIPHER_ID_NULL,      /**< The identity cipher, treated as a stream 
cipher. */
     MBEDTLS_CIPHER_ID_AES,       /**< The AES cipher. */
-    MBEDTLS_CIPHER_ID_DES,       /**< The DES cipher. */
-    MBEDTLS_CIPHER_ID_3DES,      /**< The Triple DES cipher. */
+    MBEDTLS_CIPHER_ID_DES,       /**< The DES cipher. \warning DES is 
considered weak. */
+    MBEDTLS_CIPHER_ID_3DES,      /**< The Triple DES cipher. \warning 3DES is 
considered weak. */
     MBEDTLS_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */
     MBEDTLS_CIPHER_ID_BLOWFISH,  /**< The Blowfish cipher. */
     MBEDTLS_CIPHER_ID_ARC4,      /**< The RC4 cipher. */
@@ -103,8 +103,8 @@ typedef enum {
 /**
  * \brief     Supported {cipher type, cipher mode} pairs.
  *
- * \warning   RC4 and DES are considered weak ciphers and their use
- *            constitutes a security risk. Arm recommends considering stronger
+ * \warning   RC4 and DES/3DES are considered weak ciphers and their use
+ *            constitutes a security risk. We recommend considering stronger
  *            ciphers instead.
  */
 typedef enum {
@@ -140,12 +140,12 @@ typedef enum {
     MBEDTLS_CIPHER_CAMELLIA_128_GCM,     /**< Camellia cipher with 128-bit GCM 
mode. */
     MBEDTLS_CIPHER_CAMELLIA_192_GCM,     /**< Camellia cipher with 192-bit GCM 
mode. */
     MBEDTLS_CIPHER_CAMELLIA_256_GCM,     /**< Camellia cipher with 256-bit GCM 
mode. */
-    MBEDTLS_CIPHER_DES_ECB,              /**< DES cipher with ECB mode. */
-    MBEDTLS_CIPHER_DES_CBC,              /**< DES cipher with CBC mode. */
-    MBEDTLS_CIPHER_DES_EDE_ECB,          /**< DES cipher with EDE ECB mode. */
-    MBEDTLS_CIPHER_DES_EDE_CBC,          /**< DES cipher with EDE CBC mode. */
-    MBEDTLS_CIPHER_DES_EDE3_ECB,         /**< DES cipher with EDE3 ECB mode. */
-    MBEDTLS_CIPHER_DES_EDE3_CBC,         /**< DES cipher with EDE3 CBC mode. */
+    MBEDTLS_CIPHER_DES_ECB,              /**< DES cipher with ECB mode. 
\warning DES is considered weak. */
+    MBEDTLS_CIPHER_DES_CBC,              /**< DES cipher with CBC mode. 
\warning DES is considered weak. */
+    MBEDTLS_CIPHER_DES_EDE_ECB,          /**< DES cipher with EDE ECB mode. 
\warning 3DES is considered weak. */
+    MBEDTLS_CIPHER_DES_EDE_CBC,          /**< DES cipher with EDE CBC mode. 
\warning 3DES is considered weak. */
+    MBEDTLS_CIPHER_DES_EDE3_ECB,         /**< DES cipher with EDE3 ECB mode. 
\warning 3DES is considered weak. */
+    MBEDTLS_CIPHER_DES_EDE3_CBC,         /**< DES cipher with EDE3 CBC mode. 
\warning 3DES is considered weak. */
     MBEDTLS_CIPHER_BLOWFISH_ECB,         /**< Blowfish cipher with ECB mode. */
     MBEDTLS_CIPHER_BLOWFISH_CBC,         /**< Blowfish cipher with CBC mode. */
     MBEDTLS_CIPHER_BLOWFISH_CFB64,       /**< Blowfish cipher with CFB64 mode. 
*/
@@ -226,11 +226,11 @@ typedef enum {
 enum {
     /** Undefined key length. */
     MBEDTLS_KEY_LENGTH_NONE = 0,
-    /** Key length, in bits (including parity), for DES keys. */
+    /** Key length, in bits (including parity), for DES keys. \warning DES is 
considered weak. */
     MBEDTLS_KEY_LENGTH_DES  = 64,
-    /** Key length in bits, including parity, for DES in two-key EDE. */
+    /** Key length in bits, including parity, for DES in two-key EDE. \warning 
3DES is considered weak. */
     MBEDTLS_KEY_LENGTH_DES_EDE = 128,
-    /** Key length in bits, including parity, for DES in three-key EDE. */
+    /** Key length in bits, including parity, for DES in three-key EDE. 
\warning 3DES is considered weak. */
     MBEDTLS_KEY_LENGTH_DES_EDE3 = 192,
 };
 
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 9a2de676d..5dcbdd1dd 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -2765,7 +2765,7 @@
  *
  * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
  *
- * \warning   DES is considered a weak cipher and its use constitutes a
+ * \warning   DES/3DES are considered weak ciphers and their use constitutes a
  *            security risk. We recommend considering stronger ciphers instead.
  */
 #define MBEDTLS_DES_C
diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h
index 2944d5cf1..f2bc58138 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -3,7 +3,7 @@
  *
  * \brief DES block cipher
  *
- * \warning   DES is considered a weak cipher and its use constitutes a
+ * \warning   DES/3DES are considered weak ciphers and their use constitutes a
  *            security risk. We recommend considering stronger ciphers
  *            instead.
  */
@@ -60,7 +60,7 @@ extern "C" {
 /**
  * \brief          DES context structure
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -71,6 +71,10 @@ mbedtls_des_context;
 
 /**
  * \brief          Triple-DES context structure
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 typedef struct mbedtls_des3_context {
     uint32_t sk[96];            /*!<  3DES subkeys      */
@@ -86,7 +90,7 @@ mbedtls_des3_context;
  *
  * \param ctx      DES context to be initialized
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -97,7 +101,7 @@ void mbedtls_des_init(mbedtls_des_context *ctx);
  *
  * \param ctx      DES context to be cleared
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -107,6 +111,10 @@ void mbedtls_des_free(mbedtls_des_context *ctx);
  * \brief          Initialize Triple-DES context
  *
  * \param ctx      DES3 context to be initialized
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 void mbedtls_des3_init(mbedtls_des3_context *ctx);
 
@@ -114,6 +122,10 @@ void mbedtls_des3_init(mbedtls_des3_context *ctx);
  * \brief          Clear Triple-DES context
  *
  * \param ctx      DES3 context to be cleared
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 void mbedtls_des3_free(mbedtls_des3_context *ctx);
 
@@ -125,7 +137,7 @@ void mbedtls_des3_free(mbedtls_des3_context *ctx);
  *
  * \param key      8-byte secret key
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -141,7 +153,7 @@ void mbedtls_des_key_set_parity(unsigned char 
key[MBEDTLS_DES_KEY_SIZE]);
  *
  * \return         0 is parity was ok, 1 if parity was not correct.
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -155,7 +167,7 @@ int mbedtls_des_key_check_key_parity(const unsigned char 
key[MBEDTLS_DES_KEY_SIZ
  *
  * \return         0 if no weak key was found, 1 if a weak key was identified.
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -170,7 +182,7 @@ int mbedtls_des_key_check_weak(const unsigned char 
key[MBEDTLS_DES_KEY_SIZE]);
  *
  * \return         0
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -185,7 +197,7 @@ int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const 
unsigned char key[MBE
  *
  * \return         0
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -199,6 +211,10 @@ int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const 
unsigned char key[MBE
  * \param key      16-byte secret key
  *
  * \return         0
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,
@@ -211,6 +227,10 @@ int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,
  * \param key      16-byte secret key
  *
  * \return         0
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,
@@ -223,6 +243,10 @@ int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,
  * \param key      24-byte secret key
  *
  * \return         0
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,
@@ -235,6 +259,10 @@ int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,
  * \param key      24-byte secret key
  *
  * \return         0
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,
@@ -249,7 +277,7 @@ int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,
  *
  * \return         0 if successful
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -277,7 +305,7 @@ int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx,
  * \param input    buffer holding the input data
  * \param output   buffer holding the output data
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
@@ -298,6 +326,10 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx,
  * \param output   64-bit output block
  *
  * \return         0 if successful
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,
@@ -324,6 +356,10 @@ int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,
  * \param output   buffer holding the output data
  *
  * \return         0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
+ *
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
+ *                 security risk. We recommend considering stronger ciphers
+ *                 instead.
  */
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,
@@ -342,7 +378,7 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,
  * \param SK       Round keys
  * \param key      Base key
  *
- * \warning        DES is considered a weak cipher and its use constitutes a
+ * \warning        DES/3DES are considered weak ciphers and their use 
constitutes a
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
diff --git a/library/Makefile b/library/Makefile
index 3b91e2556..b011e8873 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -186,6 +186,13 @@ else
 all: shared static
 endif
 
+ifdef TEST_TIMING_ALT_IMPL
+OBJS_CRYPTO += external_timing_for_test.o
+external_timing_for_test.o: 
../tests/src/external_timing/external_timing_for_test.c
+       echo "  CC    $<"
+       $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
+endif
+
 static: libmbedcrypto.a libmbedx509.a libmbedtls.a
        cd ../tests && echo "This is a seedfile that contains 64 bytes (65 on 
Windows)......" > seedfile
 
diff --git a/library/bignum.c b/library/bignum.c
index 5ec0541e8..d915ade63 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1280,7 +1280,7 @@ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi 
*A, const mbedtls_mpi
     /* Set the high limbs of X to match A. Don't touch the lower limbs
      * because X might be aliased to B, and we must not overwrite the
      * significant digits of B. */
-    if (A->n > n) {
+    if (A->n > n && A != X) {
         memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
     }
     if (X->n > A->n) {
@@ -2063,6 +2063,7 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi 
*A,
     size_t window_bitsize;
     size_t i, j, nblimbs;
     size_t bufsize, nbits;
+    size_t exponent_bits_in_window = 0;
     mbedtls_mpi_uint ei, mm, state;
     mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
     int neg;
@@ -2236,7 +2237,6 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi 
*A,
     nblimbs = E->n;
     bufsize = 0;
     nbits   = 0;
-    size_t exponent_bits_in_window = 0;
     state   = 0;
 
     while (1) {
diff --git a/library/ccm.c b/library/ccm.c
index 82c308aa8..2d2695e97 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -478,7 +478,7 @@ int mbedtls_ccm_self_test(int verbose)
     mbedtls_ccm_init(&ctx);
 
     if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
-                           8 * sizeof key_test_data) != 0) {
+                           8 * sizeof(key_test_data)) != 0) {
         if (verbose != 0) {
             mbedtls_printf("  CCM: setup failed");
         }
diff --git a/library/ecp.c b/library/ecp.c
index a029c2206..9051490b1 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -163,7 +163,8 @@ static int ecp_drbg_seed(ecp_drbg_context *ctx,
     int ret;
     unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
     /* The list starts with strong hashes */
-    const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
+    const mbedtls_md_type_t md_type =
+        (const mbedtls_md_type_t) (mbedtls_md_list()[0]);
     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
 
     if (secret_len > MBEDTLS_ECP_MAX_BYTES) {
@@ -2062,12 +2063,13 @@ static int ecp_mul_comb_core(const mbedtls_ecp_group 
*grp, mbedtls_ecp_point *R,
     } else
 #endif
     {
+        int have_rng = 1;
+
         /* Start with a non-zero point and randomize its coordinates */
         i = d;
         MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i]));
         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 1));
 
-        int have_rng = 1;
 #if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
         if (f_rng == NULL) {
             have_rng = 0;
@@ -2172,6 +2174,7 @@ static int ecp_mul_comb_after_precomp(const 
mbedtls_ecp_group *grp,
     unsigned char parity_trick;
     unsigned char k[COMB_MAX_D + 1];
     mbedtls_ecp_point *RR = R;
+    int have_rng = 1;
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
@@ -2208,7 +2211,6 @@ final_norm:
      *
      * Avoid the leak by randomizing coordinates before we normalize them.
      */
-    int have_rng = 1;
 #if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
     if (f_rng == NULL) {
         have_rng = 0;
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 8a9f79e2e..6ce4f64c1 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -533,7 +533,7 @@ static const mbedtls_mpi_uint brainpoolP512r1_n[] = {
 #if defined(ECP_LOAD_GROUP)
 /*
  * Create an MPI from embedded constants
- * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint)
+ * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint))
  */
 static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, 
size_t len)
 {
@@ -1252,7 +1252,7 @@ static int ecp_mod_p255(mbedtls_mpi *N)
         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
     M.p = Mp;
-    memset(Mp, 0, sizeof Mp);
+    memset(Mp, 0, sizeof(Mp));
     memcpy(Mp, N->p + P255_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint));
     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 255 % (8 * 
sizeof(mbedtls_mpi_uint))));
     M.n++; /* Make room for multiplication by 19 */
@@ -1386,7 +1386,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, 
mbedtls_mpi_uint *Rp, size_t p
     if (M.n > p_limbs + adjust) {
         M.n = p_limbs + adjust;
     }
-    memset(Mp, 0, sizeof Mp);
+    memset(Mp, 0, sizeof(Mp));
     memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
     if (shift != 0) {
         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));
@@ -1412,7 +1412,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, 
mbedtls_mpi_uint *Rp, size_t p
     if (M.n > p_limbs + adjust) {
         M.n = p_limbs + adjust;
     }
-    memset(Mp, 0, sizeof Mp);
+    memset(Mp, 0, sizeof(Mp));
     memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
     if (shift != 0) {
         MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));
diff --git a/library/entropy.c b/library/entropy.c
index 1a4ac9645..af78acc1b 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -706,7 +706,7 @@ int mbedtls_entropy_self_test(int verbose)
         goto cleanup;
     }
 
-    if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof buf)) != 0) {
+    if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
         goto cleanup;
     }
 
diff --git a/library/oid.c b/library/oid.c
index fcff15273..4ec752fb9 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -796,21 +796,55 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size,
     p = buf;
     n = size;
 
-    /* First byte contains first two dots */
-    if (oid->len > 0) {
-        ret = mbedtls_snprintf(p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40);
-        OID_SAFE_SNPRINTF;
+    /* First subidentifier contains first two OID components */
+    i = 0;
+    value = 0;
+    if ((oid->p[0]) == 0x80) {
+        /* Overlong encoding is not allowed */
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+
+    while (i < oid->len && ((oid->p[i] & 0x80) != 0)) {
+        /* Prevent overflow in value. */
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+
+        value |= oid->p[i] & 0x7F;
+        value <<= 7;
+        i++;
+    }
+    if (i >= oid->len) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     }
+    /* Last byte of first subidentifier */
+    value |= oid->p[i] & 0x7F;
+    i++;
+
+    unsigned int component1 = value / 40;
+    if (component1 > 2) {
+        /* The first component can only be 0, 1 or 2.
+         * If oid->p[0] / 40 is greater than 2, the leftover belongs to
+         * the second component. */
+        component1 = 2;
+    }
+    unsigned int component2 = value - (40 * component1);
+    ret = mbedtls_snprintf(p, n, "%u.%u", component1, component2);
+    OID_SAFE_SNPRINTF;
 
     value = 0;
-    for (i = 1; i < oid->len; i++) {
+    for (; i < oid->len; i++) {
         /* Prevent overflow in value. */
-        if (((value << 7) >> 7) != value) {
-            return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        if ((value == 0) && ((oid->p[i]) == 0x80)) {
+            /* Overlong encoding is not allowed */
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
         }
 
         value <<= 7;
-        value += oid->p[i] & 0x7F;
+        value |= oid->p[i] & 0x7F;
 
         if (!(oid->p[i] & 0x80)) {
             /* Last byte */
diff --git a/library/psa_crypto_driver_wrappers.c 
b/library/psa_crypto_driver_wrappers.c
index 48ad6d5fb..615638533 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -1060,8 +1060,9 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
             }
 
             return status;
-#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+#else /* MBEDTLS_PSA_BUILTIN_CIPHER */
             return PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
 
             /* Add cases for opaque driver here */
 #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
diff --git a/library/ripemd160.c b/library/ripemd160.c
index f5dc5f59e..a2e11cdf0 100644
--- a/library/ripemd160.c
+++ b/library/ripemd160.c
@@ -496,7 +496,7 @@ int mbedtls_ripemd160_self_test(int verbose)
     int i, ret = 0;
     unsigned char output[20];
 
-    memset(output, 0, sizeof output);
+    memset(output, 0, sizeof(output));
 
     for (i = 0; i < TESTS; i++) {
         if (verbose != 0) {
diff --git a/library/timing.c b/library/timing.c
index d4f9554ee..47e34f922 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -352,9 +352,9 @@ int mbedtls_timing_get_delay(void *data)
     return 0;
 }
 
+#endif /* !MBEDTLS_TIMING_ALT */
 
 #if defined(MBEDTLS_SELF_TEST)
-
 /*
  * Busy-waits for the given number of milliseconds.
  * Used for testing mbedtls_timing_hardclock.
@@ -383,9 +383,8 @@ static void busy_msleep(unsigned long msec)
             mbedtls_printf(" cycles=%lu ratio=%lu millisecs=%lu secs=%lu 
hardfail=%d a=%lu b=%lu\n", \
                            cycles, ratio, millisecs, secs, hardfail,   \
                            (unsigned long) a, (unsigned long) b);     \
-            mbedtls_printf(" elapsed(hires)=%lu elapsed(ctx)=%lu 
status(ctx)=%d\n", \
+            mbedtls_printf(" elapsed(hires)=%lu status(ctx)=%d\n", \
                            mbedtls_timing_get_timer(&hires, 0),      \
-                           mbedtls_timing_get_timer(&ctx.timer, 0),  \
                            mbedtls_timing_get_delay(&ctx));         \
         }                                                               \
         return 1;                                                    \
@@ -526,5 +525,4 @@ hard_test_done:
 }
 
 #endif /* MBEDTLS_SELF_TEST */
-#endif /* !MBEDTLS_TIMING_ALT */
 #endif /* MBEDTLS_TIMING_C */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 9ea96b0aa..e7fcaf462 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -639,8 +639,6 @@ static int x509_get_subject_alt_name(unsigned char **p,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len, tag_len;
-    mbedtls_asn1_buf *buf;
-    unsigned char tag;
     mbedtls_asn1_sequence *cur = subject_alt_name;
 
     /* Get main sequence tag */
@@ -656,15 +654,20 @@ static int x509_get_subject_alt_name(unsigned char **p,
 
     while (*p < end) {
         mbedtls_x509_subject_alternative_name dummy_san_buf;
+        mbedtls_x509_buf tmp_san_buf;
         memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
 
-        tag = **p;
+        tmp_san_buf.tag = **p;
         (*p)++;
+
         if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
         }
 
-        if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
+        tmp_san_buf.p = *p;
+        tmp_san_buf.len = tag_len;
+
+        if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
             MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
                                      MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
@@ -673,7 +676,7 @@ static int x509_get_subject_alt_name(unsigned char **p,
         /*
          * Check that the SAN is structured correctly.
          */
-        ret = mbedtls_x509_parse_subject_alt_name(&(cur->buf), &dummy_san_buf);
+        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, 
&dummy_san_buf);
         /*
          * In case the extension is malformed, return an error,
          * and clear the allocated sequences.
@@ -708,11 +711,8 @@ static int x509_get_subject_alt_name(unsigned char **p,
             cur = cur->next;
         }
 
-        buf = &(cur->buf);
-        buf->tag = tag;
-        buf->p = *p;
-        buf->len = tag_len;
-        *p += buf->len;
+        cur->buf = tmp_san_buf;
+        *p += tmp_san_buf.len;
     }
 
     /* Set final sequence entry's next pointer to NULL */
@@ -1601,8 +1601,8 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, 
const char *path)
         }
 
         w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,
-                                    lstrlenW(file_data.cFileName),
-                                    p, (int) len - 1,
+                                    -1,
+                                    p, (int) len,
                                     NULL, NULL);
         if (w_ret == 0) {
             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
@@ -1645,10 +1645,10 @@ cleanup:
     memset(&sb, 0, sizeof(sb));
 
     while ((entry = readdir(dir)) != NULL) {
-        snp_ret = mbedtls_snprintf(entry_name, sizeof entry_name,
+        snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name),
                                    "%s/%s", path, entry->d_name);
 
-        if (snp_ret < 0 || (size_t) snp_ret >= sizeof entry_name) {
+        if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) {
             ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
             goto cleanup;
         } else if (stat(entry_name, &sb) == -1) {
@@ -1742,11 +1742,6 @@ static int x509_get_other_name(const mbedtls_x509_buf 
*subject_alt_name,
         return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
     }
 
-    if (p + len >= end) {
-        mbedtls_platform_zeroize(other_name, sizeof(*other_name));
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
     p += len;
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
                                     MBEDTLS_ASN1_CONSTRUCTED | 
MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
@@ -1754,11 +1749,21 @@ static int x509_get_other_name(const mbedtls_x509_buf 
*subject_alt_name,
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
+    if (end != p + len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
                                     MBEDTLS_ASN1_CONSTRUCTED | 
MBEDTLS_ASN1_SEQUENCE)) != 0) {
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
+    if (end != p + len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
@@ -1767,11 +1772,6 @@ static int x509_get_other_name(const mbedtls_x509_buf 
*subject_alt_name,
     other_name->value.hardware_module_name.oid.p = p;
     other_name->value.hardware_module_name.oid.len = len;
 
-    if (p + len >= end) {
-        mbedtls_platform_zeroize(other_name, sizeof(*other_name));
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
     p += len;
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
                                     MBEDTLS_ASN1_OCTET_STRING)) != 0) {
@@ -1783,8 +1783,6 @@ static int x509_get_other_name(const mbedtls_x509_buf 
*subject_alt_name,
     other_name->value.hardware_module_name.val.len = len;
     p += len;
     if (p != end) {
-        mbedtls_platform_zeroize(other_name,
-                                 sizeof(*other_name));
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
diff --git a/include/mbedtls/aesni.h b/include/mbedtls/aesni.h
index 653b146e7..6741dead0 100644
--- a/include/mbedtls/aesni.h
+++ b/include/mbedtls/aesni.h
@@ -36,13 +36,49 @@
 #define MBEDTLS_AESNI_AES      0x02000000u
 #define MBEDTLS_AESNI_CLMUL    0x00000002u
 
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) &&  \
+/* Can we do AESNI with inline assembly?
+ * (Only implemented with gas syntax, only for 64-bit.)
+ */
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
     (defined(__amd64__) || defined(__x86_64__))   &&  \
     !defined(MBEDTLS_HAVE_X86_64)
 #define MBEDTLS_HAVE_X86_64
 #endif
 
+#if defined(MBEDTLS_AESNI_C)
+
+/* Can we do AESNI with intrinsics?
+ * (Only implemented with certain compilers, only for certain targets.)
+ *
+ * NOTE: MBEDTLS_AESNI_HAVE_INTRINSICS and MBEDTLS_AESNI_HAVE_CODE are internal
+ *       macros that may change in future releases.
+ */
+#undef MBEDTLS_AESNI_HAVE_INTRINSICS
+#if defined(_MSC_VER)
+/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
+ * VS 2013 and up for other reasons anyway, so no need to check the version. */
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+/* GCC-like compilers: currently, we only support intrinsics if the requisite
+ * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
+ * or `clang -maes -mpclmul`). */
+#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__)
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+
+/* Choose the implementation of AESNI, if one is available. */
+#undef MBEDTLS_AESNI_HAVE_CODE
+/* To minimize disruption when releasing the intrinsics-based implementation,
+ * favor the assembly-based implementation if it's available. We intend to
+ * revise this in a later release of Mbed TLS 3.x. In the long run, we will
+ * likely remove the assembly implementation. */
 #if defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
+#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
+#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
 
 #ifdef __cplusplus
 extern "C" {
@@ -131,6 +167,7 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk,
 }
 #endif
 
-#endif /* MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
+#endif  /* MBEDTLS_AESNI_C */
 
 #endif /* MBEDTLS_AESNI_H */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 2ab99823e..2cb36e9e1 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -69,10 +69,6 @@
 #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
 #endif
 
-#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM)
-#error "MBEDTLS_AESNI_C defined, but not all prerequisites"
-#endif
-
 #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
 #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 1e4d95e0c..1381c1fd1 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -51,7 +51,7 @@
  *      include/mbedtls/bn_mul.h
  *
  * Required by:
- *      MBEDTLS_AESNI_C
+ *      MBEDTLS_AESNI_C (on some platforms)
  *      MBEDTLS_PADLOCK_C
  *
  * Comment to disable the use of assembly code.
@@ -871,7 +871,7 @@
  * - Changes the behaviour of TLS 1.2 clients (not servers) when using the
  *   ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC
  *   computations restartable:
- *   - ECDH operations from the key exchange, only for Short Weierstass
+ *   - ECDH operations from the key exchange, only for Short Weierstrass
  *     curves;
  *   - verification of the server's key exchange signature;
  *   - verification of the server's certificate chain;
@@ -2344,14 +2344,32 @@
 /**
  * \def MBEDTLS_AESNI_C
  *
- * Enable AES-NI support on x86-64.
+ * Enable AES-NI support on x86-64 or x86-32.
+ *
+ * \note AESNI is only supported with certain compilers and target options:
+ * - Visual Studio 2013: supported.
+ * - GCC, x86-64, target not explicitly supporting AESNI:
+ *   requires MBEDTLS_HAVE_ASM.
+ * - GCC, x86-32, target not explicitly supporting AESNI:
+ *   not supported.
+ * - GCC, x86-64 or x86-32, target supporting AESNI: supported.
+ *   For this assembly-less implementation, you must currently compile
+ *   `library/aesni.c` and `library/aes.c` with machine options to enable
+ *   SSE2 and AESNI instructions: `gcc -msse2 -maes -mpclmul` or
+ *   `clang -maes -mpclmul`.
+ * - Non-x86 targets: this option is silently ignored.
+ * - Other compilers: this option is silently ignored.
+ *
+ * \note
+ * Above, "GCC" includes compatible compilers such as Clang.
+ * The limitations on target support are likely to be relaxed in the future.
  *
  * Module:  library/aesni.c
  * Caller:  library/aes.c
  *
- * Requires: MBEDTLS_HAVE_ASM
+ * Requires: MBEDTLS_HAVE_ASM (on some platforms, see note)
  *
- * This modules adds support for the AES-NI instructions on x86-64
+ * This modules adds support for the AES-NI instructions on x86.
  */
 #define MBEDTLS_AESNI_C
 
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index a226e7173..ec8355136 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -402,6 +402,11 @@ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, 
mbedtls_pk_type_t type);
  *                  Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... )
  *                  to verify RSASSA_PSS signatures.
  *
+ * \note            If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                  subsystem must have been initialized by calling
+ *                  psa_crypto_init() before calling this function,
+ *                  if the key might be an ECC (ECDSA) key.
+ *
  * \note            If hash_len is 0, then the length associated with md_alg
  *                  is used instead, or an error returned if it is invalid.
  *
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 7836ecec6..26e4ec400 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1544,6 +1544,10 @@ void mbedtls_ssl_init(mbedtls_ssl_context *ssl);
  *                 Calling mbedtls_ssl_setup again is not supported, even
  *                 if no session is active.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param ssl      SSL context
  * \param conf     SSL configuration to use
  *
@@ -3980,6 +3984,10 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context 
*ssl, mbedtls_ssl_session
  *                 in which case the datagram of the underlying transport that 
is
  *                 currently being processed might or might not contain further
  *                 DTLS records.
+ *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
  */
 int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl);
 
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index 1324eaebe..0ef52138f 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -38,16 +38,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  28
-#define MBEDTLS_VERSION_PATCH  2
+#define MBEDTLS_VERSION_PATCH  3
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x021C0200
-#define MBEDTLS_VERSION_STRING         "2.28.2"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.28.2"
+#define MBEDTLS_VERSION_NUMBER         0x021C0300
+#define MBEDTLS_VERSION_STRING         "2.28.3"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.28.3"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/include/mbedtls/x509_crl.h b/include/mbedtls/x509_crl.h
index 895eca0d6..140502140 100644
--- a/include/mbedtls/x509_crl.h
+++ b/include/mbedtls/x509_crl.h
@@ -95,6 +95,10 @@ mbedtls_x509_crl;
 /**
  * \brief          Parse a DER-encoded CRL and append it to the chained list
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    points to the start of the chain
  * \param buf      buffer holding the CRL data in DER format
  * \param buflen   size of the buffer
@@ -109,6 +113,10 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,
  *
  * \note           Multiple CRLs are accepted only if using PEM format
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    points to the start of the chain
  * \param buf      buffer holding the CRL data in PEM or DER format
  * \param buflen   size of the buffer
@@ -124,6 +132,10 @@ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const 
unsigned char *buf, si
  *
  * \note           Multiple CRLs are accepted only if using PEM format
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    points to the start of the chain
  * \param path     filename to read the CRLs from (in PEM or DER encoding)
  *
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 235e00c06..466611f79 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -283,6 +283,10 @@ extern const mbedtls_x509_crt_profile 
mbedtls_x509_crt_profile_suiteb;
  * \brief          Parse a single DER formatted certificate and add it
  *                 to the end of the provided chained list.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    The pointer to the start of the CRT chain to attach to.
  *                 When parsing the first CRT in a chain, this should point
  *                 to an instance of ::mbedtls_x509_crt initialized through
@@ -344,6 +348,10 @@ typedef int (*mbedtls_x509_crt_ext_cb_t)(void *p_ctx,
  * \brief            Parse a single DER formatted certificate and add it
  *                   to the end of the provided chained list.
  *
+ * \note             If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                   subsystem must have been initialized by calling
+ *                   psa_crypto_init() before calling this function.
+ *
  * \param chain      The pointer to the start of the CRT chain to attach to.
  *                   When parsing the first CRT in a chain, this should point
  *                   to an instance of ::mbedtls_x509_crt initialized through
@@ -394,6 +402,10 @@ int 
mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain,
  *                 temporary ownership of the CRT buffer until the CRT
  *                 is destroyed.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    The pointer to the start of the CRT chain to attach to.
  *                 When parsing the first CRT in a chain, this should point
  *                 to an instance of ::mbedtls_x509_crt initialized through
@@ -434,6 +446,10 @@ int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt 
*chain,
  *                 long as the certificates are enclosed in the PEM specific
  *                 '-----{BEGIN/END} CERTIFICATE-----' delimiters.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    The chain to which to add the parsed certificates.
  * \param buf      The buffer holding the certificate data in PEM or DER 
format.
  *                 For certificates in PEM encoding, this may be a 
concatenation
@@ -458,6 +474,10 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const 
unsigned char *buf, si
  *                 of failed certificates it encountered. If none complete
  *                 correctly, the first error is returned.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param chain    points to the start of the chain
  * \param path     filename to read the certificates from
  *
diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h
index fa7ef04a2..5975584da 100644
--- a/include/mbedtls/x509_csr.h
+++ b/include/mbedtls/x509_csr.h
@@ -82,6 +82,10 @@ mbedtls_x509write_csr;
  *
  * \note           CSR attributes (if any) are currently silently ignored.
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param csr      CSR context to fill
  * \param buf      buffer holding the CRL data
  * \param buflen   size of the buffer
@@ -96,6 +100,10 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
  *
  * \note           See notes for \c mbedtls_x509_csr_parse_der()
  *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
  * \param csr      CSR context to fill
  * \param buf      buffer holding the CRL data
  * \param buflen   size of the buffer
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index fd3a3e71c..553569ebd 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -204,15 +204,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
 if(USE_SHARED_MBEDTLS_LIBRARY)
     set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
-    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.2 
SOVERSION 7)
+    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.3 
SOVERSION 7)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
     add_library(${mbedx509_target} SHARED ${src_x509})
-    set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.2 
SOVERSION 1)
+    set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.3 
SOVERSION 1)
     target_link_libraries(${mbedx509_target} PUBLIC ${libs} 
${mbedcrypto_target})
 
     add_library(${mbedtls_target} SHARED ${src_tls})
-    set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.2 
SOVERSION 14)
+    set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.3 
SOVERSION 14)
     target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
 
diff --git a/library/aes.c b/library/aes.c
index bcdf3c782..f08a21f59 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -50,8 +50,7 @@
 #define AES_VALIDATE(cond)        \
     MBEDTLS_INTERNAL_VALIDATE(cond)
 
-#if defined(MBEDTLS_PADLOCK_C) &&                      \
-    (defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16))
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
 static int aes_padlock_ace = -1;
 #endif
 
@@ -512,6 +511,53 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
+/* Some implementations need the round keys to be aligned.
+ * Return an offset to be added to buf, such that (buf + offset) is
+ * correctly aligned.
+ * Note that the offset is in units of elements of buf, i.e. 32-bit words,
+ * i.e. an offset of 1 means 4 bytes and so on.
+ */
+#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) ||        \
+    (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
+#define MAY_NEED_TO_ALIGN
+#endif
+static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
+{
+#if defined(MAY_NEED_TO_ALIGN)
+    int align_16_bytes = 0;
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+    if (aes_padlock_ace == -1) {
+        aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
+    }
+    if (aes_padlock_ace) {
+        align_16_bytes = 1;
+    }
+#endif
+
+#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+        align_16_bytes = 1;
+    }
+#endif
+
+    if (align_16_bytes) {
+        /* These implementations needs 16-byte alignment
+         * for the round key array. */
+        unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4;
+        if (delta == 0) {
+            return 0;
+        } else {
+            return 4 - delta; // 16 bytes = 4 uint32_t
+        }
+    }
+#else /* MAY_NEED_TO_ALIGN */
+    (void) buf;
+#endif /* MAY_NEED_TO_ALIGN */
+
+    return 0;
+}
+
 /*
  * AES key schedule (encryption)
  */
@@ -539,18 +585,9 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const 
unsigned char *key,
     }
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
-    if (aes_padlock_ace == -1) {
-        aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
-    }
-
-    if (aes_padlock_ace) {
-        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf);
-    } else
-#endif
-    ctx->rk = RK = ctx->buf;
+    ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf);
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
         return mbedtls_aesni_setkey_enc((unsigned char *) ctx->rk, key, 
keybits);
     }
@@ -640,16 +677,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const 
unsigned char *key,
 
     mbedtls_aes_init(&cty);
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
-    if (aes_padlock_ace == -1) {
-        aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
-    }
-
-    if (aes_padlock_ace) {
-        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf);
-    } else
-#endif
-    ctx->rk = RK = ctx->buf;
+    ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf);
 
     /* Also checks keybits */
     if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) {
@@ -658,7 +686,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const 
unsigned char *key,
 
     ctx->nr = cty.nr;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
         mbedtls_aesni_inverse_key((unsigned char *) ctx->rk,
                                   (const unsigned char *) cty.rk, ctx->nr);
@@ -964,6 +992,30 @@ void mbedtls_aes_decrypt(mbedtls_aes_context *ctx,
 }
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
+#if defined(MAY_NEED_TO_ALIGN)
+/* VIA Padlock and our intrinsics-based implementation of AESNI require
+ * the round keys to be aligned on a 16-byte boundary. We take care of this
+ * before creating them, but the AES context may have moved (this can happen
+ * if the library is called from a language with managed memory), and in later
+ * calls it might have a different alignment with respect to 16-byte memory.
+ * So we may need to realign.
+ * NOTE: In the LTS branch, the context contains a pointer to within itself,
+ * so if it has been moved, things will probably go pear-shaped. We keep this
+ * code for compatibility with the development branch, in case of future 
changes.
+ */
+static void aes_maybe_realign(mbedtls_aes_context *ctx)
+{
+    unsigned current_offset = (unsigned) (ctx->rk - ctx->buf);
+    unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf);
+    if (new_offset != current_offset) {
+        memmove(ctx->buf + new_offset,     // new address
+                ctx->buf + current_offset, // current address
+                (ctx->nr + 1) * 16);       // number of round keys * bytes per 
rk
+        ctx->rk = ctx->buf + new_offset;
+    }
+}
+#endif
+
 /*
  * AES-ECB block encryption/decryption
  */
@@ -978,7 +1030,11 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
     AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT ||
                      mode == MBEDTLS_AES_DECRYPT);
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MAY_NEED_TO_ALIGN)
+    aes_maybe_realign(ctx);
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
         return mbedtls_aesni_crypt_ecb(ctx, mode, input, output);
     }
@@ -986,13 +1042,7 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
 
 #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
     if (aes_padlock_ace) {
-        if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) {
-            return 0;
-        }
-
-        // If padlock data misaligned, we just fall back to
-        // unaccelerated mode
-        //
+        return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
     }
 #endif
 
@@ -1785,6 +1835,32 @@ int mbedtls_aes_self_test(int verbose)
     memset(key, 0, 32);
     mbedtls_aes_init(&ctx);
 
+    if (verbose != 0) {
+#if defined(MBEDTLS_AES_ALT)
+        mbedtls_printf("  AES note: alternative implementation.\n");
+#else /* MBEDTLS_AES_ALT */
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
+            mbedtls_printf("  AES note: using VIA Padlock.\n");
+        } else
+#endif
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+            mbedtls_printf("  AES note: using AESNI via ");
+#if MBEDTLS_AESNI_HAVE_CODE == 1
+            mbedtls_printf("assembly");
+#elif MBEDTLS_AESNI_HAVE_CODE == 2
+            mbedtls_printf("intrinsics");
+#else
+            mbedtls_printf("(unknown)");
+#endif
+            mbedtls_printf(".\n");
+        } else
+#endif
+        mbedtls_printf("  AES note: built-in implementation.\n");
+#endif /* MBEDTLS_AES_ALT */
+    }
+
     /*
      * ECB mode
      */
diff --git a/library/aesni.c b/library/aesni.c
index 2a44b0ea3..c909f654c 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -18,21 +18,14 @@
  */
 
 /*
- * [AES-WP] 
http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
- * [CLMUL-WP] 
http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ * [AES-WP] 
https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html
+ * [CLMUL-WP] 
https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html
  */
 
 #include "common.h"
 
 #if defined(MBEDTLS_AESNI_C)
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#warning \
-    "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory 
sanitizers as they do not understand the assembly code."
-#endif
-#endif
-
 #include "mbedtls/aesni.h"
 
 #include <string.h>
@@ -43,7 +36,14 @@
 #endif
 /* *INDENT-ON* */
 
-#if defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+#if !defined(_WIN32)
+#include <cpuid.h>
+#endif
+#include <immintrin.h>
+#endif
 
 /*
  * AES-NI support detection routine
@@ -54,17 +54,355 @@ int mbedtls_aesni_has_support(unsigned int what)
     static unsigned int c = 0;
 
     if (!done) {
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+        static unsigned info[4] = { 0, 0, 0, 0 };
+#if defined(_MSC_VER)
+        __cpuid(info, 1);
+#else
+        __cpuid(1, info[0], info[1], info[2], info[3]);
+#endif
+        c = info[2];
+#else /* AESNI using asm */
         asm ("movl  $1, %%eax   \n\t"
              "cpuid             \n\t"
              : "=c" (c)
              :
              : "eax", "ebx", "edx");
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
         done = 1;
     }
 
     return (c & what) != 0;
 }
 
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16])
+{
+    const __m128i *rk = (const __m128i *) (ctx->rk);
+    unsigned nr = ctx->nr; // Number of remaining rounds
+
+    // Load round key 0
+    __m128i state;
+    memcpy(&state, input, 16);
+    state = _mm_xor_si128(state, rk[0]);  // state ^= *rk;
+    ++rk;
+    --nr;
+
+    if (mode == 0) {
+        while (nr != 0) {
+            state = _mm_aesdec_si128(state, *rk);
+            ++rk;
+            --nr;
+        }
+        state = _mm_aesdeclast_si128(state, *rk);
+    } else {
+        while (nr != 0) {
+            state = _mm_aesenc_si128(state, *rk);
+            ++rk;
+            --nr;
+        }
+        state = _mm_aesenclast_si128(state, *rk);
+    }
+
+    memcpy(output, &state, 16);
+    return 0;
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+
+static void gcm_clmul(const __m128i aa, const __m128i bb,
+                      __m128i *cc, __m128i *dd)
+{
+    /*
+     * Caryless multiplication dd:cc = aa * bb
+     * using [CLMUL-WP] algorithm 1 (p. 12).
+     */
+    *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0
+    *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0
+    __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0
+    __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0
+    ff = _mm_xor_si128(ff, ee);                      // e1+f1:e0+f0
+    ee = ff;                                         // e1+f1:e0+f0
+    ff = _mm_srli_si128(ff, 8);                      // 0:e1+f1
+    ee = _mm_slli_si128(ee, 8);                      // e0+f0:0
+    *dd = _mm_xor_si128(*dd, ff);                    // d1:d0+e1+f1
+    *cc = _mm_xor_si128(*cc, ee);                    // c1+e0+f0:c0
+}
+
+static void gcm_shift(__m128i *cc, __m128i *dd)
+{
+    /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left,
+     * taking advantage of [CLMUL-WP] eq 27 (p. 18). */
+    //                                        // *cc = r1:r0
+    //                                        // *dd = r3:r2
+    __m128i cc_lo = _mm_slli_epi64(*cc, 1);   // r1<<1:r0<<1
+    __m128i dd_lo = _mm_slli_epi64(*dd, 1);   // r3<<1:r2<<1
+    __m128i cc_hi = _mm_srli_epi64(*cc, 63);  // r1>>63:r0>>63
+    __m128i dd_hi = _mm_srli_epi64(*dd, 63);  // r3>>63:r2>>63
+    __m128i xmm5 = _mm_srli_si128(cc_hi, 8);  // 0:r1>>63
+    cc_hi = _mm_slli_si128(cc_hi, 8);         // r0>>63:0
+    dd_hi = _mm_slli_si128(dd_hi, 8);         // 0:r1>>63
+
+    *cc = _mm_or_si128(cc_lo, cc_hi);         // r1<<1|r0>>63:r0<<1
+    *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // 
r3<<1|r2>>62:r2<<1|r1>>63
+}
+
+static __m128i gcm_reduce(__m128i xx)
+{
+    //                                            // xx = x1:x0
+    /* [CLMUL-WP] Algorithm 5 Step 2 */
+    __m128i aa = _mm_slli_epi64(xx, 63);          // x1<<63:x0<<63 = stuff:a
+    __m128i bb = _mm_slli_epi64(xx, 62);          // x1<<62:x0<<62 = stuff:b
+    __m128i cc = _mm_slli_epi64(xx, 57);          // x1<<57:x0<<57 = stuff:c
+    __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); 
// a+b+c:0
+    return _mm_xor_si128(dd, xx);                 // x1+a+b+c:x0 = d:x0
+}
+
+static __m128i gcm_mix(__m128i dx)
+{
+    /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */
+    __m128i ee = _mm_srli_epi64(dx, 1);           // e1:x0>>1 = e1:e0'
+    __m128i ff = _mm_srli_epi64(dx, 2);           // f1:x0>>2 = f1:f0'
+    __m128i gg = _mm_srli_epi64(dx, 7);           // g1:x0>>7 = g1:g0'
+
+    // e0'+f0'+g0' is almost e0+f0+g0, except for some missing
+    // bits carried from d. Now get those bits back in.
+    __m128i eh = _mm_slli_epi64(dx, 63);          // d<<63:stuff
+    __m128i fh = _mm_slli_epi64(dx, 62);          // d<<62:stuff
+    __m128i gh = _mm_slli_epi64(dx, 57);          // d<<57:stuff
+    __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); 
// 0:missing bits of d
+
+    return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), 
gg), hh), dx);
+}
+
+void mbedtls_aesni_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16])
+{
+    __m128i aa, bb, cc, dd;
+
+    /* The inputs are in big-endian order, so byte-reverse them */
+    for (size_t i = 0; i < 16; i++) {
+        ((uint8_t *) &aa)[i] = a[15 - i];
+        ((uint8_t *) &bb)[i] = b[15 - i];
+    }
+
+    gcm_clmul(aa, bb, &cc, &dd);
+    gcm_shift(&cc, &dd);
+    /*
+     * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+     * using [CLMUL-WP] algorithm 5 (p. 18).
+     * Currently dd:cc holds x3:x2:x1:x0 (already shifted).
+     */
+    __m128i dx = gcm_reduce(cc);
+    __m128i xh = gcm_mix(dx);
+    cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0
+
+    /* Now byte-reverse the outputs */
+    for (size_t i = 0; i < 16; i++) {
+        c[i] = ((uint8_t *) &cc)[15 - i];
+    }
+
+    return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesni_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey, int nr)
+{
+    __m128i *ik = (__m128i *) invkey;
+    const __m128i *fk = (const __m128i *) fwdkey + nr;
+
+    *ik = *fk;
+    for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) {
+        *ik = _mm_aesimc_si128(*fk);
+    }
+    *ik = *fk;
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static __m128i aesni_set_rk_128(__m128i state, __m128i xword)
+{
+    /*
+     * Finish generating the next round key.
+     *
+     * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff
+     * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST).
+     *
+     * On exit, xword is r7:r6:r5:r4
+     * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+     * and this is returned, to be written to the round key buffer.
+     */
+    xword = _mm_shuffle_epi32(xword, 0xff);   // X:X:X:X
+    xword = _mm_xor_si128(xword, state);      // X+r3:X+r2:X+r1:r4
+    state = _mm_slli_si128(state, 4);         // r2:r1:r0:0
+    xword = _mm_xor_si128(xword, state);      // X+r3+r2:X+r2+r1:r5:r4
+    state = _mm_slli_si128(state, 4);         // r1:r0:0:0
+    xword = _mm_xor_si128(xword, state);      // X+r3+r2+r1:r6:r5:r4
+    state = _mm_slli_si128(state, 4);         // r0:0:0:0
+    state = _mm_xor_si128(xword, state);      // r7:r6:r5:r4
+    return state;
+}
+
+static void aesni_setkey_enc_128(unsigned char *rk_bytes,
+                                 const unsigned char *key)
+{
+    __m128i *rk = (__m128i *) rk_bytes;
+
+    memcpy(&rk[0], key, 16);
+    rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01));
+    rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02));
+    rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04));
+    rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08));
+    rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10));
+    rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20));
+    rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40));
+    rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80));
+    rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B));
+    rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36));
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
+                             unsigned char *rk)
+{
+    /*
+     * Finish generating the next 6 quarter-keys.
+     *
+     * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4
+     * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON
+     * (obtained with AESKEYGENASSIST).
+     *
+     * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10
+     * and those are written to the round key buffer.
+     */
+    xword = _mm_shuffle_epi32(xword, 0x55);   // X:X:X:X
+    xword = _mm_xor_si128(xword, *state0);    // X+r3:X+r2:X+r1:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r2:r1:r0:0
+    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2:X+r2+r1:X+r1+r0:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r1:r0:0:0
+    xword = _mm_xor_si128(xword, *state0);    // 
X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r0:0:0:0
+    xword = _mm_xor_si128(xword, *state0);    // 
X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0
+    *state0 = xword;                          // = r9:r8:r7:r6
+
+    xword = _mm_shuffle_epi32(xword, 0xff);   // r9:r9:r9:r9
+    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5:r9+r4
+    *state1 = _mm_slli_si128(*state1, 4);     // stuff:stuff:r4:0
+    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5+r4:r9+r4
+    *state1 = xword;                          // = stuff:stuff:r11:r10
+
+    /* Store state0 and the low half of state1 into rk, which is conceptually
+     * an array of 24-byte elements. Since 24 is not a multiple of 16,
+     * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */
+    memcpy(rk, state0, 16);
+    memcpy(rk + 16, state1, 8);
+}
+
+static void aesni_setkey_enc_192(unsigned char *rk,
+                                 const unsigned char *key)
+{
+    /* First round: use original key */
+    memcpy(rk, key, 24);
+    /* aes.c guarantees that rk is aligned on a 16-byte boundary. */
+    __m128i state0 = ((__m128i *) rk)[0];
+    __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1);
+
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x01), rk + 24 * 1);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x02), rk + 24 * 2);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x04), rk + 24 * 3);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x08), rk + 24 * 4);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x10), rk + 24 * 5);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x20), rk + 24 * 6);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x40), rk + 24 * 7);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 
0x80), rk + 24 * 8);
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
+                             __m128i *rk0, __m128i *rk1)
+{
+    /*
+     * Finish generating the next two round keys.
+     *
+     * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and
+     * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+     * (obtained with AESKEYGENASSIST).
+     *
+     * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12
+     */
+    xword = _mm_shuffle_epi32(xword, 0xff);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    state0 = _mm_xor_si128(state0, xword);
+    *rk0 = state0;
+
+    /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 )
+     * and proceed to generate next round key from there */
+    xword = _mm_aeskeygenassist_si128(state0, 0x00);
+    xword = _mm_shuffle_epi32(xword, 0xaa);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    state1 = _mm_xor_si128(state1, xword);
+    *rk1 = state1;
+}
+
+static void aesni_setkey_enc_256(unsigned char *rk_bytes,
+                                 const unsigned char *key)
+{
+    __m128i *rk = (__m128i *) rk_bytes;
+
+    memcpy(&rk[0], key, 16);
+    memcpy(&rk[1], key + 16, 16);
+
+    /*
+     * Main "loop" - Generating one more key than necessary,
+     * see definition of mbedtls_aes_context.buf
+     */
+    aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), 
&rk[2], &rk[3]);
+    aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), 
&rk[4], &rk[5]);
+    aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), 
&rk[6], &rk[7]);
+    aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), 
&rk[8], &rk[9]);
+    aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), 
&rk[10], &rk[11]);
+    aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), 
&rk[12], &rk[13]);
+    aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), 
&rk[14], &rk[15]);
+}
+
+#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#warning \
+    "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory 
sanitizers as they do not understand the assembly code."
+#endif
+#endif
+
 /*
  * Binutils needs to be at least 2.19 to support AES-NI instructions.
  * Unfortunately, a lot of users have a lower version now (2014-04).
@@ -75,13 +413,13 @@ int mbedtls_aesni_has_support(unsigned int what)
  * Operand macros are in gas order (src, dst) as opposed to Intel order
  * (dst, src) in order to blend better into the surrounding assembly code.
  */
-#define AESDEC      ".byte 0x66,0x0F,0x38,0xDE,"
-#define AESDECLAST  ".byte 0x66,0x0F,0x38,0xDF,"
-#define AESENC      ".byte 0x66,0x0F,0x38,0xDC,"
-#define AESENCLAST  ".byte 0x66,0x0F,0x38,0xDD,"
-#define AESIMC      ".byte 0x66,0x0F,0x38,0xDB,"
-#define AESKEYGENA  ".byte 0x66,0x0F,0x3A,0xDF,"
-#define PCLMULQDQ   ".byte 0x66,0x0F,0x3A,0x44,"
+#define AESDEC(regs)      ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t"
+#define AESDECLAST(regs)  ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t"
+#define AESENC(regs)      ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t"
+#define AESENCLAST(regs)  ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t"
+#define AESIMC(regs)      ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t"
+#define AESKEYGENA(regs, imm)  ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t"
+#define PCLMULQDQ(regs, imm)   ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t"
 
 #define xmm0_xmm0   "0xC0"
 #define xmm0_xmm1   "0xC8"
@@ -109,25 +447,25 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
 
          "1:                        \n\t" // encryption loop
          "movdqu    (%1), %%xmm1    \n\t" // load round key
-         AESENC     xmm1_xmm0      "\n\t" // do round
-                                   "add       $16, %1         \n\t" // point 
to next round key
-                                   "subl      $1, %0          \n\t" // loop
-                                   "jnz       1b              \n\t"
-                                   "movdqu    (%1), %%xmm1    \n\t" // load 
round key
-         AESENCLAST xmm1_xmm0      "\n\t" // last round
-                                   "jmp       3f              \n\t"
-
-                                   "2:                        \n\t" // 
decryption loop
-                                   "movdqu    (%1), %%xmm1    \n\t"
-         AESDEC     xmm1_xmm0      "\n\t" // do round
-                                   "add       $16, %1         \n\t"
-                                   "subl      $1, %0          \n\t"
-                                   "jnz       2b              \n\t"
-                                   "movdqu    (%1), %%xmm1    \n\t" // load 
round key
-         AESDECLAST xmm1_xmm0      "\n\t" // last round
-
-                                   "3:                        \n\t"
-                                   "movdqu    %%xmm0, (%4)    \n\t" // export 
output
+         AESENC(xmm1_xmm0)                // do round
+         "add       $16, %1         \n\t" // point to next round key
+         "subl      $1, %0          \n\t" // loop
+         "jnz       1b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENCLAST(xmm1_xmm0)            // last round
+         "jmp       3f              \n\t"
+
+         "2:                        \n\t" // decryption loop
+         "movdqu    (%1), %%xmm1    \n\t"
+         AESDEC(xmm1_xmm0)                // do round
+         "add       $16, %1         \n\t"
+         "subl      $1, %0          \n\t"
+         "jnz       2b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESDECLAST(xmm1_xmm0)            // last round
+
+         "3:                        \n\t"
+         "movdqu    %%xmm0, (%4)    \n\t" // export output
          :
          : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
          : "memory", "cc", "xmm0", "xmm1");
@@ -158,84 +496,84 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
 
          /*
           * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
-          * using [CLMUL-WP] algorithm 1 (p. 13).
+          * using [CLMUL-WP] algorithm 1 (p. 12).
           */
          "movdqa %%xmm1, %%xmm2             \n\t" // copy of b1:b0
          "movdqa %%xmm1, %%xmm3             \n\t" // same
          "movdqa %%xmm1, %%xmm4             \n\t" // same
-         PCLMULQDQ xmm0_xmm1 ",0x00         \n\t" // a0*b0 = c1:c0
-         PCLMULQDQ xmm0_xmm2 ",0x11         \n\t" // a1*b1 = d1:d0
-         PCLMULQDQ xmm0_xmm3 ",0x10         \n\t" // a0*b1 = e1:e0
-         PCLMULQDQ xmm0_xmm4 ",0x01         \n\t" // a1*b0 = f1:f0
-                             "pxor %%xmm3, %%xmm4               \n\t" // 
e1+f1:e0+f0
-                             "movdqa %%xmm4, %%xmm3             \n\t" // same
-                             "psrldq $8, %%xmm4                 \n\t" // 
0:e1+f1
-                             "pslldq $8, %%xmm3                 \n\t" // 
e0+f0:0
-                             "pxor %%xmm4, %%xmm2               \n\t" // 
d1:d0+e1+f1
-                             "pxor %%xmm3, %%xmm1               \n\t" // 
c1+e0+f1:c0
+         PCLMULQDQ(xmm0_xmm1, "0x00")             // a0*b0 = c1:c0
+         PCLMULQDQ(xmm0_xmm2, "0x11")             // a1*b1 = d1:d0
+         PCLMULQDQ(xmm0_xmm3, "0x10")             // a0*b1 = e1:e0
+         PCLMULQDQ(xmm0_xmm4, "0x01")             // a1*b0 = f1:f0
+         "pxor %%xmm3, %%xmm4               \n\t" // e1+f1:e0+f0
+         "movdqa %%xmm4, %%xmm3             \n\t" // same
+         "psrldq $8, %%xmm4                 \n\t" // 0:e1+f1
+         "pslldq $8, %%xmm3                 \n\t" // e0+f0:0
+         "pxor %%xmm4, %%xmm2               \n\t" // d1:d0+e1+f1
+         "pxor %%xmm3, %%xmm1               \n\t" // c1+e0+f1:c0
 
          /*
           * Now shift the result one bit to the left,
-          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          * taking advantage of [CLMUL-WP] eq 27 (p. 18)
           */
-                             "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
-                             "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
-                             "psllq $1, %%xmm1                  \n\t" // 
r1<<1:r0<<1
-                             "psllq $1, %%xmm2                  \n\t" // 
r3<<1:r2<<1
-                             "psrlq $63, %%xmm3                 \n\t" // 
r1>>63:r0>>63
-                             "psrlq $63, %%xmm4                 \n\t" // 
r3>>63:r2>>63
-                             "movdqa %%xmm3, %%xmm5             \n\t" // 
r1>>63:r0>>63
-                             "pslldq $8, %%xmm3                 \n\t" // 
r0>>63:0
-                             "pslldq $8, %%xmm4                 \n\t" // 
r2>>63:0
-                             "psrldq $8, %%xmm5                 \n\t" // 
0:r1>>63
-                             "por %%xmm3, %%xmm1                \n\t" // 
r1<<1|r0>>63:r0<<1
-                             "por %%xmm4, %%xmm2                \n\t" // 
r3<<1|r2>>62:r2<<1
-                             "por %%xmm5, %%xmm2                \n\t" // 
r3<<1|r2>>62:r2<<1|r1>>63
+         "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
+         "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
+         "psllq $1, %%xmm1                  \n\t" // r1<<1:r0<<1
+         "psllq $1, %%xmm2                  \n\t" // r3<<1:r2<<1
+         "psrlq $63, %%xmm3                 \n\t" // r1>>63:r0>>63
+         "psrlq $63, %%xmm4                 \n\t" // r3>>63:r2>>63
+         "movdqa %%xmm3, %%xmm5             \n\t" // r1>>63:r0>>63
+         "pslldq $8, %%xmm3                 \n\t" // r0>>63:0
+         "pslldq $8, %%xmm4                 \n\t" // r2>>63:0
+         "psrldq $8, %%xmm5                 \n\t" // 0:r1>>63
+         "por %%xmm3, %%xmm1                \n\t" // r1<<1|r0>>63:r0<<1
+         "por %%xmm4, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1
+         "por %%xmm5, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
 
          /*
           * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
-          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * using [CLMUL-WP] algorithm 5 (p. 18).
           * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
           */
          /* Step 2 (1) */
-                             "movdqa %%xmm1, %%xmm3             \n\t" // x1:x0
-                             "movdqa %%xmm1, %%xmm4             \n\t" // same
-                             "movdqa %%xmm1, %%xmm5             \n\t" // same
-                             "psllq $63, %%xmm3                 \n\t" // 
x1<<63:x0<<63 = stuff:a
-                             "psllq $62, %%xmm4                 \n\t" // 
x1<<62:x0<<62 = stuff:b
-                             "psllq $57, %%xmm5                 \n\t" // 
x1<<57:x0<<57 = stuff:c
+         "movdqa %%xmm1, %%xmm3             \n\t" // x1:x0
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         "movdqa %%xmm1, %%xmm5             \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // x1<<63:x0<<63 = stuff:a
+         "psllq $62, %%xmm4                 \n\t" // x1<<62:x0<<62 = stuff:b
+         "psllq $57, %%xmm5                 \n\t" // x1<<57:x0<<57 = stuff:c
 
          /* Step 2 (2) */
-                             "pxor %%xmm4, %%xmm3               \n\t" // 
stuff:a+b
-                             "pxor %%xmm5, %%xmm3               \n\t" // 
stuff:a+b+c
-                             "pslldq $8, %%xmm3                 \n\t" // 
a+b+c:0
-                             "pxor %%xmm3, %%xmm1               \n\t" // 
x1+a+b+c:x0 = d:x0
+         "pxor %%xmm4, %%xmm3               \n\t" // stuff:a+b
+         "pxor %%xmm5, %%xmm3               \n\t" // stuff:a+b+c
+         "pslldq $8, %%xmm3                 \n\t" // a+b+c:0
+         "pxor %%xmm3, %%xmm1               \n\t" // x1+a+b+c:x0 = d:x0
 
          /* Steps 3 and 4 */
-                             "movdqa %%xmm1,%%xmm0              \n\t" // d:x0
-                             "movdqa %%xmm1,%%xmm4              \n\t" // same
-                             "movdqa %%xmm1,%%xmm5              \n\t" // same
-                             "psrlq $1, %%xmm0                  \n\t" // 
e1:x0>>1 = e1:e0'
-                             "psrlq $2, %%xmm4                  \n\t" // 
f1:x0>>2 = f1:f0'
-                             "psrlq $7, %%xmm5                  \n\t" // 
g1:x0>>7 = g1:g0'
-                             "pxor %%xmm4, %%xmm0               \n\t" // 
e1+f1:e0'+f0'
-                             "pxor %%xmm5, %%xmm0               \n\t" // 
e1+f1+g1:e0'+f0'+g0'
+         "movdqa %%xmm1,%%xmm0              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psrlq $1, %%xmm0                  \n\t" // e1:x0>>1 = e1:e0'
+         "psrlq $2, %%xmm4                  \n\t" // f1:x0>>2 = f1:f0'
+         "psrlq $7, %%xmm5                  \n\t" // g1:x0>>7 = g1:g0'
+         "pxor %%xmm4, %%xmm0               \n\t" // e1+f1:e0'+f0'
+         "pxor %%xmm5, %%xmm0               \n\t" // e1+f1+g1:e0'+f0'+g0'
          // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
          // bits carried from d. Now get those\t bits back in.
-                             "movdqa %%xmm1,%%xmm3              \n\t" // d:x0
-                             "movdqa %%xmm1,%%xmm4              \n\t" // same
-                             "movdqa %%xmm1,%%xmm5              \n\t" // same
-                             "psllq $63, %%xmm3                 \n\t" // 
d<<63:stuff
-                             "psllq $62, %%xmm4                 \n\t" // 
d<<62:stuff
-                             "psllq $57, %%xmm5                 \n\t" // 
d<<57:stuff
-                             "pxor %%xmm4, %%xmm3               \n\t" // 
d<<63+d<<62:stuff
-                             "pxor %%xmm5, %%xmm3               \n\t" // 
missing bits of d:stuff
-                             "psrldq $8, %%xmm3                 \n\t" // 
0:missing bits of d
-                             "pxor %%xmm3, %%xmm0               \n\t" // 
e1+f1+g1:e0+f0+g0
-                             "pxor %%xmm1, %%xmm0               \n\t" // h1:h0
-                             "pxor %%xmm2, %%xmm0               \n\t" // 
x3+h1:x2+h0
-
-                             "movdqu %%xmm0, (%2)               \n\t" // done
+         "movdqa %%xmm1,%%xmm3              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // d<<63:stuff
+         "psllq $62, %%xmm4                 \n\t" // d<<62:stuff
+         "psllq $57, %%xmm5                 \n\t" // d<<57:stuff
+         "pxor %%xmm4, %%xmm3               \n\t" // d<<63+d<<62:stuff
+         "pxor %%xmm5, %%xmm3               \n\t" // missing bits of d:stuff
+         "psrldq $8, %%xmm3                 \n\t" // 0:missing bits of d
+         "pxor %%xmm3, %%xmm0               \n\t" // e1+f1+g1:e0+f0+g0
+         "pxor %%xmm1, %%xmm0               \n\t" // h1:h0
+         "pxor %%xmm2, %%xmm0               \n\t" // x3+h1:x2+h0
+
+         "movdqu %%xmm0, (%2)               \n\t" // done
          :
          : "r" (aa), "r" (bb), "r" (cc)
          : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
@@ -261,8 +599,8 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey,
 
     for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) {
         asm ("movdqu (%0), %%xmm0       \n\t"
-             AESIMC  xmm0_xmm0         "\n\t"
-                                       "movdqu %%xmm0, (%1)       \n\t"
+             AESIMC(xmm0_xmm0)
+             "movdqu %%xmm0, (%1)       \n\t"
              :
              : "r" (fk), "r" (ik)
              : "memory", "xmm0");
@@ -306,16 +644,16 @@ static void aesni_setkey_enc_128(unsigned char *rk,
 
          /* Main "loop" */
          "2:                                \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x01        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x02        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x04        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x08        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x10        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x20        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x40        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x80        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x1B        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x36        \n\tcall 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x01")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x02")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x04")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x08")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x10")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x20")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x40")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x80")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x1B")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x36")      "call 1b \n\t"
          :
          : "r" (rk), "r" (key)
          : "memory", "cc", "0");
@@ -364,14 +702,14 @@ static void aesni_setkey_enc_192(unsigned char *rk,
          "ret                           \n\t"
 
          "2:                            \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x01    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x02    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x04    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x08    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x10    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x20    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x40    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x80    \n\tcall 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x01")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x02")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x04")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x08")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x10")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x20")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x40")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x80")  "call 1b \n\t"
 
          :
          : "r" (rk), "r" (key)
@@ -414,36 +752,38 @@ static void aesni_setkey_enc_256(unsigned char *rk,
 
          /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
           * and proceed to generate next round key from there */
-         AESKEYGENA xmm0_xmm2 ",0x00        \n\t"
-                              "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
-                              "pxor %%xmm1, %%xmm2               \n\t"
-                              "pslldq $4, %%xmm1                 \n\t"
-                              "pxor %%xmm1, %%xmm2               \n\t"
-                              "pslldq $4, %%xmm1                 \n\t"
-                              "pxor %%xmm1, %%xmm2               \n\t"
-                              "pslldq $4, %%xmm1                 \n\t"
-                              "pxor %%xmm2, %%xmm1               \n\t"
-                              "add $16, %0                       \n\t"
-                              "movdqu %%xmm1, (%0)               \n\t"
-                              "ret                               \n\t"
+         AESKEYGENA(xmm0_xmm2, "0x00")
+         "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm2, %%xmm1               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm1, (%0)               \n\t"
+         "ret                               \n\t"
 
          /*
           * Main "loop" - Generating one more key than necessary,
           * see definition of mbedtls_aes_context.buf
           */
-                              "2:                                \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x01        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x02        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x04        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x08        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x10        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x20        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x40        \n\tcall 1b \n\t"
+         "2:                                \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x01")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x02")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x04")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x08")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x10")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x20")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x40")      "call 1b \n\t"
          :
          : "r" (rk), "r" (key)
          : "memory", "cc", "0");
 }
 
+#endif  /* MBEDTLS_AESNI_HAVE_CODE */
+
 /*
  * Key expansion, wrapper
  */
@@ -461,6 +801,6 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk,
     return 0;
 }
 
-#endif /* MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
 
 #endif /* MBEDTLS_AESNI_C */
diff --git a/library/common.h b/library/common.h
index 2786c97d4..e162aa3cf 100644
--- a/library/common.h
+++ b/library/common.h
@@ -29,6 +29,7 @@
 #include "mbedtls/config.h"
 #endif
 
+#include <assert.h>
 #include <stddef.h>
 #include <stdint.h>
 
@@ -347,4 +348,18 @@ static inline const unsigned char 
*mbedtls_buffer_offset_const(
     }
 #endif
 
+/* Always provide a static assert macro, so it can be used unconditionally.
+ * It will expand to nothing on some systems.
+ * Can be used outside functions (but don't add a trailing ';' in that case:
+ * the semicolon is included here to avoid triggering -Wextra-semi when
+ * MBEDTLS_STATIC_ASSERT() expands to nothing).
+ * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
+ * defines static_assert even with -std=c99, but then complains about it.
+ */
+#if defined(static_assert) && !defined(__FreeBSD__)
+#define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg);
+#else
+#define MBEDTLS_STATIC_ASSERT(expr, msg)
+#endif
+
 #endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/library/gcm.c b/library/gcm.c
index f7db0d42d..0c958c729 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -93,7 +93,7 @@ static int gcm_gen_table(mbedtls_gcm_context *ctx)
     ctx->HL[8] = vl;
     ctx->HH[8] = vh;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     /* With CLMUL support, we need only h, not the rest of the table */
     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
         return 0;
@@ -190,7 +190,7 @@ static void gcm_mult(mbedtls_gcm_context *ctx, const 
unsigned char x[16],
     unsigned char lo, hi, rem;
     uint64_t zh, zl;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
         unsigned char h[16];
 
@@ -202,7 +202,7 @@ static void gcm_mult(mbedtls_gcm_context *ctx, const 
unsigned char x[16],
         mbedtls_aesni_gcm_mult(output, x, h);
         return;
     }
-#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
 
     lo = x[15] & 0xf;
 
@@ -754,6 +754,27 @@ int mbedtls_gcm_self_test(int verbose)
     int i, j, ret;
     mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
 
+    if (verbose != 0) {
+#if defined(MBEDTLS_GCM_ALT)
+        mbedtls_printf("  GCM note: alternative implementation.\n");
+#else /* MBEDTLS_GCM_ALT */
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+            mbedtls_printf("  GCM note: using AESNI via ");
+#if MBEDTLS_AESNI_HAVE_CODE == 1
+            mbedtls_printf("assembly");
+#elif MBEDTLS_AESNI_HAVE_CODE == 2
+            mbedtls_printf("intrinsics");
+#else
+            mbedtls_printf("(unknown)");
+#endif
+            mbedtls_printf(".\n");
+        } else
+#endif
+        mbedtls_printf("  GCM note: built-in implementation.\n");
+#endif /* MBEDTLS_GCM_ALT */
+    }
+
     for (j = 0; j < 3; j++) {
         int key_len = 128 + 64 * j;
 
diff --git a/library/oid.c b/library/oid.c
index 4ec752fb9..12a96503b 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -775,65 +775,26 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg,
                  cipher_alg)
 #endif /* MBEDTLS_PKCS12_C */
 
-#define OID_SAFE_SNPRINTF                               \
-    do {                                                \
-        if (ret < 0 || (size_t) ret >= n)              \
-        return MBEDTLS_ERR_OID_BUF_TOO_SMALL;    \
-                                                      \
-        n -= (size_t) ret;                              \
-        p += (size_t) ret;                              \
-    } while (0)
-
 /* Return the x.y.z.... style numeric string for the given OID */
 int mbedtls_oid_get_numeric_string(char *buf, size_t size,
                                    const mbedtls_asn1_buf *oid)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, n;
-    unsigned int value;
-    char *p;
-
-    p = buf;
-    n = size;
-
-    /* First subidentifier contains first two OID components */
-    i = 0;
-    value = 0;
-    if ((oid->p[0]) == 0x80) {
-        /* Overlong encoding is not allowed */
-        return MBEDTLS_ERR_ASN1_INVALID_DATA;
-    }
-
-    while (i < oid->len && ((oid->p[i] & 0x80) != 0)) {
-        /* Prevent overflow in value. */
-        if (value > (UINT_MAX >> 7)) {
-            return MBEDTLS_ERR_ASN1_INVALID_DATA;
-        }
+    char *p = buf;
+    size_t n = size;
+    unsigned int value = 0;
 
-        value |= oid->p[i] & 0x7F;
-        value <<= 7;
-        i++;
+    if (size > INT_MAX) {
+        /* Avoid overflow computing return value */
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     }
-    if (i >= oid->len) {
+
+    if (oid->len <= 0) {
+        /* OID must not be empty */
         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     }
-    /* Last byte of first subidentifier */
-    value |= oid->p[i] & 0x7F;
-    i++;
-
-    unsigned int component1 = value / 40;
-    if (component1 > 2) {
-        /* The first component can only be 0, 1 or 2.
-         * If oid->p[0] / 40 is greater than 2, the leftover belongs to
-         * the second component. */
-        component1 = 2;
-    }
-    unsigned int component2 = value - (40 * component1);
-    ret = mbedtls_snprintf(p, n, "%u.%u", component1, component2);
-    OID_SAFE_SNPRINTF;
 
-    value = 0;
-    for (; i < oid->len; i++) {
+    for (size_t i = 0; i < oid->len; i++) {
         /* Prevent overflow in value. */
         if (value > (UINT_MAX >> 7)) {
             return MBEDTLS_ERR_ASN1_INVALID_DATA;
@@ -848,12 +809,38 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size,
 
         if (!(oid->p[i] & 0x80)) {
             /* Last byte */
-            ret = mbedtls_snprintf(p, n, ".%u", value);
-            OID_SAFE_SNPRINTF;
+            if (n == size) {
+                int component1;
+                unsigned int component2;
+                /* First subidentifier contains first two OID components */
+                if (value >= 80) {
+                    component1 = '2';
+                    component2 = value - 80;
+                } else if (value >= 40) {
+                    component1 = '1';
+                    component2 = value - 40;
+                } else {
+                    component1 = '0';
+                    component2 = value;
+                }
+                ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
+            } else {
+                ret = mbedtls_snprintf(p, n, ".%u", value);
+            }
+            if (ret < 2 || (size_t) ret >= n) {
+                return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+            }
+            n -= (size_t) ret;
+            p += ret;
             value = 0;
         }
     }
 
+    if (value != 0) {
+        /* Unterminated subidentifier */
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+
     return (int) (size - n);
 }
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index d8a994045..bad7f4697 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -47,7 +47,6 @@
 
 #include "psa_crypto_random_impl.h"
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include "mbedtls/platform.h"
@@ -1512,14 +1511,12 @@ exit:
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
-#if defined(static_assert)
-static_assert((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & 
MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
-              "One or more key attribute flag is listed as both external-only 
and dual-use");
-static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
-              "One or more key attribute flag is listed as both internal-only 
and dual-use");
-static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) 
== 0,
-              "One or more key attribute flag is listed as both internal-only 
and external-only");
-#endif
+MBEDTLS_STATIC_ASSERT((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & 
MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
+                      "One or more key attribute flag is listed as both 
external-only and dual-use")
+MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & 
MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
+                      "One or more key attribute flag is listed as both 
internal-only and dual-use")
+MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & 
MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0,
+                      "One or more key attribute flag is listed as both 
internal-only and external-only")
 
 /** Validate that a key policy is internally well-formed.
  *
@@ -1782,11 +1779,10 @@ static psa_status_t psa_finish_key_creation(
             psa_key_slot_number_t slot_number =
                 psa_key_slot_get_slot_number(slot);
 
-#if defined(static_assert)
-            static_assert(sizeof(slot_number) ==
-                          sizeof(data.slot_number),
-                          "Slot number size does not match 
psa_se_key_data_storage_t");
-#endif
+            MBEDTLS_STATIC_ASSERT(sizeof(slot_number) ==
+                                  sizeof(data.slot_number),
+                                  "Slot number size does not match 
psa_se_key_data_storage_t");
+
             memcpy(&data.slot_number, &slot_number, sizeof(slot_number));
             status = psa_save_persistent_key(&slot->attr,
                                              (uint8_t *) &data,
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index b66039364..7bea10ad6 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -22,7 +22,6 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 
-#include <assert.h>
 #include <stdint.h>
 #include <string.h>
 
@@ -315,10 +314,8 @@ psa_status_t psa_register_se_driver(
     }
     /* Driver table entries are 0-initialized. 0 is not a valid driver
      * location because it means a transparent key. */
-#if defined(static_assert)
-    static_assert(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
-                  "Secure element support requires 0 to mean a local key");
-#endif
+    MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
+                          "Secure element support requires 0 to mean a local 
key");
     if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index a38e76440..8a2ab7b9b 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -5429,8 +5429,10 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned 
char *buf, size_t len)
     n = (len < ssl->in_msglen)
         ? len : ssl->in_msglen;
 
-    memcpy(buf, ssl->in_offt, n);
-    ssl->in_msglen -= n;
+    if (len != 0) {
+        memcpy(buf, ssl->in_offt, n);
+        ssl->in_msglen -= n;
+    }
 
     /* Zeroising the plaintext buffer to erase unused application data
        from the memory. */
@@ -5506,7 +5508,9 @@ static int ssl_write_real(mbedtls_ssl_context *ssl,
          */
         ssl->out_msglen  = len;
         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
-        memcpy(ssl->out_msg, buf, len);
+        if (len > 0) {
+            memcpy(ssl->out_msg, buf, len);
+        }
 
         if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret);

Reply via email to