Merge pull request #4366 from gilles-peskine-arm/development_3.0-merge_2.x-20210419

Merge development 2.x into 3.0 (Apr 19)
diff --git a/ChangeLog.d/issue1792.txt b/ChangeLog.d/issue1792.txt
new file mode 100644
index 0000000..9949bf4
--- /dev/null
+++ b/ChangeLog.d/issue1792.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix a bug in ECDSA that would cause it to fail when the hash is all-bits
+     zero. Fixes #1792
diff --git a/ChangeLog.d/mpi_read_negative_zero.txt b/ChangeLog.d/mpi_read_negative_zero.txt
new file mode 100644
index 0000000..e338de7
--- /dev/null
+++ b/ChangeLog.d/mpi_read_negative_zero.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * mbedtls_mpi_read_string on "-0" produced an MPI object that was not treated
+     as equal to 0 in all cases. Fix it to produce the same object as "0".
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 5f9c5a8..81e1f28 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -777,7 +777,7 @@
  *      publicExponent     INTEGER  }  -- e
  *   ```
  * - For elliptic curve keys on a twisted Edwards curve (key types for which
- *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_GET_CURVE
+ *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY
  *   returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined
  *   by RFC 8032
  *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).
diff --git a/include/psa/crypto_builtin.h b/include/psa/crypto_builtin.h
new file mode 100644
index 0000000..b3bc140
--- /dev/null
+++ b/include/psa/crypto_builtin.h
@@ -0,0 +1,144 @@
+/*
+ *  Context structure declaration of the Mbed TLS software-based PSA drivers
+ *  called through the PSA Crypto driver dispatch layer.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * \note This header and its content is not part of the Mbed TLS API and
+ * applications must not depend on it. Its main purpose is to define the
+ * multi-part state objects of the Mbed TLS software-based PSA drivers. The
+ * definition of these objects are then used by crypto_struct.h to define the
+ * implementation-defined types of PSA multi-part state objects.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_BUILTIN_H
+#define PSA_CRYPTO_BUILTIN_H
+
+#include <psa/crypto_driver_common.h>
+
+/*
+ * Hash multi-part operation definitions.
+ */
+
+#include "mbedtls/md2.h"
+#include "mbedtls/md4.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/ripemd160.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+#define MBEDTLS_PSA_BUILTIN_HASH
+#endif
+
+typedef struct
+{
+    psa_algorithm_t alg;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_MD2_C)
+        mbedtls_md2_context md2;
+#endif
+#if defined(MBEDTLS_MD4_C)
+        mbedtls_md4_context md4;
+#endif
+#if defined(MBEDTLS_MD5_C)
+        mbedtls_md5_context md5;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        mbedtls_ripemd160_context ripemd160;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        mbedtls_sha1_context sha1;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        mbedtls_sha256_context sha256;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        mbedtls_sha512_context sha512;
+#endif
+    } ctx;
+} mbedtls_psa_hash_operation_t;
+
+#define MBEDTLS_PSA_HASH_OPERATION_INIT {0, {0}}
+
+/*
+ * Cipher multi-part operation definitions.
+ */
+
+#include "mbedtls/cipher.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_XTS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
+#define MBEDTLS_PSA_BUILTIN_CIPHER  1
+#endif
+
+typedef struct {
+    /* Context structure for the Mbed TLS cipher implementation. */
+    psa_algorithm_t alg;
+    uint8_t iv_length;
+    uint8_t block_length;
+    mbedtls_cipher_context_t cipher;
+} mbedtls_psa_cipher_operation_t;
+
+#define MBEDTLS_PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}}
+
+/*
+ * BEYOND THIS POINT, TEST DRIVER DECLARATIONS ONLY.
+ */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+typedef mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT MBEDTLS_PSA_HASH_OPERATION_INIT
+
+typedef mbedtls_psa_cipher_operation_t
+        mbedtls_transparent_test_driver_cipher_operation_t;
+
+typedef struct {
+    unsigned int initialised : 1;
+    mbedtls_transparent_test_driver_cipher_operation_t ctx;
+} mbedtls_opaque_test_driver_cipher_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \
+     MBEDTLS_PSA_CIPHER_OPERATION_INIT
+
+#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \
+     { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT }
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+#endif /* PSA_CRYPTO_BUILTIN_H */
diff --git a/include/psa/crypto_builtin_cipher.h b/include/psa/crypto_builtin_cipher.h
deleted file mode 100644
index df26c91..0000000
--- a/include/psa/crypto_builtin_cipher.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Context structure declaration of the software-based driver which performs
- *  cipher operations through the PSA Crypto driver dispatch layer.
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifndef PSA_CRYPTO_BUILTIN_CIPHER_H
-#define PSA_CRYPTO_BUILTIN_CIPHER_H
-
-#include <psa/crypto_driver_common.h>
-#include "mbedtls/cipher.h"
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_XTS) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
-#define MBEDTLS_PSA_BUILTIN_CIPHER  1
-#endif
-
-typedef struct {
-    /* Context structure for the Mbed TLS cipher implementation. */
-    psa_algorithm_t alg;
-    uint8_t iv_length;
-    uint8_t block_length;
-    mbedtls_cipher_context_t cipher;
-} mbedtls_psa_cipher_operation_t;
-
-#define MBEDTLS_PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}}
-
-/*
- * BEYOND THIS POINT, TEST DRIVER DECLARATIONS ONLY.
- */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-
-typedef mbedtls_psa_cipher_operation_t
-        mbedtls_transparent_test_driver_cipher_operation_t;
-
-typedef struct {
-    unsigned int initialised : 1;
-    mbedtls_transparent_test_driver_cipher_operation_t ctx;
-} mbedtls_opaque_test_driver_cipher_operation_t;
-
-#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \
-     MBEDTLS_PSA_CIPHER_OPERATION_INIT
-
-#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \
-     { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT }
-
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-
-#endif /* PSA_CRYPTO_BUILTIN_CIPHER_H */
diff --git a/include/psa/crypto_builtin_hash.h b/include/psa/crypto_builtin_hash.h
deleted file mode 100644
index 64323bf..0000000
--- a/include/psa/crypto_builtin_hash.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Context structure declaration of the software-based driver which performs
- *  hashing through the PSA Crypto driver dispatch layer.
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifndef PSA_CRYPTO_BUILTIN_HASH_H
-#define PSA_CRYPTO_BUILTIN_HASH_H
-
-#include <psa/crypto_driver_common.h>
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
-#include "mbedtls/md5.h"
-#include "mbedtls/ripemd160.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-#include "mbedtls/sha512.h"
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
-#define MBEDTLS_PSA_BUILTIN_HASH
-#endif
-
-typedef struct
-{
-    psa_algorithm_t alg;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_MD2_C)
-        mbedtls_md2_context md2;
-#endif
-#if defined(MBEDTLS_MD4_C)
-        mbedtls_md4_context md4;
-#endif
-#if defined(MBEDTLS_MD5_C)
-        mbedtls_md5_context md5;
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-        mbedtls_ripemd160_context ripemd160;
-#endif
-#if defined(MBEDTLS_SHA1_C)
-        mbedtls_sha1_context sha1;
-#endif
-#if defined(MBEDTLS_SHA256_C)
-        mbedtls_sha256_context sha256;
-#endif
-#if defined(MBEDTLS_SHA512_C)
-        mbedtls_sha512_context sha512;
-#endif
-    } ctx;
-} mbedtls_psa_hash_operation_t;
-
-#define MBEDTLS_PSA_HASH_OPERATION_INIT {0, {0}}
-
-/*
- * BEYOND THIS POINT, TEST DRIVER DECLARATIONS ONLY.
- */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-
-typedef mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t;
-
-#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT MBEDTLS_PSA_HASH_OPERATION_INIT
-
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-
-#endif /* PSA_CRYPTO_BUILTIN_HASH_H */
diff --git a/include/psa/crypto_driver_contexts.h b/include/psa/crypto_driver_contexts.h
index bee6895..d725e84 100644
--- a/include/psa/crypto_driver_contexts.h
+++ b/include/psa/crypto_driver_contexts.h
@@ -3,6 +3,15 @@
  *  interface.
  *
  *  Warning: This file will be auto-generated in the future.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * \note This header and its content is not part of the Mbed TLS API and
+ * applications must not depend on it. Its main purpose is to define the
+ * multi-part state objects of the PSA drivers included in the cryptographic
+ * library. The definition of these objects are then used by crypto_struct.h
+ * to define the implementation-defined types of PSA multi-part state objects.
  */
 /*  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0
@@ -30,8 +39,7 @@
  * declared during the autogeneration process. */
 
 /* Include the context structure definitions for the Mbed TLS software drivers */
-#include "psa/crypto_builtin_cipher.h"
-#include "psa/crypto_builtin_hash.h"
+#include "psa/crypto_builtin.h"
 
 /* Define the context to be used for an operation that is executed through the
  * PSA Driver wrapper layer as the union of all possible driver's contexts.
@@ -41,7 +49,7 @@
  * of both this file and the content of psa_crypto_driver_wrappers.c */
 
 typedef union {
-    unsigned dummy; /* Make sure this structure is always non-empty */
+    unsigned dummy; /* Make sure this union is always non-empty */
     mbedtls_psa_hash_operation_t mbedtls_ctx;
 #if defined(PSA_CRYPTO_DRIVER_TEST)
     mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx;
@@ -49,7 +57,7 @@
 } psa_driver_hash_context_t;
 
 typedef union {
-    unsigned dummy; /* Make sure this structure is always non-empty */
+    unsigned dummy; /* Make sure this union is always non-empty */
     mbedtls_psa_cipher_operation_t mbedtls_ctx;
 #if defined(PSA_CRYPTO_DRIVER_TEST)
     mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx;
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index b2da6a2..8ac7ce1 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -15,12 +15,20 @@
  *
  * <h3>Design notes about multipart operation structures</h3>
  *
- * Each multipart operation structure contains a `psa_algorithm_t alg`
- * field which indicates which specific algorithm the structure is for.
- * When the structure is not in use, `alg` is 0. Most of the structure
- * consists of a union which is discriminated by `alg`.
+ * For multipart operations without driver delegation support, each multipart
+ * operation structure contains a `psa_algorithm_t alg` field which indicates
+ * which specific algorithm the structure is for. When the structure is not in
+ * use, `alg` is 0. Most of the structure consists of a union which is
+ * discriminated by `alg`.
  *
- * Note that when `alg` is 0, the content of other fields is undefined.
+ * For multipart operations with driver delegation support, each multipart
+ * operation structure contains an `unsigned int id` field indicating which
+ * driver got assigned to do the operation. When the structure is not in use,
+ * 'id' is 0. The structure contains also a driver context which is the union
+ * of the contexts of all drivers able to handle the type of multipart
+ * operation.
+ *
+ * Note that when `alg` or `id` is 0, the content of other fields is undefined.
  * In particular, it is not guaranteed that a freshly-initialized structure
  * is all-zero: we initialize structures to something like `{0, 0}`, which
  * is only guaranteed to initializes the first member of the union;
@@ -76,9 +84,9 @@
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
-     * ID values are auto-generated in psa_driver_wrappers.h
+     * ID values are auto-generated in psa_driver_wrappers.h.
      * ID value zero means the context is not valid or not assigned to
-     * any driver (i.e. none of the driver contexts are active). */
+     * any driver (i.e. the driver context is not active, in use). */
     unsigned int id;
     psa_driver_hash_context_t ctx;
 };
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index b755b17..fbc3664 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -62,6 +62,7 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_aead.c
     psa_crypto_cipher.c
     psa_crypto_client.c
     psa_crypto_driver_wrappers.c
diff --git a/library/Makefile b/library/Makefile
index 4d64ef4..6dced76 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -119,6 +119,7 @@
 	     platform_util.o \
 	     poly1305.o \
 	     psa_crypto.o \
+	     psa_crypto_aead.o \
 	     psa_crypto_cipher.o \
 	     psa_crypto_client.o \
 	     psa_crypto_driver_wrappers.o \
diff --git a/library/bignum.c b/library/bignum.c
index abda2c1..71014e5 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -470,6 +470,7 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, j, slen, n;
+    int sign = 1;
     mbedtls_mpi_uint d;
     mbedtls_mpi T;
     MPI_VALIDATE_RET( X != NULL );
@@ -480,6 +481,12 @@
 
     mbedtls_mpi_init( &T );
 
+    if( s[0] == '-' )
+    {
+        ++s;
+        sign = -1;
+    }
+
     slen = strlen( s );
 
     if( radix == 16 )
@@ -494,12 +501,6 @@
 
         for( i = slen, j = 0; i > 0; i--, j++ )
         {
-            if( i == 1 && s[i - 1] == '-' )
-            {
-                X->s = -1;
-                break;
-            }
-
             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
         }
@@ -510,26 +511,15 @@
 
         for( i = 0; i < slen; i++ )
         {
-            if( i == 0 && s[i] == '-' )
-            {
-                X->s = -1;
-                continue;
-            }
-
             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
-
-            if( X->s == 1 )
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
-            }
-            else
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
-            }
+            MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
         }
     }
 
+    if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
+        X->s = -1;
+
 cleanup:
 
     mbedtls_mpi_free( &T );
diff --git a/library/ecjpake.c b/library/ecjpake.c
index bd47169..464ff51 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -273,7 +273,7 @@
 
     r_len = *(*p)++;
 
-    if( end < *p || (size_t)( end - *p ) < r_len )
+    if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
     {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
diff --git a/library/ecp.c b/library/ecp.c
index 94658fa..4c0d28e 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -77,6 +77,8 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
+#include "ecp_invasive.h"
+
 #include <string.h>
 
 #if !defined(MBEDTLS_ECP_ALT)
@@ -2808,7 +2810,7 @@
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
- * R = m * P with shortcuts for m == 1 and m == -1
+ * R = m * P with shortcuts for m == 0, m == 1 and m == -1
  * NOT constant-time - ONLY for short Weierstrass!
  */
 static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
@@ -2819,7 +2821,11 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
+    if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
+    }
+    else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
     {
         MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
     }
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 962d5af..165c315 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -25,6 +25,8 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
+#include "ecp_invasive.h"
+
 #include <string.h>
 
 #if !defined(MBEDTLS_ECP_ALT)
@@ -1028,26 +1030,35 @@
     STORE32; i++;                               \
     cur = c > 0 ? c : 0; STORE32;               \
     cur = 0; while( ++i < MAX32 ) { STORE32; }  \
-    if( c < 0 ) fix_negative( N, c, bits );
+    if( c < 0 ) mbedtls_ecp_fix_negative( N, c, bits );
 
 /*
  * If the result is negative, we get it in the form
- * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ * c * 2^bits + N, with c negative and N positive shorter than 'bits'
  */
-static inline void fix_negative( mbedtls_mpi *N, signed char c, size_t bits )
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits )
 {
     size_t i;
 
-    /* Set N := N - 2^bits */
-    --N->p[0];
+    /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so
+     * set the absolute value to 0xfff...fff - N. There is no carry
+     * since we're subtracting from all-bits-one.  */
     for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ )
     {
         N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i];
     }
+    /* Add 1, taking care of the carry. */
+    i = 0;
+    do
+        ++N->p[i];
+    while( N->p[i++] == 0 && i <= bits / 8 / sizeof( mbedtls_mpi_uint ) );
+    /* Invert the sign.
+     * Now N = N0 - 2^bits where N0 is the initial value of N. */
     N->s = -1;
 
-    /* Add |c| * 2^(bits + 32) to the absolute value. Since c and N are
-    * negative, this adds c * 2^(bits + 32). */
+    /* Add |c| * 2^bits to the absolute value. Since c and N are
+    * negative, this adds c * 2^bits. */
     mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c;
 #if defined(MBEDTLS_HAVE_INT64)
     if( bits == 224 )
diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h
new file mode 100644
index 0000000..b523967
--- /dev/null
+++ b/library/ecp_invasive.h
@@ -0,0 +1,51 @@
+/**
+ * \file ecp_invasive.h
+ *
+ * \brief ECP module: interfaces for invasive testing only.
+ *
+ * The interfaces in this file are intended for testing purposes only.
+ * They SHOULD NOT be made available in library integrations except when
+ * building the library for testing.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef MBEDTLS_ECP_INVASIVE_H
+#define MBEDTLS_ECP_INVASIVE_H
+
+#include "common.h"
+#include "mbedtls/ecp.h"
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+/* Preconditions:
+ *   - bits is a multiple of 64 or is 224
+ *   - c is -1 or -2
+ *   - 0 <= N < 2^bits
+ *   - N has room for bits plus one limb
+ *
+ * Behavior:
+ * Set N to c * 2^bits + old_value_of_N.
+ */
+void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits );
+#endif
+
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
+
+#endif /* MBEDTLS_ECP_INVASIVE_H */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 9c9891f..ca56381 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -563,17 +563,6 @@
     return( PSA_SUCCESS );
 }
 
-/** Return the size of the key in the given slot, in bits.
- *
- * \param[in] slot      A key slot.
- *
- * \return The key size in bits, read from the metadata in the slot.
- */
-static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
-{
-    return( slot->attr.bits );
-}
-
 /** Check whether a given key type is valid for use with a given MAC algorithm
  *
  * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH
@@ -3530,158 +3519,6 @@
 /* AEAD */
 /****************************************************************/
 
-typedef struct
-{
-    psa_key_slot_t *slot;
-    const mbedtls_cipher_info_t *cipher_info;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-        mbedtls_ccm_context ccm;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-        mbedtls_gcm_context gcm;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-        mbedtls_chachapoly_context chachapoly;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-    } ctx;
-    psa_algorithm_t core_alg;
-    uint8_t full_tag_length;
-    uint8_t tag_length;
-} aead_operation_t;
-
-#define AEAD_OPERATION_INIT {0, 0, {0}, 0, 0, 0}
-
-static void psa_aead_abort_internal( aead_operation_t *operation )
-{
-    switch( operation->core_alg )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-        case PSA_ALG_CCM:
-            mbedtls_ccm_free( &operation->ctx.ccm );
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-        case PSA_ALG_GCM:
-            mbedtls_gcm_free( &operation->ctx.gcm );
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-    }
-
-    psa_unlock_key_slot( operation->slot );
-}
-
-static psa_status_t psa_aead_setup( aead_operation_t *operation,
-                                    mbedtls_svc_key_id_t key,
-                                    psa_key_usage_t usage,
-                                    psa_algorithm_t alg )
-{
-    psa_status_t status;
-    size_t key_bits;
-    mbedtls_cipher_id_t cipher_id;
-
-    status = psa_get_and_lock_transparent_key_slot_with_policy(
-                 key, &operation->slot, usage, alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    key_bits = psa_get_key_slot_bits( operation->slot );
-
-    operation->cipher_info =
-        mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits,
-                                      &cipher_id );
-    if( operation->cipher_info == NULL )
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
-        goto cleanup;
-    }
-
-    switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
-            operation->core_alg = PSA_ALG_CCM;
-            operation->full_tag_length = 16;
-            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
-             * The call to mbedtls_ccm_encrypt_and_tag or
-             * mbedtls_ccm_auth_decrypt will validate the tag length. */
-            if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( operation->slot->attr.type ) != 16 )
-            {
-                status = PSA_ERROR_INVALID_ARGUMENT;
-                goto cleanup;
-            }
-            mbedtls_ccm_init( &operation->ctx.ccm );
-            status = mbedtls_to_psa_error(
-                mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
-                                    operation->slot->key.data,
-                                    (unsigned int) key_bits ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
-            operation->core_alg = PSA_ALG_GCM;
-            operation->full_tag_length = 16;
-            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
-             * The call to mbedtls_gcm_crypt_and_tag or
-             * mbedtls_gcm_auth_decrypt will validate the tag length. */
-            if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( operation->slot->attr.type ) != 16 )
-            {
-                status = PSA_ERROR_INVALID_ARGUMENT;
-                goto cleanup;
-            }
-            mbedtls_gcm_init( &operation->ctx.gcm );
-            status = mbedtls_to_psa_error(
-                mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
-                                    operation->slot->key.data,
-                                    (unsigned int) key_bits ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
-            operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
-            operation->full_tag_length = 16;
-            /* We only support the default tag length. */
-            if( alg != PSA_ALG_CHACHA20_POLY1305 )
-            {
-                status = PSA_ERROR_NOT_SUPPORTED;
-                goto cleanup;
-            }
-            mbedtls_chachapoly_init( &operation->ctx.chachapoly );
-            status = mbedtls_to_psa_error(
-                mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
-                                           operation->slot->key.data ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-
-        default:
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto cleanup;
-    }
-
-    if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length )
-    {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        goto cleanup;
-    }
-    operation->tag_length = PSA_AEAD_TAG_LENGTH( alg );
-
-    return( PSA_SUCCESS );
-
-cleanup:
-    psa_aead_abort_internal( operation );
-    return( status );
-}
-
 psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
@@ -3694,107 +3531,37 @@
                                size_t ciphertext_size,
                                size_t *ciphertext_length )
 {
-    psa_status_t status;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
-    uint8_t *tag;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
 
     *ciphertext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg );
+    if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    status = psa_get_and_lock_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
-    /* For all currently supported modes, the tag is at the end of the
-     * ciphertext. */
-    if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
-    {
-        status = PSA_ERROR_BUFFER_TOO_SMALL;
-        goto exit;
-    }
-    tag = ciphertext + plaintext_length;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-    if( operation.core_alg == PSA_ALG_GCM )
-    {
-        status = mbedtls_to_psa_error(
-            mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
-                                       MBEDTLS_GCM_ENCRYPT,
-                                       plaintext_length,
-                                       nonce, nonce_length,
-                                       additional_data, additional_data_length,
-                                       plaintext, ciphertext,
-                                       operation.tag_length, tag ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-    if( operation.core_alg == PSA_ALG_CCM )
-    {
-        status = mbedtls_to_psa_error(
-            mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
-                                         plaintext_length,
-                                         nonce, nonce_length,
-                                         additional_data,
-                                         additional_data_length,
-                                         plaintext, ciphertext,
-                                         tag, operation.tag_length ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        if( nonce_length != 12 || operation.tag_length != 16 )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        status = mbedtls_to_psa_error(
-            mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
-                                                plaintext_length,
-                                                nonce,
-                                                additional_data,
-                                                additional_data_length,
-                                                plaintext,
-                                                ciphertext,
-                                                tag ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-    {
-        (void) tag;
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    status = psa_driver_wrapper_aead_encrypt(
+        &attributes, slot->key.data, slot->key.bytes,
+        alg,
+        nonce, nonce_length,
+        additional_data, additional_data_length,
+        plaintext, plaintext_length,
+        ciphertext, ciphertext_size, ciphertext_length );
 
     if( status != PSA_SUCCESS && ciphertext_size != 0 )
         memset( ciphertext, 0, ciphertext_size );
 
-exit:
-    psa_aead_abort_internal( &operation );
-    if( status == PSA_SUCCESS )
-        *ciphertext_length = plaintext_length + operation.tag_length;
-    return( status );
-}
+    psa_unlock_key_slot( slot );
 
-/* Locate the tag in a ciphertext buffer containing the encrypted data
- * followed by the tag. Return the length of the part preceding the tag in
- * *plaintext_length. This is the size of the plaintext in modes where
- * the encrypted data has the same size as the plaintext, such as
- * CCM and GCM. */
-static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
-                                                  const uint8_t *ciphertext,
-                                                  size_t ciphertext_length,
-                                                  size_t plaintext_size,
-                                                  const uint8_t **p_tag )
-{
-    size_t payload_length;
-    if( tag_length > ciphertext_length )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    payload_length = ciphertext_length - tag_length;
-    if( payload_length > plaintext_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-    *p_tag = ciphertext + payload_length;
-    return( PSA_SUCCESS );
+    return( status );
 }
 
 psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
@@ -3809,86 +3576,39 @@
                                size_t plaintext_size,
                                size_t *plaintext_length )
 {
-    psa_status_t status;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
-    const uint8_t *tag = NULL;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
 
     *plaintext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg );
+    if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    status = psa_get_and_lock_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_aead_unpadded_locate_tag( operation.tag_length,
-                                           ciphertext, ciphertext_length,
-                                           plaintext_size, &tag );
-    if( status != PSA_SUCCESS )
-        goto exit;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-    if( operation.core_alg == PSA_ALG_GCM )
-    {
-        status = mbedtls_to_psa_error(
-            mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
-                                      ciphertext_length - operation.tag_length,
-                                      nonce, nonce_length,
-                                      additional_data,
-                                      additional_data_length,
-                                      tag, operation.tag_length,
-                                      ciphertext, plaintext ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-    if( operation.core_alg == PSA_ALG_CCM )
-    {
-        status = mbedtls_to_psa_error(
-            mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
-                                      ciphertext_length - operation.tag_length,
-                                      nonce, nonce_length,
-                                      additional_data,
-                                      additional_data_length,
-                                      ciphertext, plaintext,
-                                      tag, operation.tag_length ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        if( nonce_length != 12 || operation.tag_length != 16 )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        status = mbedtls_to_psa_error(
-            mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
-                                             ciphertext_length - operation.tag_length,
-                                             nonce,
-                                             additional_data,
-                                             additional_data_length,
-                                             tag,
-                                             ciphertext,
-                                             plaintext ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-    {
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    status = psa_driver_wrapper_aead_decrypt(
+        &attributes, slot->key.data, slot->key.bytes,
+        alg,
+        nonce, nonce_length,
+        additional_data, additional_data_length,
+        ciphertext, ciphertext_length,
+        plaintext, plaintext_size, plaintext_length );
 
     if( status != PSA_SUCCESS && plaintext_size != 0 )
         memset( plaintext, 0, plaintext_size );
 
-exit:
-    psa_aead_abort_internal( &operation );
-    if( status == PSA_SUCCESS )
-        *plaintext_length = ciphertext_length - operation.tag_length;
+    psa_unlock_key_slot( slot );
+
     return( status );
 }
 
-
-
 /****************************************************************/
 /* Generators */
 /****************************************************************/
diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c
new file mode 100644
index 0000000..2632830
--- /dev/null
+++ b/library/psa_crypto_aead.c
@@ -0,0 +1,363 @@
+/*
+ *  PSA AEAD entry points
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa_crypto_aead.h"
+#include "psa_crypto_core.h"
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/gcm.h"
+
+typedef struct
+{
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        mbedtls_ccm_context ccm;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        mbedtls_gcm_context gcm;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        mbedtls_chachapoly_context chachapoly;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    } ctx;
+    psa_algorithm_t core_alg;
+    uint8_t tag_length;
+} aead_operation_t;
+
+#define AEAD_OPERATION_INIT {{0}, 0, 0}
+
+static void psa_aead_abort_internal( aead_operation_t *operation )
+{
+    switch( operation->core_alg )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        case PSA_ALG_CCM:
+            mbedtls_ccm_free( &operation->ctx.ccm );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        case PSA_ALG_GCM:
+            mbedtls_gcm_free( &operation->ctx.gcm );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            mbedtls_chachapoly_free( &operation->ctx.chachapoly );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    }
+}
+
+static psa_status_t psa_aead_setup(
+    aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t key_bits;
+    const mbedtls_cipher_info_t *cipher_info;
+    mbedtls_cipher_id_t cipher_id;
+    size_t full_tag_length = 0;
+
+    key_bits = attributes->core.bits;
+
+    cipher_info = mbedtls_cipher_info_from_psa( alg,
+                                                attributes->core.type, key_bits,
+                                                &cipher_id );
+    if( cipher_info == NULL )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
+            operation->core_alg = PSA_ALG_CCM;
+            full_tag_length = 16;
+            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
+             * The call to mbedtls_ccm_encrypt_and_tag or
+             * mbedtls_ccm_auth_decrypt will validate the tag length. */
+            if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+
+            mbedtls_ccm_init( &operation->ctx.ccm );
+            status = mbedtls_to_psa_error(
+                mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
+                                    key_buffer, (unsigned int) key_bits ) );
+            if( status != PSA_SUCCESS )
+                return( status );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
+            operation->core_alg = PSA_ALG_GCM;
+            full_tag_length = 16;
+            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
+             * The call to mbedtls_gcm_crypt_and_tag or
+             * mbedtls_gcm_auth_decrypt will validate the tag length. */
+            if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+
+            mbedtls_gcm_init( &operation->ctx.gcm );
+            status = mbedtls_to_psa_error(
+                mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
+                                    key_buffer, (unsigned int) key_bits ) );
+            if( status != PSA_SUCCESS )
+                return( status );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
+            operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
+            full_tag_length = 16;
+            /* We only support the default tag length. */
+            if( alg != PSA_ALG_CHACHA20_POLY1305 )
+                return( PSA_ERROR_NOT_SUPPORTED );
+
+            mbedtls_chachapoly_init( &operation->ctx.chachapoly );
+            status = mbedtls_to_psa_error(
+                mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
+                                           key_buffer ) );
+            if( status != PSA_SUCCESS )
+                return( status );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+
+        default:
+            return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    if( PSA_AEAD_TAG_LENGTH( alg ) > full_tag_length )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    operation->tag_length = PSA_AEAD_TAG_LENGTH( alg );
+
+    return( PSA_SUCCESS );
+}
+
+psa_status_t mbedtls_psa_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
+    uint8_t *tag;
+    (void) key_buffer_size;
+
+    status = psa_aead_setup( &operation, attributes, key_buffer, alg );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    /* For all currently supported modes, the tag is at the end of the
+     * ciphertext. */
+    if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
+    {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+    tag = ciphertext + plaintext_length;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if( operation.core_alg == PSA_ALG_CCM )
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
+                                         plaintext_length,
+                                         nonce, nonce_length,
+                                         additional_data,
+                                         additional_data_length,
+                                         plaintext, ciphertext,
+                                         tag, operation.tag_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation.core_alg == PSA_ALG_GCM )
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
+                                       MBEDTLS_GCM_ENCRYPT,
+                                       plaintext_length,
+                                       nonce, nonce_length,
+                                       additional_data, additional_data_length,
+                                       plaintext, ciphertext,
+                                       operation.tag_length, tag ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        if( nonce_length != 12 || operation.tag_length != 16 )
+        {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+        }
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
+                                                plaintext_length,
+                                                nonce,
+                                                additional_data,
+                                                additional_data_length,
+                                                plaintext,
+                                                ciphertext,
+                                                tag ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) tag;
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    if( status == PSA_SUCCESS )
+        *ciphertext_length = plaintext_length + operation.tag_length;
+
+exit:
+    psa_aead_abort_internal( &operation );
+
+    return( status );
+}
+
+/* Locate the tag in a ciphertext buffer containing the encrypted data
+ * followed by the tag. Return the length of the part preceding the tag in
+ * *plaintext_length. This is the size of the plaintext in modes where
+ * the encrypted data has the same size as the plaintext, such as
+ * CCM and GCM. */
+static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
+                                                  const uint8_t *ciphertext,
+                                                  size_t ciphertext_length,
+                                                  size_t plaintext_size,
+                                                  const uint8_t **p_tag )
+{
+    size_t payload_length;
+    if( tag_length > ciphertext_length )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    payload_length = ciphertext_length - tag_length;
+    if( payload_length > plaintext_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+    *p_tag = ciphertext + payload_length;
+    return( PSA_SUCCESS );
+}
+
+psa_status_t mbedtls_psa_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
+    const uint8_t *tag = NULL;
+    (void) key_buffer_size;
+
+    status = psa_aead_setup( &operation, attributes, key_buffer, alg );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_aead_unpadded_locate_tag( operation.tag_length,
+                                           ciphertext, ciphertext_length,
+                                           plaintext_size, &tag );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if( operation.core_alg == PSA_ALG_CCM )
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
+                                      ciphertext_length - operation.tag_length,
+                                      nonce, nonce_length,
+                                      additional_data,
+                                      additional_data_length,
+                                      ciphertext, plaintext,
+                                      tag, operation.tag_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation.core_alg == PSA_ALG_GCM )
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
+                                      ciphertext_length - operation.tag_length,
+                                      nonce, nonce_length,
+                                      additional_data,
+                                      additional_data_length,
+                                      tag, operation.tag_length,
+                                      ciphertext, plaintext ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        if( nonce_length != 12 || operation.tag_length != 16 )
+        {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+        }
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
+                                             ciphertext_length - operation.tag_length,
+                                             nonce,
+                                             additional_data,
+                                             additional_data_length,
+                                             tag,
+                                             ciphertext,
+                                             plaintext ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    if( status == PSA_SUCCESS )
+        *plaintext_length = ciphertext_length - operation.tag_length;
+
+exit:
+    psa_aead_abort_internal( &operation );
+
+    if( status == PSA_SUCCESS )
+        *plaintext_length = ciphertext_length - operation.tag_length;
+    return( status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
diff --git a/library/psa_crypto_aead.h b/library/psa_crypto_aead.h
new file mode 100644
index 0000000..aab0f83
--- /dev/null
+++ b/library/psa_crypto_aead.h
@@ -0,0 +1,151 @@
+/*
+ *  PSA AEAD driver entry points
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_AEAD_H
+#define PSA_CRYPTO_AEAD_H
+
+#include <psa/crypto.h>
+
+/**
+ * \brief Process an authenticated encryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_encrypt entry point. This function behaves as an aead_encrypt
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes         The attributes of the key to use for the
+ *                                operation.
+ * \param[in]  key_buffer         The buffer containing the key context.
+ * \param      key_buffer_size    Size of the \p key_buffer buffer in bytes.
+ * \param      alg                The AEAD algorithm to compute.
+ * \param[in]  nonce              Nonce or IV to use.
+ * \param      nonce_length       Size of the nonce buffer in bytes. This must
+ *                                be appropriate for the selected algorithm.
+ *                                The default nonce size is
+ *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where
+ *                                key_type is the type of key.
+ * \param[in]  additional_data    Additional data that will be authenticated
+ *                                but not encrypted.
+ * \param      additional_data_length  Size of additional_data in bytes.
+ * \param[in]  plaintext          Data that will be authenticated and encrypted.
+ * \param      plaintext_length   Size of plaintext in bytes.
+ * \param[out] ciphertext         Output buffer for the authenticated and
+ *                                encrypted data. The additional data is not
+ *                                part of this output. For algorithms where the
+ *                                encrypted data and the authentication tag are
+ *                                defined as separate outputs, the
+ *                                authentication tag is appended to the
+ *                                encrypted data.
+ * \param      ciphertext_size    Size of the ciphertext buffer in bytes. This
+ *                                must be appropriate for the selected algorithm
+ *                                and key:
+ *                                - A sufficient output size is
+ *                                  PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg,
+ *                                  plaintext_length) where key_type is the type
+ *                                  of key.
+ *                                - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(
+ *                                  plaintext_length) evaluates to the maximum
+ *                                  ciphertext size of any supported AEAD
+ *                                  encryption.
+ * \param[out] ciphertext_length  On success, the size of the output in the
+ *                                ciphertext buffer.
+ *
+ * \retval #PSA_SUCCESS Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         ciphertext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length );
+
+/**
+ * \brief Process an authenticated decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_decrypt entry point. This function behaves as an aead_decrypt
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes         The attributes of the key to use for the
+ *                                operation.
+ * \param[in]  key_buffer         The buffer containing the key context.
+ * \param      key_buffer_size    Size of the \p key_buffer buffer in bytes.
+ * \param      alg                The AEAD algorithm to compute.
+ * \param[in]  nonce              Nonce or IV to use.
+ * \param      nonce_length       Size of the nonce buffer in bytes. This must
+ *                                be appropriate for the selected algorithm.
+ *                                The default nonce size is
+ *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where
+ *                                key_type is the type of key.
+ * \param[in]  additional_data    Additional data that has been authenticated
+ *                                but not encrypted.
+ * \param      additional_data_length  Size of additional_data in bytes.
+ * \param[in]  ciphertext         Data that has been authenticated and
+ *                                encrypted. For algorithms where the encrypted
+ *                                data and the authentication tag are defined
+ *                                as separate inputs, the buffer contains
+ *                                encrypted data followed by the authentication
+ *                                tag.
+ * \param      ciphertext_length  Size of ciphertext in bytes.
+ * \param[out] plaintext          Output buffer for the decrypted data.
+ * \param      plaintext_size     Size of the plaintext buffer in bytes. This
+ *                                must be appropriate for the selected algorithm
+ *                                and key:
+ *                                - A sufficient output size is
+ *                                  PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg,
+ *                                  ciphertext_length) where key_type is the
+ *                                  type of key.
+ *                                - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(
+ *                                  ciphertext_length) evaluates to the maximum
+ *                                  plaintext size of any supported AEAD
+ *                                  decryption.
+ * \param[out] plaintext_length   On success, the size of the output in the
+ *                                plaintext buffer.
+ *
+ * \retval #PSA_SUCCESS Success.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The cipher is not authentic.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         plaintext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
+
+#endif /* PSA_CRYPTO_AEAD */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index ec7ac80..f949c71 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -212,6 +212,22 @@
  */
 psa_status_t mbedtls_to_psa_error( int ret );
 
+/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
+ *  as well as the PSA type and size of the key to be used with the cipher
+ *  algorithm.
+ *
+ * \param       alg        PSA cipher algorithm identifier
+ * \param       key_type   PSA key type
+ * \param       key_bits   Size of the key in bits
+ * \param[out]  cipher_id  Mbed TLS cipher algorithm identifier
+ *
+ * \return  The Mbed TLS cipher information of the cipher algorithm.
+ *          \c NULL if the PSA cipher algorithm is not supported.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
+    psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits,
+    mbedtls_cipher_id_t *cipher_id );
+
 /** Import a key in binary format.
  *
  * \note The signature of this function is that of a PSA driver
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
index 9459c46..536505e 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -19,6 +19,7 @@
  *  limitations under the License.
  */
 
+#include "psa_crypto_aead.h"
 #include "psa_crypto_cipher.h"
 #include "psa_crypto_core.h"
 #include "psa_crypto_driver_wrappers.h"
@@ -1177,4 +1178,107 @@
     }
 }
 
+psa_status_t psa_driver_wrapper_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = test_transparent_aead_encrypt(
+                         attributes, key_buffer, key_buffer_size,
+                         alg,
+                         nonce, nonce_length,
+                         additional_data, additional_data_length,
+                         plaintext, plaintext_length,
+                         ciphertext, ciphertext_size, ciphertext_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            return( mbedtls_psa_aead_encrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        plaintext, plaintext_length,
+                        ciphertext, ciphertext_size, ciphertext_length ) );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = test_transparent_aead_decrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        ciphertext, ciphertext_length,
+                        plaintext, plaintext_size, plaintext_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            return( mbedtls_psa_aead_decrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        ciphertext, ciphertext_length,
+                        plaintext, plaintext_size, plaintext_length ) );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
 /* End of automatically generated file. */
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index e336996..e499411 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -156,6 +156,28 @@
 psa_status_t psa_driver_wrapper_hash_abort(
     psa_hash_operation_t *operation );
 
+/*
+ * AEAD functions
+ */
+
+psa_status_t psa_driver_wrapper_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length );
+
+psa_status_t psa_driver_wrapper_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
+
 #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
 
 /* End of automatically generated file. */
diff --git a/library/psa_crypto_hash.c b/library/psa_crypto_hash.c
index 7552100..a49edd8 100644
--- a/library/psa_crypto_hash.c
+++ b/library/psa_crypto_hash.c
@@ -583,48 +583,48 @@
   */
 #if defined(PSA_CRYPTO_DRIVER_TEST)
 
-psa_status_t is_hash_accelerated( psa_algorithm_t alg )
+static int is_hash_accelerated( psa_algorithm_t alg )
 {
     switch( alg )
     {
 #if defined(MBEDTLS_PSA_ACCEL_ALG_MD2)
         case PSA_ALG_MD2:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_MD4)
         case PSA_ALG_MD4:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
         case PSA_ALG_MD5:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
         case PSA_ALG_RIPEMD160:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
         case PSA_ALG_SHA_1:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
         case PSA_ALG_SHA_224:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
         case PSA_ALG_SHA_256:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
         case PSA_ALG_SHA_384:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
 #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
         case PSA_ALG_SHA_512:
-            return( PSA_SUCCESS );
+            return( 1 );
 #endif
         default:
-            return( PSA_ERROR_NOT_SUPPORTED );
+            return( 0 );
     }
 }
 
@@ -636,7 +636,7 @@
     size_t hash_size,
     size_t *hash_length)
 {
-    if( is_hash_accelerated( alg ) == PSA_SUCCESS )
+    if( is_hash_accelerated( alg ) )
         return( hash_compute( alg, input, input_length,
                               hash, hash_size, hash_length ) );
     else
@@ -647,7 +647,7 @@
     mbedtls_transparent_test_driver_hash_operation_t *operation,
     psa_algorithm_t alg )
 {
-    if( is_hash_accelerated( alg ) == PSA_SUCCESS )
+    if( is_hash_accelerated( alg ) )
         return( hash_setup( operation, alg ) );
     else
         return( PSA_ERROR_NOT_SUPPORTED );
@@ -657,7 +657,7 @@
     const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
     mbedtls_transparent_test_driver_hash_operation_t *target_operation )
 {
-    if( is_hash_accelerated( source_operation->alg ) == PSA_SUCCESS )
+    if( is_hash_accelerated( source_operation->alg ) )
         return( hash_clone( source_operation, target_operation ) );
     else
         return( PSA_ERROR_BAD_STATE );
@@ -668,7 +668,7 @@
     const uint8_t *input,
     size_t input_length )
 {
-    if( is_hash_accelerated( operation->alg ) == PSA_SUCCESS )
+    if( is_hash_accelerated( operation->alg ) )
         return( hash_update( operation, input, input_length ) );
     else
         return( PSA_ERROR_BAD_STATE );
@@ -680,7 +680,7 @@
     size_t hash_size,
     size_t *hash_length )
 {
-    if( is_hash_accelerated( operation->alg ) == PSA_SUCCESS )
+    if( is_hash_accelerated( operation->alg ) )
         return( hash_finish( operation, hash, hash_size, hash_length ) );
     else
         return( PSA_ERROR_BAD_STATE );
diff --git a/library/psa_crypto_hash.h b/library/psa_crypto_hash.h
index b2dfdc5..6655643 100644
--- a/library/psa_crypto_hash.h
+++ b/library/psa_crypto_hash.h
@@ -22,7 +22,6 @@
 #define PSA_CRYPTO_HASH_H
 
 #include <psa/crypto.h>
-#include <psa/crypto_builtin_hash.h>
 
 #include "md_wrap.h"
 
diff --git a/scripts/assemble_changelog.py b/scripts/assemble_changelog.py
index 39632aa..56d6c37 100755
--- a/scripts/assemble_changelog.py
+++ b/scripts/assemble_changelog.py
@@ -201,6 +201,8 @@
     # a version that is not yet released. Something like "3.1a" is accepted.
     _version_number_re = re.compile(br'[0-9]+\.[0-9A-Za-z.]+')
     _incomplete_version_number_re = re.compile(br'.*\.[A-Za-z]')
+    _only_url_re = re.compile(br'^\s*\w+://\S+\s*$')
+    _has_url_re = re.compile(br'.*://.*')
 
     def add_categories_from_text(self, filename, line_offset,
                                  text, allow_unknown_category):
@@ -219,12 +221,18 @@
                                        category.name.decode('utf8'))
 
             body_split = category.body.splitlines()
+
             for line_number, line in enumerate(body_split, 1):
-                if len(line) > MAX_LINE_LENGTH:
+                if not self._only_url_re.match(line) and \
+                   len(line) > MAX_LINE_LENGTH:
+                    long_url_msg = '. URL exceeding length limit must be alone in its line.' \
+                        if self._has_url_re.match(line) else ""
                     raise InputFormatError(filename,
                                            category.body_line + line_number,
-                                           'Line is longer than allowed: Length {} (Max {})',
-                                           len(line), MAX_LINE_LENGTH)
+                                           'Line is longer than allowed: '
+                                           'Length {} (Max {}){}',
+                                           len(line), MAX_LINE_LENGTH,
+                                           long_url_msg)
 
             self.categories[category.name] += category.body
 
diff --git a/tests/include/test/drivers/aead.h b/tests/include/test/drivers/aead.h
new file mode 100644
index 0000000..1be8910
--- /dev/null
+++ b/tests/include/test/drivers/aead.h
@@ -0,0 +1,70 @@
+/*
+ * Test driver for AEAD driver entry points.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_TEST_DRIVERS_AEAD_H
+#define PSA_CRYPTO_TEST_DRIVERS_AEAD_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times AEAD driver functions are called. */
+    unsigned long hits;
+    /* Status returned by the last AEAD driver function call. */
+    psa_status_t driver_status;
+} test_driver_aead_hooks_t;
+
+#define TEST_DRIVER_AEAD_INIT { 0, 0, 0 }
+static inline test_driver_aead_hooks_t test_driver_aead_hooks_init( void )
+{
+    const test_driver_aead_hooks_t v = TEST_DRIVER_AEAD_INIT;
+    return( v );
+}
+
+extern test_driver_aead_hooks_t test_driver_aead_hooks;
+
+psa_status_t test_transparent_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length );
+
+psa_status_t test_transparent_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_AEAD_H */
diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h
index f26b795..2fdce5c 100644
--- a/tests/include/test/drivers/test_driver.h
+++ b/tests/include/test/drivers/test_driver.h
@@ -22,6 +22,7 @@
 
 #define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff
 
+#include "test/drivers/aead.h"
 #include "test/drivers/signature.h"
 #include "test/drivers/key_management.h"
 #include "test/drivers/cipher.h"
diff --git a/tests/src/drivers/aead.c b/tests/src/drivers/aead.c
new file mode 100644
index 0000000..c877525
--- /dev/null
+++ b/tests/src/drivers/aead.c
@@ -0,0 +1,95 @@
+/*
+ * Test driver for AEAD entry points.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa_crypto_aead.h"
+
+#include "test/drivers/aead.h"
+
+test_driver_aead_hooks_t test_driver_aead_hooks = TEST_DRIVER_AEAD_INIT;
+
+psa_status_t test_transparent_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
+{
+    test_driver_aead_hooks.hits++;
+
+    if( test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         test_driver_aead_hooks.driver_status =
+             test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_encrypt(
+                attributes, key_buffer, key_buffer_size,
+                alg,
+                nonce, nonce_length,
+                additional_data, additional_data_length,
+                plaintext, plaintext_length,
+                ciphertext, ciphertext_size, ciphertext_length );
+    }
+
+    return( test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t test_transparent_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
+{
+    test_driver_aead_hooks.hits++;
+
+    if( test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         test_driver_aead_hooks.driver_status =
+             test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_decrypt(
+                attributes, key_buffer, key_buffer_size,
+                alg,
+                nonce, nonce_length,
+                additional_data, additional_data_length,
+                ciphertext, ciphertext_length,
+                plaintext, plaintext_size, plaintext_length );
+    }
+
+    return( test_driver_aead_hooks.driver_status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data
index 889f684..755a43c 100644
--- a/tests/suites/test_suite_ecdsa.data
+++ b/tests/suites/test_suite_ecdsa.data
@@ -1,6 +1,26 @@
 ECDSA Parameter validation
 ecdsa_invalid_param:
 
+ECDSA primitive hash zero #1
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP192R1
+
+ECDSA primitive hash zero #2
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP224R1
+
+ECDSA primitive hash zero #3
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP256R1
+
+ECDSA primitive hash zero #4
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP384R1
+
+ECDSA primitive hash zero #5
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP521R1
+
 ECDSA primitive random #1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdsa_prim_random:MBEDTLS_ECP_DP_SECP192R1
@@ -33,6 +53,26 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 ecdsa_prim_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF5849120597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B375FA1":"0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD19052A8":"006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEAE643":"00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B956C2F":"DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F":"0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE544320552251":"017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F866472660":0
 
+ECDSA write-read hash zero #1
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP192R1
+
+ECDSA write-read hash zero #2
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP224R1
+
+ECDSA write-read hash zero #3
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP256R1
+
+ECDSA write-read hash zero #4
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP384R1
+
+ECDSA write-read hash zero #5
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP521R1
+
 ECDSA write-read random #1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdsa_write_read_random:MBEDTLS_ECP_DP_SECP192R1
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index e6da884..8157234 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -205,6 +205,38 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void ecdsa_prim_zero( int id )
+{
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point Q;
+    mbedtls_mpi d, r, s;
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    unsigned char buf[MBEDTLS_MD_MAX_SIZE];
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &Q );
+    mbedtls_mpi_init( &d ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
+    memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) );
+    memset( buf, 0, sizeof( buf ) );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_gen_keypair( &grp, &d, &Q,
+                                          &mbedtls_test_rnd_pseudo_rand,
+                                          &rnd_info ) == 0 );
+
+    TEST_ASSERT( mbedtls_ecdsa_sign( &grp, &r, &s, &d, buf, sizeof( buf ),
+                                     &mbedtls_test_rnd_pseudo_rand,
+                                     &rnd_info ) == 0 );
+    TEST_ASSERT( mbedtls_ecdsa_verify( &grp, buf, sizeof( buf ), &Q, &r, &s ) == 0 );
+
+exit:
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &Q );
+    mbedtls_mpi_free( &d ); mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void ecdsa_prim_random( int id )
 {
     mbedtls_ecp_group grp;
@@ -347,6 +379,66 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+void ecdsa_write_read_zero( int id )
+{
+    mbedtls_ecdsa_context ctx;
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    unsigned char hash[32];
+    unsigned char sig[200];
+    size_t sig_len, i;
+
+    mbedtls_ecdsa_init( &ctx );
+    memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) );
+    memset( hash, 0, sizeof( hash ) );
+    memset( sig, 0x2a, sizeof( sig ) );
+
+    /* generate signing key */
+    TEST_ASSERT( mbedtls_ecdsa_genkey( &ctx, id,
+                                       &mbedtls_test_rnd_pseudo_rand,
+                                       &rnd_info ) == 0 );
+
+    /* generate and write signature, then read and verify it */
+    TEST_ASSERT( mbedtls_ecdsa_write_signature( &ctx, MBEDTLS_MD_SHA256,
+                 hash, sizeof( hash ),
+                 sig, &sig_len, &mbedtls_test_rnd_pseudo_rand,
+                 &rnd_info ) == 0 );
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == 0 );
+
+    /* check we didn't write past the announced length */
+    for( i = sig_len; i < sizeof( sig ); i++ )
+        TEST_ASSERT( sig[i] == 0x2a );
+
+    /* try verification with invalid length */
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len - 1 ) != 0 );
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len + 1 ) != 0 );
+
+    /* try invalid sequence tag */
+    sig[0]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) != 0 );
+    sig[0]--;
+
+    /* try modifying r */
+    sig[10]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[10]--;
+
+    /* try modifying s */
+    sig[sig_len - 1]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[sig_len - 1]--;
+
+exit:
+    mbedtls_ecdsa_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
 void ecdsa_write_read_random( int id )
 {
     mbedtls_ecdsa_context ctx;
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index ffa59e5..fe14f88 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -56,7 +56,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: zero-length r
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: no data for r
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51601":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -104,7 +104,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: zero-length r
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: no data for r
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51601":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -170,7 +170,7 @@
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: zero-length r
-read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c800":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c800":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: no data for r
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c801":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -224,7 +224,7 @@
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: zero-length r
-read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d00":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: no data for r
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d20":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 408a9b7..106791c 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -458,6 +458,14 @@
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_test_mul_rng:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660"
 
+ECP point muladd secp256r1 #1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd:MBEDTLS_ECP_DP_SECP256R1:"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579":"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ffffffff20e120e1e1e1e13a4e135157317b79d4ecf329fed4f9eb00dc67dbddae33faca8b6d8a0255b5ce":"04fab65e09aa5dd948320f86246be1d3fc571e7f799d9005170ed5cc868b67598431a668f96aa9fd0b0eb15f0edf4c7fe1be2885eadcb57e3db4fdd093585d3fa6"
+
+ECP point muladd secp256r1 #2
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd:MBEDTLS_ECP_DP_SECP256R1:"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ffffffff20e120e1e1e1e13a4e135157317b79d4ecf329fed4f9eb00dc67dbddae33faca8b6d8a0255b5ce":"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579":"04fab65e09aa5dd948320f86246be1d3fc571e7f799d9005170ed5cc868b67598431a668f96aa9fd0b0eb15f0edf4c7fe1be2885eadcb57e3db4fdd093585d3fa6"
+
 ECP test vectors Curve448 (RFC 7748 6.2, after decodeUCoordinate)
 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
 ecp_test_vec_x:MBEDTLS_ECP_DP_CURVE448:"eb7298a5c0d8c29a1dab27f1a6826300917389449741a974f5bac9d98dc298d46555bce8bae89eeed400584bb046cf75579f51d125498f98":"a01fc432e5807f17530d1288da125b0cd453d941726436c8bbd9c5222c3da7fa639ce03db8d23b274a0721a1aed5227de6e3b731ccf7089b":"ad997351b6106f36b0d1091b929c4c37213e0d2b97e85ebb20c127691d0dad8f1d8175b0723745e639a3cb7044290b99e0e2a0c27a6a301c":"0936f37bc6c1bd07ae3dec7ab5dc06a73ca13242fb343efc72b9d82730b445f3d4b0bd077162a46dcfec6f9b590bfcbcf520cdb029a8b73e":"9d874a5137509a449ad5853040241c5236395435c36424fd560b0cb62b281d285275a740ce32a22dd1740f4aa9161cec95ccc61a18f4ff07"
@@ -508,3 +516,127 @@
 ECP restartable muladd secp256r1 max_ops=250
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":250:4:64
+
+ECP fix_negative: 0, -1, 224
+fix_negative:"00":-1:224
+
+ECP fix_negative: 1, -1, 224
+fix_negative:"01":-1:224
+
+ECP fix_negative: 2^32-1, -1, 224
+fix_negative:"ffffffff":-1:224
+
+ECP fix_negative: 2^32, -1, 224
+fix_negative:"0100000000":-1:224
+
+ECP fix_negative: 2^64-1, -1, 224
+fix_negative:"ffffffffffffffff":-1:224
+
+ECP fix_negative: 2^64, -1, 224
+fix_negative:"010000000000000000":-1:224
+
+ECP fix_negative: 2^128-1, -1, 224
+fix_negative:"ffffffffffffffffffffffffffffffff":-1:224
+
+ECP fix_negative: 2^128, -1, 224
+fix_negative:"0100000000000000000000000000000000":-1:224
+
+ECP fix_negative: 2^128+1, -1, 224
+fix_negative:"0100000000000000000000000000000001":-1:224
+
+ECP fix_negative: 2^224-1, -1, 224
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-1:224
+
+ECP fix_negative: 0, -2, 224
+fix_negative:"00":-2:224
+
+ECP fix_negative: 1, -2, 224
+fix_negative:"01":-2:224
+
+ECP fix_negative: 2^32-1, -2, 224
+fix_negative:"ffffffff":-2:224
+
+ECP fix_negative: 2^32, -2, 224
+fix_negative:"0100000000":-2:224
+
+ECP fix_negative: 2^64-1, -2, 224
+fix_negative:"ffffffffffffffff":-2:224
+
+ECP fix_negative: 2^64, -2, 224
+fix_negative:"010000000000000000":-2:224
+
+ECP fix_negative: 2^128-1, -2, 224
+fix_negative:"ffffffffffffffffffffffffffffffff":-2:224
+
+ECP fix_negative: 2^128, -2, 224
+fix_negative:"0100000000000000000000000000000000":-2:224
+
+ECP fix_negative: 2^128+1, -2, 224
+fix_negative:"0100000000000000000000000000000001":-2:224
+
+ECP fix_negative: 2^224-1, -2, 224
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-2:224
+
+ECP fix_negative: 0, -1, 256
+fix_negative:"00":-1:256
+
+ECP fix_negative: 1, -1, 256
+fix_negative:"01":-1:256
+
+ECP fix_negative: 2^32-1, -1, 256
+fix_negative:"ffffffff":-1:256
+
+ECP fix_negative: 2^32, -1, 256
+fix_negative:"0100000000":-1:256
+
+ECP fix_negative: 2^64-1, -1, 256
+fix_negative:"ffffffffffffffff":-1:256
+
+ECP fix_negative: 2^64, -1, 256
+fix_negative:"010000000000000000":-1:256
+
+ECP fix_negative: 2^128-1, -1, 256
+fix_negative:"ffffffffffffffffffffffffffffffff":-1:256
+
+ECP fix_negative: 2^128, -1, 256
+fix_negative:"0100000000000000000000000000000000":-1:256
+
+ECP fix_negative: 2^128+1, -1, 256
+fix_negative:"0100000000000000000000000000000001":-1:256
+
+ECP fix_negative: 2^256-1, -1, 256
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-1:256
+
+ECP fix_negative: 0, -2, 256
+fix_negative:"00":-2:256
+
+ECP fix_negative: 1, -2, 256
+fix_negative:"01":-2:256
+
+ECP fix_negative: 2^32-1, -2, 256
+fix_negative:"ffffffff":-2:256
+
+ECP fix_negative: 2^32, -2, 256
+fix_negative:"0100000000":-2:256
+
+ECP fix_negative: 2^64-1, -2, 256
+fix_negative:"ffffffffffffffff":-2:256
+
+ECP fix_negative: 2^64, -2, 256
+fix_negative:"010000000000000000":-2:256
+
+ECP fix_negative: 2^128-1, -2, 256
+fix_negative:"ffffffffffffffffffffffffffffffff":-2:256
+
+ECP fix_negative: 2^128, -2, 256
+fix_negative:"0100000000000000000000000000000000":-2:256
+
+ECP fix_negative: 2^128+1, -2, 256
+fix_negative:"0100000000000000000000000000000001":-2:256
+
+ECP fix_negative: 2^256-1, -2, 256
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-2:256
+
+# The first call to fix_negative in the test case of issue #4296.
+ECP fix_negative: #4296.1
+fix_negative:"8A4DD4C8B42C5EAED15FE4F4579F4CE513EC90A94010BF000000000000000000":-1:256
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 4ee75a6..6d23377 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1,6 +1,15 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ecp.h"
 
+#include "ecp_invasive.h"
+
+#if defined(MBEDTLS_TEST_HOOKS) &&                  \
+    ( defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||  \
+      defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
+      defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) )
+#define HAVE_FIX_NEGATIVE
+#endif
+
 #define ECP_PF_UNKNOWN     -1
 
 #define ECP_PT_RESET( x )           \
@@ -752,6 +761,52 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+void ecp_muladd( int id,
+                 data_t *u1_bin, data_t *P1_bin,
+                 data_t *u2_bin, data_t *P2_bin,
+                 data_t *expected_result )
+{
+    /* Compute R = u1 * P1 + u2 * P2 */
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point P1, P2, R;
+    mbedtls_mpi u1, u2;
+    uint8_t actual_result[MBEDTLS_ECP_MAX_PT_LEN];
+    size_t len;
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &P1 );
+    mbedtls_ecp_point_init( &P2 );
+    mbedtls_ecp_point_init( &R );
+    mbedtls_mpi_init( &u1 );
+    mbedtls_mpi_init( &u2 );
+
+    TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, id ) );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &u1, u1_bin->x, u1_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &u2, u2_bin->x, u2_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_read_binary( &grp, &P1,
+                                                  P1_bin->x, P1_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_read_binary( &grp, &P2,
+                                                  P2_bin->x, P2_bin->len ) );
+
+    TEST_EQUAL( 0, mbedtls_ecp_muladd( &grp, &R, &u1, &P1, &u2, &P2 ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_write_binary(
+                    &grp, &R, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                    &len, actual_result, sizeof( actual_result ) ) );
+
+    ASSERT_COMPARE( expected_result->x, expected_result->len,
+                    actual_result, len );
+
+exit:
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &P1 );
+    mbedtls_ecp_point_free( &P2 );
+    mbedtls_ecp_point_free( &R );
+    mbedtls_mpi_free( &u1 );
+    mbedtls_mpi_free( &u2 );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void ecp_fast_mod( int id, char * N_str )
 {
@@ -1152,6 +1207,36 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:HAVE_FIX_NEGATIVE */
+void fix_negative( data_t *N_bin, int c, int bits )
+{
+    mbedtls_mpi C, M, N;
+
+    mbedtls_mpi_init( &C );
+    mbedtls_mpi_init( &M );
+    mbedtls_mpi_init( &N );
+
+    /* C = - c * 2^bits (positive since c is negative) */
+    TEST_EQUAL( 0, mbedtls_mpi_lset( &C, -c ) );
+    TEST_EQUAL( 0, mbedtls_mpi_shift_l( &C, bits ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &N, N_bin->x, N_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &N, C.n ) );
+
+    /* M = N - C = - ( C - N ) (expected result of fix_negative) */
+    TEST_EQUAL( 0, mbedtls_mpi_sub_mpi( &M, &N, &C ) );
+
+    mbedtls_ecp_fix_negative( &N, c, bits );
+
+    TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( &N, &M ) );
+
+exit:
+    mbedtls_mpi_free( &C );
+    mbedtls_mpi_free( &M );
+    mbedtls_mpi_free( &N );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void ecp_selftest(  )
 {
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index b5f6844..59fd782 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -10,21 +10,39 @@
 Base test mpi_read_write_string #1
 mpi_read_write_string:10:"128":10:"128":100:0:0
 
+Base test mpi_read_write_string #1 (Leading 0)
+mpi_read_write_string:10:"0128":10:"128":100:0:0
+
 Base test mpi_read_write_string #2
 mpi_read_write_string:10:"128":16:"80":100:0:0
 
-Base test mpi_read_write_string #3 (Read zero)
+Base test mpi_read_write_string #3 (Read zero decimal)
 mpi_read_write_string:10:"0":10:"0":100:0:0
 
-Base test mpi_read_write_string #3 (Negative decimal) [#1]
+Base test mpi_read_write_string #3 (Read zero hex)
+mpi_read_write_string:16:"0":16:"00":100:0:0
+
+Base test mpi_read_write_string #3 (Read minus zero decimal)
+mpi_read_write_string:10:"-0":10:"0":100:0:0
+
+Base test mpi_read_write_string #3 (Read minus zero hex)
+mpi_read_write_string:16:"-0":16:"00":100:0:0
+
+Base test mpi_read_write_string #3 (Negative decimal)
 mpi_read_write_string:10:"-23":10:"-23":100:0:0
 
-Base test mpi_read_write_string #3 (Negative hex)
+Base test mpi_read_write_string #3 (Negative decimal, leading 0)
+mpi_read_write_string:10:"-023":10:"-23":100:0:0
+
+Base test mpi_read_write_string #3 (Negative hex -> decimal)
 mpi_read_write_string:16:"-20":10:"-32":100:0:0
 
-Base test mpi_read_write_string #3 (Negative decimal) [#2]
+Base test mpi_read_write_string #3 (Negative hex)
 mpi_read_write_string:16:"-23":16:"-23":100:0:0
 
+Base test mpi_read_write_string #3 (Negative hex, leading 0)
+mpi_read_write_string:16:"-023":16:"-23":100:0:0
+
 Base test mpi_read_write_string #4 (Buffer just fits)
 mpi_read_write_string:16:"-4":4:"-10":4:0:0
 
@@ -49,12 +67,18 @@
 Test mpi_read_write_string #7
 mpi_read_write_string:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"0941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":200:0:0
 
-Test mpi_read_write_string #8 (Empty MPI -> hex)
+Test mpi_read_write_string #8 (Empty MPI hex -> hex)
 mpi_read_write_string:16:"":16:"00":4:0:0
 
-Test mpi_read_write_string #9 (Empty MPI -> dec)
+Test mpi_read_write_string #9 (Empty MPI hex -> dec)
 mpi_read_write_string:16:"":10:"0":4:0:0
 
+Test mpi_read_write_string #8 (Empty MPI dec -> hex)
+mpi_read_write_string:10:"":16:"00":4:0:0
+
+Test mpi_read_write_string #9 (Empty MPI dec -> dec)
+mpi_read_write_string:10:"":10:"0":4:0:0
+
 Test mpi_write_string #10 (Negative hex with odd number of digits)
 mpi_read_write_string:16:"-1":16:"":3:0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 450946e..944ef23 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -558,7 +558,7 @@
 
 PSA key policy: AEAD, min-length policy used as algorithm
 depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
-aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:8:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_ERROR_INVALID_ARGUMENT
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:8:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_ERROR_NOT_SUPPORTED
 
 PSA key policy: AEAD, tag length > exact-length policy
 depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 07311e4..241d715 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -195,3 +195,51 @@
 Cipher driver: negative testing on all entry points
 depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_entry_points:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA AEAD encrypt: AES-CCM, 24 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_SUCCESS
+
+PSA AEAD encrypt: AES-CCM, 24 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD encrypt: AES-CCM, 24 bytes, INSUFFICIENT_MEMORY
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_SUCCESS
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1, INSUFFICIENT_MEMORY
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD decrypt: AES-CCM, 39 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_SUCCESS
+
+PSA AEAD decrypt: AES-CCM, 39 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-CCM, 39 bytes, INSUFFICIENT_MEMORY
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1, INSUFFICIENT_MEMORY
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_INSUFFICIENT_MEMORY
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 3e280be..b287ce1 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -809,3 +809,130 @@
     test_driver_cipher_hooks = test_driver_cipher_hooks_init();
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void aead_encrypt( int key_type_arg, data_t *key_data,
+                   int alg_arg,
+                   data_t *nonce,
+                   data_t *additional_data,
+                   data_t *input_data,
+                   data_t *expected_result,
+                   int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output_data = NULL;
+    size_t output_size = 0;
+    size_t output_length = 0;
+    size_t tag_length = PSA_AEAD_TAG_LENGTH( alg );
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    test_driver_aead_hooks = test_driver_aead_hooks_init();
+
+    output_size = input_data->len + tag_length;
+    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+     * should be exact. */
+    TEST_EQUAL( output_size,
+                PSA_AEAD_ENCRYPT_OUTPUT_SIZE( alg, input_data->len ) );
+    TEST_ASSERT( output_size <=
+                 PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    ASSERT_ALLOC( output_data, output_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    test_driver_aead_hooks.forced_status = forced_status;
+    status = psa_aead_encrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x, additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+    TEST_EQUAL( test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( test_driver_aead_hooks.driver_status, forced_status );
+
+    TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
+                        PSA_SUCCESS : forced_status );
+
+    if( status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_result->x, expected_result->len,
+                        output_data, output_length );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output_data );
+    PSA_DONE( );
+    test_driver_aead_hooks = test_driver_aead_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_decrypt( int key_type_arg, data_t *key_data,
+                   int alg_arg,
+                   data_t *nonce,
+                   data_t *additional_data,
+                   data_t *input_data,
+                   data_t *expected_data,
+                   int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output_data = NULL;
+    size_t output_size = 0;
+    size_t output_length = 0;
+    size_t tag_length = PSA_AEAD_TAG_LENGTH( alg );
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    test_driver_aead_hooks = test_driver_aead_hooks_init();
+
+    output_size = input_data->len - tag_length;
+    ASSERT_ALLOC( output_data, output_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    test_driver_aead_hooks.forced_status = forced_status;
+    status = psa_aead_decrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x,
+                               additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+    TEST_EQUAL( test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( test_driver_aead_hooks.driver_status, forced_status );
+
+    TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
+                        PSA_SUCCESS : forced_status );
+
+    if( status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_data->x, expected_data->len,
+                        output_data, output_length );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output_data );
+    PSA_DONE( );
+    test_driver_aead_hooks = test_driver_aead_hooks_init();
+}
+/* END_CASE */
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 2bba78f..54846b5 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -209,8 +209,7 @@
     <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />

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

     <ClInclude Include="..\..\include\psa\crypto.h" />

-    <ClInclude Include="..\..\include\psa\crypto_builtin_cipher.h" />

-    <ClInclude Include="..\..\include\psa\crypto_builtin_hash.h" />

+    <ClInclude Include="..\..\include\psa\crypto_builtin.h" />

     <ClInclude Include="..\..\include\psa\crypto_compat.h" />

     <ClInclude Include="..\..\include\psa\crypto_config.h" />

     <ClInclude Include="..\..\include\psa\crypto_driver_common.h" />

@@ -232,6 +231,7 @@
     <ClInclude Include="..\..\tests\include\test\psa_exercise_key.h" />

     <ClInclude Include="..\..\tests\include\test\psa_helpers.h" />

     <ClInclude Include="..\..\tests\include\test\random.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\aead.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\key_management.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />

@@ -243,6 +243,7 @@
     <ClInclude Include="..\..\library\cipher_wrap.h" />

     <ClInclude Include="..\..\library\common.h" />

     <ClInclude Include="..\..\library\ecp_alt.h" />

+    <ClInclude Include="..\..\library\ecp_invasive.h" />

     <ClInclude Include="..\..\library\entropy_poll.h" />

     <ClInclude Include="..\..\library\md_wrap.h" />

     <ClInclude Include="..\..\library\mps_common.h" />

@@ -251,6 +252,7 @@
     <ClInclude Include="..\..\library\mps_trace.h" />

     <ClInclude Include="..\..\library\padlock.h" />

     <ClInclude Include="..\..\library\pk_wrap.h" />

+    <ClInclude Include="..\..\library\psa_crypto_aead.h" />

     <ClInclude Include="..\..\library\psa_crypto_cipher.h" />

     <ClInclude Include="..\..\library\psa_crypto_core.h" />

     <ClInclude Include="..\..\library\psa_crypto_driver_wrappers.h" />

@@ -328,6 +330,7 @@
     <ClCompile Include="..\..\library\platform_util.c" />

     <ClCompile Include="..\..\library\poly1305.c" />

     <ClCompile Include="..\..\library\psa_crypto.c" />

+    <ClCompile Include="..\..\library\psa_crypto_aead.c" />

     <ClCompile Include="..\..\library\psa_crypto_cipher.c" />

     <ClCompile Include="..\..\library\psa_crypto_client.c" />

     <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />