Merge pull request #246 from gilles-peskine-arm/psa-se_driver-interface_test_strategy

Secure element driver interface test strategy
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 16d7197..81fa6cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -137,8 +137,8 @@
     set(CMAKE_C_FLAGS_RELEASE     "-O2")
     set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
     set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
-    set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -O3")
-    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
+    set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
+    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
     set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
     set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
 endif(CMAKE_COMPILER_IS_GNU)
@@ -149,7 +149,7 @@
     set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
     set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
     set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
-    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
+    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
     set(CMAKE_C_FLAGS_MEMSAN      "-Werror -fsanitize=memory -O3")
     set(CMAKE_C_FLAGS_MEMSANDBG   "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2")
     set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 4d380e0..236c1a2 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -18,7 +18,7 @@
 #### Platform Security Architecture (PSA)
 
 Arm's Platform Security Architecture (PSA) is a holistic set of threat models,
-security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives.
+security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that enables you to design security into both hardware and firmware consistently. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives.
 
 ### Using Mbed Crypto
 
@@ -37,11 +37,11 @@
 
 ### Getting the Mbed Crypto library
 
-Mbed Crypto releases are available in the [public Github repository]( https://github.com/ARMmbed/mbed-crypto).
+Mbed Crypto releases are available in the [public GitHub repository](https://github.com/ARMmbed/mbed-crypto).
 
 ### Building the Mbed Crypto library
 
-You need the following tools to build the library with the provided makefiles:
+**Prerequisites to building the library with the provided makefiles:**
 * GNU Make.
 * A C toolchain (compiler, linker, archiver).
 * Python 2 or Python 3 (either works) to generate the test code.
@@ -49,7 +49,7 @@
 
 If you have a C compiler such as GCC or Clang, just run `make` in the top-level directory to build the library, a set of unit tests and some sample programs.
 
-To select a different compiler, set the `CC` variable to name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`), such as:
+To select a different compiler, set the `CC` variable to the name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`); for example:
 ```
 make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
 ```
@@ -64,13 +64,13 @@
 ### Importing a key
 
 To use a key for cryptography operations in Mbed Crypto, you need to first
-import it. Upon importing, you'll be given a handle to refer to the key for use
+import it. Importing the key creates a handle that refers to the key for use
 with other function calls.
 
-Prerequisites for importing keys:
-* Initialize the library with a successful call to `psa_crypto_init`.
+**Prerequisites to importing keys:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
 
-Importing a key:
+This example shows how to import a key:
 ```C
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -112,23 +112,24 @@
 
 ### Signing a message using RSA
 
-Mbed Crypto provides support for encrypting, decrypting, signing and verifying messages using public key signature algorithms (such as RSA or ECDSA).
+Mbed Crypto supports encrypting, decrypting, signing and verifying messages using public key signature algorithms, such as RSA or ECDSA.
 
-Prerequisites for performing asymmetric signature operations:
-* Initialize the library with a successful call to `psa_crypto_init`.
+**Prerequisites to performing asymmetric signature operations:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
 * Have a valid key with appropriate attributes set:
     * Usage flag `PSA_KEY_USAGE_SIGN` to allow signing.
     * Usage flag `PSA_KEY_USAGE_VERIFY` to allow signature verification.
-    * Algorithm set to desired signature algorithm.
+    * Algorithm set to the desired signature algorithm.
 
-To sign a given `hash` using RSA:
-1. Call `psa_asymmetric_sign()` and get the output buffer that contains the
-   signature:
+This example shows how to sign a hash that has already been calculated:
 ```C
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t key[] = RSA_KEY;
-    uint8_t hash[] = "INPUT_FOR_SIGN";
+    uint8_t hash[32] = {0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
+                        0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
+                        0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
+                        0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
     uint8_t signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
     size_t signature_length;
     psa_key_handle_t handle;
@@ -179,21 +180,21 @@
 
 ### Using symmetric ciphers
 
-Mbed Crypto provides support for encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
+Mbed Crypto supports encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
 
-Prerequisites to working with the symmetric cipher API:
-* Initialize the library with a successful call to `psa_crypto_init`.
-* Configure the key policy accordingly (`PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption).
-* Have a valid key in the key slot.
+**Prerequisites to working with the symmetric cipher API:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
+* Have a handle to a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
 
-Encrypting a message with a symmetric cipher:
+**To encrypt a message with a symmetric cipher:**
 1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
-1. Call `psa_cipher_encrypt_setup` to initialize the operation structure and  specify the algorithm and the key to be used.
-1. Call either `psa_cipher_generate_iv` or `psa_cipher_set_iv` to generate or set the initialization vector (IV). We recommended `psa_cipher_generate_iv`, unless you require a specific IV value.
-1. Call `psa_cipher_update` one or more times, passing either the whole or only a fragment of the message each time.
-1. Call `psa_cipher_finish` to end the operation and output the encrypted message.
+1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
+1. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be used.
+1. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate or set the initialization vector (IV). We recommend calling `psa_cipher_generate_iv()`, unless you require a specific IV value.
+1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
+1. Call `psa_cipher_finish()` to end the operation and output the encrypted message.
 
-Encrypting data using an AES key in cipher block chain (CBC) mode with no padding (assuming all prerequisites have been fulfilled):
+This example shows how to encrypt data using an AES (Advanced Encryption Standard) key in CBC (Cipher Block Chaining) mode with no padding (assuming all prerequisites have been fulfilled):
 ```c
     enum {
         block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
@@ -267,14 +268,15 @@
     mbedtls_psa_crypto_free();
 ```
 
-Decrypting a message with a symmetric cipher:
+**To decrypt a message with a symmetric cipher:**
 1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
-1. Call `psa_cipher_decrypt_setup` to initialize the operation structure and to specify the algorithm and the key to be used.
-1. Call `psa_cipher_set_iv` with the IV for the decryption.
-1. Call `psa_cipher_update` one or more times passing either the whole or only a fragment of the message each time.
-1. Call `psa_cipher_finish` to end the operation and output the decrypted message.
+1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
+1. Call `psa_cipher_decrypt_setup()` to specify the algorithm and the key to be used.
+1. Call `psa_cipher_set_iv()` with the IV for the decryption.
+1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
+1. Call `psa_cipher_finish()` to end the operation and output the decrypted message.
 
-Decrypting encrypted data using an AES key in CBC mode with no padding
+This example shows how to decrypt encrypted data using an AES key in CBC mode with no padding
 (assuming all prerequisites have been fulfilled):
 ```c
     enum {
@@ -350,33 +352,36 @@
 
 #### Handling cipher operation contexts
 
-Once you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup`, you can terminate the operation at any time by calling `psa_cipher_abort`.
+After you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate the operation at any time by calling `psa_cipher_abort()`.
 
-The call to `psa_cipher_abort` frees any resources associated with the operation (except for the operation structure itself). An implicit call to `psa_cipher_abort` occurs when any of these conditions occur:
-* A call to `psa_cipher_generate_iv`, `psa_cipher_set_iv` or `psa_cipher_update` has failed (returning any status other than `PSA_SUCCESS`).
-* Either a successful or failed call to `psa_cipher_finish`.
+The call to `psa_cipher_abort()` frees any resources associated with the operation, except for the operation structure itself.
 
-Once `psa_cipher_abort` has been called (either implicitly by the implementation or explicitly by the user), the operation structure is invalidated and may not be reused for the same operation. However, the operation structure may be reused for a different operation by calling either `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup` again.
+Mbed Crypto implicitly calls `psa_cipher_abort()` when:
+* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
+* A call to `psa_cipher_finish()` succeeds or fails.
 
-For an operation that has been initialized successfully (by a successful call to `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup`) it is imperative that at some time `psa_cipher_abort` is called.
+After an implicit or explicit call to `psa_cipher_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling either `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.
 
-Multiple sequential calls to `psa_cipher_abort` on an operation that has already been terminated (either implicitly or explicitly) are safe and have no effect.
+You must call `psa_cipher_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`).
+
+Making multiple sequential calls to `psa_cipher_abort()` on an operation that is terminated (either implicitly or explicitly) is safe and has no effect.
 
 ### Hashing a message
 
 Mbed Crypto lets you compute and verify hashes using various hashing
 algorithms.
 
-Prerequisites to working with the hash APIs:
-* Initialize the library with a successful call to `psa_crypto_init`.
+**Prerequisites to working with the hash APIs:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
 
-To calculate a hash:
+**To calculate a hash:**
 1. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash functions.
-1. Call `psa_hash_setup` to initialize the operation structure and specify the hash algorithm.
-1. Call `psa_hash_update` one or more times, passing either the whole or only a fragment of the message each time.
-1. Call `psa_hash_finish` to calculate the hash, or `psa_hash_verify` to compare the computed hash with an expected hash value.
+1. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`.
+1. Call `psa_hash_setup()` to specify the hash algorithm.
+1. Call `psa_hash_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
+1. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to compare the computed hash with an expected hash value.
 
-Calculate the `SHA-256` hash of a message:
+This example shows how to calculate the SHA-256 hash of a message:
 ```c
     psa_status_t status;
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -421,7 +426,7 @@
     mbedtls_psa_crypto_free();
 ```
 
-Verify the `SHA-256` hash of a message:
+This example shows how to verify the SHA-256 hash of a message:
 ```c
     psa_status_t status;
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -473,29 +478,29 @@
 
 #### Handling hash operation contexts
 
-Once the operation structure has been successfully initialized by a successful call to `psa_hash_setup`, it's possible to terminate the operation at any time by calling `psa_hash_abort`. The call to `psa_hash_abort` frees any resources associated with the operation (except for the operation structure itself).
+After a successful call to `psa_hash_setup()`, you can terminate the operation at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees any resources associated with the operation, except for the operation structure itself.
 
-An implicit call to `psa_hash_abort` occurs when any of these conditions occur:
-1. A call to `psa_hash_update` has failed (returning any status other than `PSA_SUCCESS`).
-1. Either a successful or failed call to `psa_hash_finish`.
-1. Either a successful or failed call to `psa_hash_verify`.
+Mbed Crypto implicitly calls `psa_hash_abort()` when:
+1. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`).
+1. A call to `psa_hash_finish()` succeeds or fails.
+1. A call to `psa_hash_verify()` succeeds or fails.
 
-Once `psa_hash_abort` has been called (either implicitly by the implementation or explicitly by the user), the operation structure is invalidated and may not be reused for the same operation. However, the operation structure may be reused for a different operation by calling `psa_hash_setup` again.
+After an implicit or explicit call to `psa_hash_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling `psa_hash_setup()` again.
 
-For an operation that has been initialized successfully (by a successful call to `psa_hash_setup`) it is imperative that at some time `psa_hash_abort` is called.
+You must call `psa_hash_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_hash_setup()`) .
 
-Multiple sequential calls to `psa_hash_abort` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect.
+Making multiple sequential calls to `psa_hash_abort()` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect.
 
 ### Generating a random value
 
-Mbed Crypto can generate random data. To generate a random key, use
-`psa_generate_key()` instead of `psa_generate_random()`
+Mbed Crypto can generate random data.
 
-Prerequisites to random generation:
+**Prerequisites to generating random data:**
 * Initialize the library with a successful call to `psa_crypto_init()`.
 
-Generate a random, ten-byte piece of data:
-1. Generate random bytes by calling `psa_generate_random()`:
+<span class="notes">**Note:** To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.</span>
+
+This example shows how to generate ten bytes of random data by calling `psa_generate_random()`:
 ```C
     psa_status_t status;
     uint8_t random[10] = { 0 };
@@ -527,35 +532,38 @@
 Mbed Crypto provides a key derivation API that lets you derive new keys from
 existing ones. The key derivation API has functions to take inputs, including
 other keys and data, and functions to generate outputs, such as new keys or
-other data. A key derivation context must first be initialized and set up,
-provided with a key and optionally other data, and then derived data can be
-read from it either to a buffer or directly sent to a key slot. Refer to the
-documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
-information on which inputs to pass when and when you can obtain which outputs.
+other data.
 
-Prerequisites to working with the key derivation APIs:
-* Initialize the library with a successful call to `psa_crypto_init`.
+You must first initialize and set up a key derivation context,
+provided with a key and, optionally, other data. Then, use the key derivation context to either read derived data to a buffer or send derived data directly to a key slot.
+
+See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
+information about which inputs to pass when, and when you can obtain which outputs.
+
+**Prerequisites to working with the key derivation APIs:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
 * Use a key with the appropriate attributes set:
     * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
     * Key type set to `PSA_KEY_TYPE_DERIVE`.
     * Algorithm set to a key derivation algorithm
-      (`PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
+      (for example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
 
-Deriving a new AES-CTR 128-bit encryption key into a given key slot using HKDF
-with a given key, salt and info:
-1. Set up the key derivation context using the `psa_key_derivation_setup`
+**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
+with a given key, salt and info:**
+
+1. Set up the key derivation context using the `psa_key_derivation_setup()`
 function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
-1. Provide an optional salt with `psa_key_derivation_input_bytes`.
-1. Provide info with `psa_key_derivation_input_bytes`.
-1. Provide secret with `psa_key_derivation_input_key`, referencing a key that
+1. Provide an optional salt with `psa_key_derivation_input_bytes()`.
+1. Provide info with `psa_key_derivation_input_bytes()`.
+1. Provide a secret with `psa_key_derivation_input_key()`, referencing a key that
    can be used for key derivation.
 1. Set the key attributes desired for the new derived key. We'll set
-   `PSA_KEY_USAGE_ENCRYPT` parameter and the algorithm `PSA_ALG_CTR` for this
+   the `PSA_KEY_USAGE_ENCRYPT` usage flag and the `PSA_ALG_CTR` algorithm for this
    example.
 1. Derive the key by calling `psa_key_derivation_output_key()`.
 1. Clean up the key derivation context.
 
-At this point the derived key slot holds a new 128-bit AES-CTR encryption key
+At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
 derived from the key, salt and info provided:
 ```C
     psa_status_t status;
@@ -659,14 +667,13 @@
 
 ### Authenticating and encrypting or decrypting a message
 
-Mbed Crypto provides a simple way for authenticate and encrypt with associated data (AEAD) supporting `PSA_ALG_CCM` algorithm.
+Mbed Crypto provides a simple way to authenticate and encrypt with associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm.
 
-Prerequisites to working with the AEAD ciphers APIs:
-* Initialize the library with a successful call to `psa_crypto_init`.
-* The key attributes for the key used for derivation must have usage flags
-  `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT`.
+**Prerequisites to working with the AEAD cipher APIs:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
+* The key attributes for the key used for derivation must have the `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags.
 
-To authenticate and encrypt a message:
+This example shows how to authenticate and encrypt a message:
 ```C
     psa_status_t status;
     static const uint8_t key[] = {
@@ -737,7 +744,7 @@
     mbedtls_psa_crypto_free();
 ```
 
-To authenticate and decrypt a message:
+This example shows how to authenticate and decrypt a message:
 
 ```C
     psa_status_t status;
@@ -816,18 +823,15 @@
 
 Mbed Crypto provides a simple way to generate a key or key pair.
 
-Prerequisites to using key generation and export APIs:
-* Initialize the library with a successful call to `psa_crypto_init`.
+**Prerequisites to using key generation and export APIs:**
+* Initialize the library with a successful call to `psa_crypto_init()`.
 
-Generate an ECDSA key:
+**To generate an ECDSA key:**
 1. Set the desired key attributes for key generation by calling
    `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
-   `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). We don't set
-   `PSA_KEY_USAGE_EXPORT` as we only want to export the public key, not the key
-   pair (or private key).
+   `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). You only want to export the public key, not the key pair (or private key); therefore, do not set `PSA_KEY_USAGE_EXPORT`.
 1. Generate a key by calling `psa_generate_key()`.
-1. Export the generated public key by calling `psa_export_public_key()`
-:
+1. Export the generated public key by calling `psa_export_public_key()`:
 ```C
     enum {
         key_bits = 256,
@@ -877,8 +881,6 @@
     mbedtls_psa_crypto_free();
 ```
 
-### More about the Mbed Crypto library
+### More about the PSA Crypto API
 
-More information on [Mbed Crypto](https://github.com/ARMmbed/mbed-crypto/).
-
-More information on [PSA Crypto](https://github.com/ARMmbed/mbed-crypto/blob/development/docs/PSA_Crypto_API_Overview.pdf).
+For more information about the PSA Crypto API, please see the [PSA Cryptography API Specification](https://armmbed.github.io/mbed-crypto/html/index.html).
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 3c1430c..e14fc74 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -441,6 +441,16 @@
  *            dependencies on them, and considering stronger message digests
  *            and ciphers instead.
  *
+ * \warning   If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are
+ *            enabled, then the deterministic ECDH signature functions pass the
+ *            the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore
+ *            alternative implementations should use the RNG only for generating
+ *            the ephemeral key and nothing else. If this is not possible, then
+ *            MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative
+ *            implementation should be provided for mbedtls_ecdsa_sign_det_ext()
+ *            (and for mbedtls_ecdsa_sign_det() too if backward compatibility is
+ *            desirable).
+ *
  */
 //#define MBEDTLS_MD2_PROCESS_ALT
 //#define MBEDTLS_MD4_PROCESS_ALT
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index ad51188..b009e73 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -176,6 +176,12 @@
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED    __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
 /**
  * \brief           This function computes the ECDSA signature of a
  *                  previously-hashed message, deterministic version.
@@ -190,6 +196,19 @@
  *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
  *                  4.1.3, step 5.
  *
+ * \warning         Since the output of the internal RNG is always the same for
+ *                  the same key and message, this limits the efficiency of
+ *                  blinding and leaks information through side channels. For
+ *                  secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
+ *
+ *                  (Optimally the blinding is a random value that is different
+ *                  on every execution. In this case the blinding is still
+ *                  random from the attackers perspective, but is the same on
+ *                  each execution. This means that this blinding does not
+ *                  prevent attackers from recovering secrets by combining
+ *                  several measurement traces, but may prevent some attacks
+ *                  that exploit relationships between secret data.)
+ *
  * \see             ecp.h
  *
  * \param grp       The context for the elliptic curve to use.
@@ -214,7 +233,55 @@
 int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
                             mbedtls_mpi *s, const mbedtls_mpi *d,
                             const unsigned char *buf, size_t blen,
-                            mbedtls_md_type_t md_alg );
+                            mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED;
+#undef MBEDTLS_DEPRECATED
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/**
+ * \brief           This function computes the ECDSA signature of a
+ *                  previously-hashed message, deterministic version.
+ *
+ *                  For more information, see <em>RFC-6979: Deterministic
+ *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
+ *                  Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note            If the bitlength of the message hash is larger than the
+ *                  bitlength of the group order, then the hash is truncated as
+ *                  defined in <em>Standards for Efficient Cryptography Group
+ *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ *                  4.1.3, step 5.
+ *
+ * \see             ecp.h
+ *
+ * \param grp           The context for the elliptic curve to use.
+ *                      This must be initialized and have group parameters
+ *                      set, for example through mbedtls_ecp_group_load().
+ * \param r             The MPI context in which to store the first part
+ *                      the signature. This must be initialized.
+ * \param s             The MPI context in which to store the second part
+ *                      the signature. This must be initialized.
+ * \param d             The private signing key. This must be initialized
+ *                      and setup, for example through mbedtls_ecp_gen_privkey().
+ * \param buf           The hashed content to be signed. This must be a readable
+ *                      buffer of length \p blen Bytes. It may be \c NULL if
+ *                      \p blen is zero.
+ * \param blen          The length of \p buf in Bytes.
+ * \param md_alg        The hash algorithm used to hash the original data.
+ * \param f_rng_blind   The RNG function used for blinding. This must not be
+ *                      \c NULL.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
+ *                      \c NULL if \p f_rng doesn't need a context parameter.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
+ *                  error code on failure.
+ */
+int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                            mbedtls_mpi *s, const mbedtls_mpi *d,
+                            const unsigned char *buf, size_t blen,
+                            mbedtls_md_type_t md_alg,
+                            int (*f_rng_blind)(void *, unsigned char *, size_t),
+                            void *p_rng_blind );
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
 /**
@@ -293,7 +360,8 @@
  *                  the signature written. Must not be \c NULL.
  * \param f_rng     The RNG function. This must not be \c NULL if
  *                  #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
- *                  it is unused and may be set to \c NULL.
+ *                  it is used only for blinding and may be set to \c NULL, but
+ *                  doing so is DEPRECATED.
  * \param p_rng     The RNG context to be passed to \p f_rng. This may be
  *                  \c NULL if \p f_rng is \c NULL or doesn't use a context.
  *
diff --git a/include/mbedtls/md_internal.h b/include/mbedtls/md_internal.h
index 267ceba..bb876ef 100644
--- a/include/mbedtls/md_internal.h
+++ b/include/mbedtls/md_internal.h
@@ -46,42 +46,17 @@
  */
 struct mbedtls_md_info_t
 {
-    /** Digest identifier */
-    mbedtls_md_type_t type;
-
     /** Name of the message digest */
     const char * name;
 
+    /** Digest identifier */
+    mbedtls_md_type_t type;
+
     /** Output length of the digest function in bytes */
-    int size;
+    unsigned char size;
 
     /** Block length of the digest function in bytes */
-    int block_size;
-
-    /** Digest initialisation function */
-    int (*starts_func)( void *ctx );
-
-    /** Digest update function */
-    int (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
-
-    /** Digest finalisation function */
-    int (*finish_func)( void *ctx, unsigned char *output );
-
-    /** Generic digest function */
-    int (*digest_func)( const unsigned char *input, size_t ilen,
-                        unsigned char *output );
-
-    /** Allocate a new context */
-    void * (*ctx_alloc_func)( void );
-
-    /** Free the given context */
-    void (*ctx_free_func)( void *ctx );
-
-    /** Clone state from a context */
-    void (*clone_func)( void *dst, const void *src );
-
-    /** Internal use only */
-    int (*process_func)( void *ctx, const unsigned char *input );
+    unsigned char block_size;
 };
 
 #if defined(MBEDTLS_MD2_C)
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 0d8cbfa..5288815 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -328,6 +328,12 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_get_key_attributes(psa_key_handle_t handle,
                                     psa_key_attributes_t *attributes);
@@ -361,15 +367,18 @@
  * keys that can be opened with psa_open_key(). Such keys have a key identifier
  * in the vendor range, as documented in the description of #psa_key_id_t.
  *
- * The application must eventually close the handle with psa_close_key()
- * to release associated resources. If the application dies without calling
- * psa_close_key(), the implementation should perform the equivalent of a
- * call to psa_close_key().
+ * The application must eventually close the handle with psa_close_key() or
+ * psa_destroy_key() to release associated resources. If the application dies
+ * without calling one of these functions, the implementation should perform
+ * the equivalent of a call to psa_close_key().
  *
  * Some implementations permit an application to open the same key multiple
- * times. Applications that rely on this behavior will not be portable to
- * implementations that only permit a single key handle to be opened. See
- * also :ref:\`key-handles\`.
+ * times. If this is successful, each call to psa_open_key() will return a
+ * different key handle.
+ *
+ * \note Applications that rely on opening a key multiple times will not be
+ * portable to implementations that only permit a single key handle to be
+ * opened. See also :ref:\`key-handles\`.
  *
  * \param id            The persistent identifier of the key.
  * \param[out] handle   On success, a handle to the key.
@@ -392,7 +401,12 @@
  *         define any way to create such a key, but it may be possible
  *         through implementation-specific means.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_open_key(psa_key_id_t id,
                           psa_key_handle_t *handle);
@@ -411,289 +425,24 @@
  * Closing the key handle makes the handle invalid, and the key handle
  * must not be used again by the application.
  *
- * If the key is currently in use in a multipart operation, then closing the
- * last remaining handle to the key will abort the multipart operation.
+ * \note If the key handle was used to set up an active
+ * :ref:\`multipart operation <multipart-operations>\`, then closing the
+ * key handle can cause the multipart operation to fail. Applications should
+ * maintain the key handle until after the multipart operation has finished.
  *
  * \param handle        The key handle to close.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_close_key(psa_key_handle_t handle);
 
-/**@}*/
-
-/** \defgroup import_export Key import and export
- * @{
- */
-
-/**
- * \brief Import a key in binary format.
- *
- * This function supports any output from psa_export_key(). Refer to the
- * documentation of psa_export_public_key() for the format of public keys
- * and to the documentation of psa_export_key() for the format for
- * other key types.
- *
- * This specification supports a single format for each key type.
- * Implementations may support other formats as long as the standard
- * format is supported. Implementations that support other formats
- * should ensure that the formats are clearly unambiguous so as to
- * minimize the risk that an invalid input is accidentally interpreted
- * according to a different format.
- *
-
- * \param[in] attributes    The attributes for the new key.
- *                          The key size is always determined from the
- *                          \p data buffer.
- *                          If the key size in \p attributes is nonzero,
- *                          it must be equal to the size from \p data.
- * \param[out] handle       On success, a handle to the newly created key.
- *                          \c 0 on failure.
- * \param[in] data    Buffer containing the key data. The content of this
- *                    buffer is interpreted according to the type declared
- *                    in \p attributes.
- *                    All implementations must support at least the format
- *                    described in the documentation
- *                    of psa_export_key() or psa_export_public_key() for
- *                    the chosen type. Implementations may allow other
- *                    formats, but should be conservative: implementations
- *                    should err on the side of rejecting content if it
- *                    may be erroneous (e.g. wrong type or truncated data).
- * \param data_length Size of the \p data buffer in bytes.
- *
- * \retval #PSA_SUCCESS
- *         Success.
- *         If the key is persistent, the key material and the key's metadata
- *         have been saved to persistent storage.
- * \retval #PSA_ERROR_ALREADY_EXISTS
- *         This is an attempt to create a persistent key, and there is
- *         already a persistent key with the given identifier.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- *         The key type or key size is not supported, either by the
- *         implementation in general or in this particular persistent location.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key attributes, as a whole, are invalid.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key data is not correctly formatted.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The size in \p attributes is nonzero and does not match the size
- *         of the key data.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_STORAGE_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
-                            const uint8_t *data,
-                            size_t data_length,
-                            psa_key_handle_t *handle);
-
-/**
- * \brief Destroy a key.
- *
- * This function destroys a key from both volatile
- * memory and, if applicable, non-volatile storage. Implementations shall
- * make a best effort to ensure that that the key material cannot be recovered.
- *
- * This function also erases any metadata such as policies and frees all
- * resources associated with the key.
- *
- * Destroying a key will invalidate all existing handles to the key.
- *
- * If the key is currently in use in a multipart operation, then destroying the
- * key will abort the multipart operation.
- *
- * \param handle        Handle to the key to erase.
- *
- * \retval #PSA_SUCCESS
- *         The key material has been erased.
- * \retval #PSA_ERROR_NOT_PERMITTED
- *         The key cannot be erased because it is
- *         read-only, either due to a policy or due to physical restrictions.
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- *         There was an failure in communication with the cryptoprocessor.
- *         The key material may still be present in the cryptoprocessor.
- * \retval #PSA_ERROR_STORAGE_FAILURE
- *         The storage is corrupted. Implementations shall make a best effort
- *         to erase key material even in this stage, however applications
- *         should be aware that it may be impossible to guarantee that the
- *         key material is not recoverable in such cases.
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- *         An unexpected condition which is not a storage corruption or
- *         a communication failure occurred. The cryptoprocessor may have
- *         been compromised.
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_destroy_key(psa_key_handle_t handle);
-
-/**
- * \brief Export a key in binary format.
- *
- * The output of this function can be passed to psa_import_key() to
- * create an equivalent object.
- *
- * If the implementation of psa_import_key() supports other formats
- * beyond the format specified here, the output from psa_export_key()
- * must use the representation specified here, not the original
- * representation.
- *
- * For standard key types, the output format is as follows:
- *
- * - For symmetric keys (including MAC keys), the format is the
- *   raw bytes of the key.
- * - For DES, the key data consists of 8 bytes. The parity bits must be
- *   correct.
- * - For Triple-DES, the format is the concatenation of the
- *   two or three DES keys.
- * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format
- *   is the non-encrypted DER encoding of the representation defined by
- *   PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0.
- *   ```
- *   RSAPrivateKey ::= SEQUENCE {
- *       version             INTEGER,  -- must be 0
- *       modulus             INTEGER,  -- n
- *       publicExponent      INTEGER,  -- e
- *       privateExponent     INTEGER,  -- d
- *       prime1              INTEGER,  -- p
- *       prime2              INTEGER,  -- q
- *       exponent1           INTEGER,  -- d mod (p-1)
- *       exponent2           INTEGER,  -- d mod (q-1)
- *       coefficient         INTEGER,  -- (inverse of q) mod p
- *   }
- *   ```
- * - For elliptic curve key pairs (key types for which
- *   #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is
- *   a representation of the private value as a `ceiling(m/8)`-byte string
- *   where `m` is the bit size associated with the curve, i.e. the bit size
- *   of the order of the curve's coordinate field. This byte string is
- *   in little-endian order for Montgomery curves (curve types
- *   `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass
- *   curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX`
- *   and `PSA_ECC_CURVE_BRAINPOOL_PXXX`).
- *   This is the content of the `privateKey` field of the `ECPrivateKey`
- *   format defined by RFC 5915.
- * - For Diffie-Hellman key exchange key pairs (key types for which
- *   #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the
- *   format is the representation of the private key `x` as a big-endian byte
- *   string. The length of the byte string is the private key size in bytes
- *   (leading zeroes are not stripped).
- * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is
- *   true), the format is the same as for psa_export_public_key().
- *
- * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set.
- *
- * \param handle            Handle to the key to export.
- * \param[out] data         Buffer where the key data is to be written.
- * \param data_size         Size of the \p data buffer in bytes.
- * \param[out] data_length  On success, the number of bytes
- *                          that make up the key data.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- * \retval #PSA_ERROR_NOT_PERMITTED
- *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- *         The size of the \p data buffer is too small. You can determine a
- *         sufficient buffer size by calling
- *         #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits)
- *         where \c type is the key type
- *         and \c bits is the key size in bits.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_export_key(psa_key_handle_t handle,
-                            uint8_t *data,
-                            size_t data_size,
-                            size_t *data_length);
-
-/**
- * \brief Export a public key or the public part of a key pair in binary format.
- *
- * The output of this function can be passed to psa_import_key() to
- * create an object that is equivalent to the public key.
- *
- * This specification supports a single format for each key type.
- * Implementations may support other formats as long as the standard
- * format is supported. Implementations that support other formats
- * should ensure that the formats are clearly unambiguous so as to
- * minimize the risk that an invalid input is accidentally interpreted
- * according to a different format.
- *
- * For standard key types, the output format is as follows:
- * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of
- *   the representation defined by RFC 3279 &sect;2.3.1 as `RSAPublicKey`.
- *   ```
- *   RSAPublicKey ::= SEQUENCE {
- *      modulus            INTEGER,    -- n
- *      publicExponent     INTEGER  }  -- e
- *   ```
- * - For elliptic curve public keys (key types for which
- *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
- *   representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.
- *   Let `m` be the bit size associated with the curve, i.e. the bit size of
- *   `q` for a curve over `F_q`. The representation consists of:
- *      - The byte 0x04;
- *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
- *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
- * - For Diffie-Hellman key exchange public keys (key types for which
- *   #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true),
- *   the format is the representation of the public key `y = g^x mod p` as a
- *   big-endian byte string. The length of the byte string is the length of the
- *   base prime `p` in bytes.
- *
- * Exporting a public key object or the public part of a key pair is
- * always permitted, regardless of the key's usage flags.
- *
- * \param handle            Handle to the key to export.
- * \param[out] data         Buffer where the key data is to be written.
- * \param data_size         Size of the \p data buffer in bytes.
- * \param[out] data_length  On success, the number of bytes
- *                          that make up the key data.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key is neither a public key nor a key pair.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- *         The size of the \p data buffer is too small. You can determine a
- *         sufficient buffer size by calling
- *         #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
- *         where \c type is the key type
- *         and \c bits is the key size in bits.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_export_public_key(psa_key_handle_t handle,
-                                   uint8_t *data,
-                                   size_t data_size,
-                                   size_t *data_length);
-
 /** Make a copy of a key.
  *
  * Copy key material from one location to another.
@@ -771,12 +520,301 @@
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_copy_key(psa_key_handle_t source_handle,
                           const psa_key_attributes_t *attributes,
                           psa_key_handle_t *target_handle);
 
+
+/**
+ * \brief Destroy a key.
+ *
+ * This function destroys a key from both volatile
+ * memory and, if applicable, non-volatile storage. Implementations shall
+ * make a best effort to ensure that that the key material cannot be recovered.
+ *
+ * This function also erases any metadata such as policies and frees
+ * resources associated with the key. To free all resources associated with
+ * the key, all handles to the key must be closed or destroyed.
+ *
+ * Destroying the key makes the handle invalid, and the key handle
+ * must not be used again by the application. Using other open handles to the
+ * destroyed key in a cryptographic operation will result in an error.
+ *
+ * If a key is currently in use in a multipart operation, then destroying the
+ * key will cause the multipart operation to fail.
+ *
+ * \param handle        Handle to the key to erase.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key material has been erased.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key cannot be erased because it is
+ *         read-only, either due to a policy or due to physical restrictions.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ *         There was an failure in communication with the cryptoprocessor.
+ *         The key material may still be present in the cryptoprocessor.
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The storage is corrupted. Implementations shall make a best effort
+ *         to erase key material even in this stage, however applications
+ *         should be aware that it may be impossible to guarantee that the
+ *         key material is not recoverable in such cases.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *         An unexpected condition which is not a storage corruption or
+ *         a communication failure occurred. The cryptoprocessor may have
+ *         been compromised.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_destroy_key(psa_key_handle_t handle);
+
+/**@}*/
+
+/** \defgroup import_export Key import and export
+ * @{
+ */
+
+/**
+ * \brief Import a key in binary format.
+ *
+ * This function supports any output from psa_export_key(). Refer to the
+ * documentation of psa_export_public_key() for the format of public keys
+ * and to the documentation of psa_export_key() for the format for
+ * other key types.
+ *
+ * This specification supports a single format for each key type.
+ * Implementations may support other formats as long as the standard
+ * format is supported. Implementations that support other formats
+ * should ensure that the formats are clearly unambiguous so as to
+ * minimize the risk that an invalid input is accidentally interpreted
+ * according to a different format.
+ *
+
+ * \param[in] attributes    The attributes for the new key.
+ *                          The key size is always determined from the
+ *                          \p data buffer.
+ *                          If the key size in \p attributes is nonzero,
+ *                          it must be equal to the size from \p data.
+ * \param[out] handle       On success, a handle to the newly created key.
+ *                          \c 0 on failure.
+ * \param[in] data    Buffer containing the key data. The content of this
+ *                    buffer is interpreted according to the type declared
+ *                    in \p attributes.
+ *                    All implementations must support at least the format
+ *                    described in the documentation
+ *                    of psa_export_key() or psa_export_public_key() for
+ *                    the chosen type. Implementations may allow other
+ *                    formats, but should be conservative: implementations
+ *                    should err on the side of rejecting content if it
+ *                    may be erroneous (e.g. wrong type or truncated data).
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular persistent location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key attributes, as a whole, are invalid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key data is not correctly formatted.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size in \p attributes is nonzero and does not match the size
+ *         of the key data.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         \p operation is either not initialized or is in use
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
+                            const uint8_t *data,
+                            size_t data_length,
+                            psa_key_handle_t *handle);
+
+
+
+/**
+ * \brief Export a key in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an equivalent object.
+ *
+ * If the implementation of psa_import_key() supports other formats
+ * beyond the format specified here, the output from psa_export_key()
+ * must use the representation specified here, not the original
+ * representation.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For symmetric keys (including MAC keys), the format is the
+ *   raw bytes of the key.
+ * - For DES, the key data consists of 8 bytes. The parity bits must be
+ *   correct.
+ * - For Triple-DES, the format is the concatenation of the
+ *   two or three DES keys.
+ * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format
+ *   is the non-encrypted DER encoding of the representation defined by
+ *   PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0.
+ *   ```
+ *   RSAPrivateKey ::= SEQUENCE {
+ *       version             INTEGER,  -- must be 0
+ *       modulus             INTEGER,  -- n
+ *       publicExponent      INTEGER,  -- e
+ *       privateExponent     INTEGER,  -- d
+ *       prime1              INTEGER,  -- p
+ *       prime2              INTEGER,  -- q
+ *       exponent1           INTEGER,  -- d mod (p-1)
+ *       exponent2           INTEGER,  -- d mod (q-1)
+ *       coefficient         INTEGER,  -- (inverse of q) mod p
+ *   }
+ *   ```
+ * - For elliptic curve key pairs (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is
+ *   a representation of the private value as a `ceiling(m/8)`-byte string
+ *   where `m` is the bit size associated with the curve, i.e. the bit size
+ *   of the order of the curve's coordinate field. This byte string is
+ *   in little-endian order for Montgomery curves (curve types
+ *   `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass
+ *   curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX`
+ *   and `PSA_ECC_CURVE_BRAINPOOL_PXXX`).
+ *   This is the content of the `privateKey` field of the `ECPrivateKey`
+ *   format defined by RFC 5915.
+ * - For Diffie-Hellman key exchange key pairs (key types for which
+ *   #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the
+ *   format is the representation of the private key `x` as a big-endian byte
+ *   string. The length of the byte string is the private key size in bytes
+ *   (leading zeroes are not stripped).
+ * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is
+ *   true), the format is the same as for psa_export_public_key().
+ *
+ * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set.
+ *
+ * \param handle            Handle to the key to export.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p data buffer is too small. You can determine a
+ *         sufficient buffer size by calling
+ *         #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits)
+ *         where \c type is the key type
+ *         and \c bits is the key size in bits.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_export_key(psa_key_handle_t handle,
+                            uint8_t *data,
+                            size_t data_size,
+                            size_t *data_length);
+
+/**
+ * \brief Export a public key or the public part of a key pair in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an object that is equivalent to the public key.
+ *
+ * This specification supports a single format for each key type.
+ * Implementations may support other formats as long as the standard
+ * format is supported. Implementations that support other formats
+ * should ensure that the formats are clearly unambiguous so as to
+ * minimize the risk that an invalid input is accidentally interpreted
+ * according to a different format.
+ *
+ * For standard key types, the output format is as follows:
+ * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of
+ *   the representation defined by RFC 3279 &sect;2.3.1 as `RSAPublicKey`.
+ *   ```
+ *   RSAPublicKey ::= SEQUENCE {
+ *      modulus            INTEGER,    -- n
+ *      publicExponent     INTEGER  }  -- e
+ *   ```
+ * - For elliptic curve public keys (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
+ *   representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.
+ *   Let `m` be the bit size associated with the curve, i.e. the bit size of
+ *   `q` for a curve over `F_q`. The representation consists of:
+ *      - The byte 0x04;
+ *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+ *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
+ * - For Diffie-Hellman key exchange public keys (key types for which
+ *   #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true),
+ *   the format is the representation of the public key `y = g^x mod p` as a
+ *   big-endian byte string. The length of the byte string is the length of the
+ *   base prime `p` in bytes.
+ *
+ * Exporting a public key object or the public part of a key pair is
+ * always permitted, regardless of the key's usage flags.
+ *
+ * \param handle            Handle to the key to export.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key is neither a public key nor a key pair.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p data buffer is too small. You can determine a
+ *         sufficient buffer size by calling
+ *         #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
+ *         where \c type is the key type
+ *         and \c bits is the key size in bits.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_export_public_key(psa_key_handle_t handle,
+                                   uint8_t *data,
+                                   size_t data_size,
+                                   size_t *data_length);
+
+
+
 /**@}*/
 
 /** \defgroup hash Message digests
@@ -802,10 +840,18 @@
  *         Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a hash algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p hash_size is too small
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_compute(psa_algorithm_t alg,
                               const uint8_t *input,
@@ -831,10 +877,17 @@
  *         differs from the expected hash.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a hash algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p input_length or \p hash_length do not match the hash size for \p alg
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_compare(psa_algorithm_t alg,
                               const uint8_t *input,
@@ -921,7 +974,9 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_NOT_SUPPORTED
- *         \p alg is not supported or is not a hash algorithm.
+ *         \p alg is not a supported hash algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p alg is not a hash algorithm.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (already set up and not
  *         subsequently completed).
@@ -929,6 +984,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         \p operation is either not initialized or is in use
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
                             psa_algorithm_t alg);
@@ -951,6 +1012,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_update(psa_hash_operation_t *operation,
                              const uint8_t *input,
@@ -992,6 +1059,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
                              uint8_t *hash,
@@ -1028,6 +1101,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
                              const uint8_t *hash,
@@ -1059,6 +1138,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
 
@@ -1085,6 +1170,15 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is either not initialized or has already been setup.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is either not initialized or has already been setup.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
                             psa_hash_operation_t *target_operation);
@@ -1123,10 +1217,14 @@
  *         \p handle is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p mac_size is too small
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1165,6 +1263,12 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The key could not be retrieved from storage.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_mac_verify(psa_key_handle_t handle,
                             psa_algorithm_t alg,
@@ -1258,7 +1362,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p handle is not compatible with \p alg.
@@ -1268,6 +1371,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The key could not be retrieved from storage.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (already set up and not
  *         subsequently completed).
@@ -1318,7 +1423,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c key is not compatible with \c alg.
@@ -1328,6 +1432,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         The key could not be retrieved from storage
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (already set up and not
  *         subsequently completed).
@@ -1360,6 +1466,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_mac_update(psa_mac_operation_t *operation,
                             const uint8_t *input,
@@ -1402,6 +1513,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
                                  uint8_t *mac,
@@ -1438,6 +1554,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
                                    const uint8_t *mac,
@@ -1470,6 +1591,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
 
@@ -1512,6 +1637,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_encrypt(psa_key_handle_t handle,
                                 psa_algorithm_t alg,
@@ -1552,7 +1682,12 @@
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_decrypt(psa_key_handle_t handle,
                                 psa_algorithm_t alg,
@@ -1648,7 +1783,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p handle is not compatible with \p alg.
@@ -1658,6 +1792,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (already set up and not
  *         subsequently completed).
@@ -1710,7 +1845,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p handle is not compatible with \p alg.
@@ -1720,6 +1854,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (already set up and not
  *         subsequently completed).
@@ -1759,6 +1894,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
                                     uint8_t *iv,
@@ -1794,6 +1934,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
                                const uint8_t *iv,
@@ -1830,6 +1975,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
                                const uint8_t *input,
@@ -1859,6 +2009,14 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The total input size passed to this operation is not valid for
+ *         this particular algorithm. For example, the algorithm is a based
+ *         on block cipher and requires a whole number of blocks, but the
+ *         total input size is not a multiple of the block size.
+ * \retval #PSA_ERROR_INVALID_PADDING
+ *         This is a decryption operation for an algorithm that includes
+ *         padding, and the ciphertext does not contain valid padding.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (not set up, IV required but
  *         not set, or already completed).
@@ -1868,6 +2026,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
                                uint8_t *output,
@@ -1901,6 +2064,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
 
@@ -1941,16 +2108,18 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p handle is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p ciphertext_size is too small
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -1997,7 +2166,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The ciphertext is not authentic.
  * \retval #PSA_ERROR_NOT_PERMITTED
@@ -2006,9 +2174,12 @@
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p plaintext_size or \p nonce_length is too small
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2127,6 +2298,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2188,6 +2360,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2225,6 +2398,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
                                      uint8_t *nonce,
@@ -2259,6 +2437,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
                                 const uint8_t *nonce,
@@ -2297,6 +2480,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
                                   size_t ad_length,
@@ -2339,6 +2526,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
                                 const uint8_t *input,
@@ -2411,6 +2603,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_update(psa_aead_operation_t *operation,
                              const uint8_t *input,
@@ -2480,6 +2677,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
                              uint8_t *ciphertext,
@@ -2538,6 +2740,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
                              uint8_t *plaintext,
@@ -2573,6 +2780,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
 
@@ -2603,6 +2814,8 @@
  *                              that make up the returned signature value.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p signature buffer is too small. You can
  *         determine a sufficient buffer size by calling
@@ -2615,6 +2828,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
@@ -2650,6 +2864,8 @@
  *
  * \retval #PSA_SUCCESS
  *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The calculation was perfomed successfully, but the passed
  *         signature is not a valid signature.
@@ -2659,6 +2875,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -2700,6 +2917,8 @@
  *                              that make up the returned output.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
@@ -2712,6 +2931,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
@@ -2756,6 +2976,8 @@
  *                              that make up the returned output.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p output buffer is too small. You can
  *         determine a sufficient buffer size by calling
@@ -2768,6 +2990,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
  * \retval #PSA_ERROR_INVALID_PADDING
  * \retval #PSA_ERROR_BAD_STATE
@@ -2881,7 +3104,13 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is either not initialized or has already been setup.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_setup(
     psa_key_derivation_operation_t *operation,
@@ -2897,8 +3126,15 @@
  * \param[out] capacity     On success, the capacity of the operation.
  *
  * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_BAD_STATE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_get_capacity(
     const psa_key_derivation_operation_t *operation,
@@ -2920,7 +3156,14 @@
  *         In this case, the operation object remains valid and its capacity
  *         remains unchanged.
  * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_set_capacity(
     psa_key_derivation_operation_t *operation,
@@ -2963,6 +3206,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The value of \p step is not valid given the state of \p operation.
  * \retval #PSA_ERROR_BAD_STATE
@@ -2999,7 +3243,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c step is not compatible with the operation's algorithm.
@@ -3009,6 +3252,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The value of \p step is not valid given the state of \p operation.
  * \retval #PSA_ERROR_BAD_STATE
@@ -3061,7 +3305,6 @@
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c private_key is not compatible with \c alg,
@@ -3073,6 +3316,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_key_agreement(
     psa_key_derivation_operation_t *operation,
@@ -3107,6 +3355,11 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_output_bytes(
     psa_key_derivation_operation_t *operation,
@@ -3224,6 +3477,7 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
@@ -3255,6 +3509,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_key_derivation_abort(
     psa_key_derivation_operation_t *operation);
@@ -3295,12 +3553,19 @@
  *         \p private_key is not compatible with \p alg,
  *         or \p peer_key is not valid for \p alg or not compatible with
  *         \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p output_size is too small
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not a supported key agreement algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
  */
 psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
                                    psa_key_handle_t private_key,
@@ -3331,6 +3596,7 @@
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
@@ -3373,6 +3639,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index b53e1c7..fc0f963 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -149,7 +149,7 @@
  *
  * \warning If a function returns this error, it is undetermined
  * whether the requested action has completed or not. Implementations
- * should return #PSA_SUCCESS on successful completion whenver
+ * should return #PSA_SUCCESS on successful completion whenever
  * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE
  * if the requested action was completed successfully in an external
  * cryptoprocessor but there was a breakdown of communication before
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index f4bb472..5c5ddc2 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -45,7 +45,6 @@
     md2.c
     md4.c
     md5.c
-    md_wrap.c
     memory_buffer_alloc.c
     nist_kw.c
     oid.c
diff --git a/library/Makefile b/library/Makefile
index 8e27694..d7c1567 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -74,7 +74,7 @@
 		gcm.o		havege.o			\
 		hkdf.o						\
 		hmac_drbg.o	md.o		md2.o		\
-		md4.o		md5.o		md_wrap.o	\
+		md4.o		md5.o				\
 		memory_buffer_alloc.o		nist_kw.o	\
 		oid.o		padlock.o	pem.o		\
 		pk.o		pk_wrap.o	pkcs12.o	\
diff --git a/library/bignum.c b/library/bignum.c
index 5f5df78..d5bde8b 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -742,10 +742,15 @@
 static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
 {
     uint8_t i;
+    unsigned char *x_ptr;
     mbedtls_mpi_uint tmp = 0;
-    /* This works regardless of the endianness. */
-    for( i = 0; i < ciL; i++, x >>= 8 )
-        tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
+
+    for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
+    {
+        tmp <<= CHAR_BIT;
+        tmp |= (mbedtls_mpi_uint) *x_ptr;
+    }
+
     return( tmp );
 }
 
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 5c30380..bda9262 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -254,6 +254,8 @@
                 mbedtls_mpi *r, mbedtls_mpi *s,
                 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                int (*f_rng_blind)(void *, unsigned char *, size_t),
+                void *p_rng_blind,
                 mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
     int ret, key_tries, sign_tries;
@@ -323,7 +325,9 @@
 mul:
 #endif
             MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
-                                                  f_rng, p_rng, ECDSA_RS_ECP ) );
+                                                          f_rng_blind,
+                                                          p_rng_blind,
+                                                          ECDSA_RS_ECP ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
         }
         while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
@@ -349,7 +353,8 @@
          * Generate a random value to blind inv_mod in next step,
          * avoiding a potential timing leak.
          */
-        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
+        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind,
+                                                  p_rng_blind ) );
 
         /*
          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
@@ -406,8 +411,9 @@
     ECDSA_VALIDATE_RET( f_rng != NULL );
     ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
 
+    /* Use the same RNG for both blinding and ephemeral key generation */
     return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
-                                    f_rng, p_rng, NULL ) );
+                                    f_rng, p_rng, f_rng, p_rng, NULL ) );
 }
 #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
 
@@ -419,6 +425,8 @@
                     mbedtls_mpi *r, mbedtls_mpi *s,
                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
                     mbedtls_md_type_t md_alg,
+                    int (*f_rng_blind)(void *, unsigned char *, size_t),
+                    void *p_rng_blind,
                     mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
     int ret;
@@ -465,8 +473,69 @@
     ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
                               mbedtls_hmac_drbg_random, p_rng );
 #else
-    ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
-                      mbedtls_hmac_drbg_random, p_rng, rs_ctx );
+    if( f_rng_blind != NULL )
+        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+                                      mbedtls_hmac_drbg_random, p_rng,
+                                      f_rng_blind, p_rng_blind, rs_ctx );
+    else
+    {
+        mbedtls_hmac_drbg_context *p_rng_blind_det;
+
+#if !defined(MBEDTLS_ECP_RESTARTABLE)
+        /*
+         * To avoid reusing rng_ctx and risking incorrect behavior we seed a
+         * second HMAC-DRBG with the same seed. We also apply a label to avoid
+         * reusing the bits of the ephemeral key for blinding and eliminate the
+         * risk that they leak this way.
+         */
+        const char* blind_label = "BLINDING CONTEXT";
+        mbedtls_hmac_drbg_context rng_ctx_blind;
+
+        mbedtls_hmac_drbg_init( &rng_ctx_blind );
+        p_rng_blind_det = &rng_ctx_blind;
+        mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
+                                    data, 2 * grp_len );
+        ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det,
+                                            (const unsigned char*) blind_label,
+                                            strlen( blind_label ) );
+        if( ret != 0 )
+        {
+            mbedtls_hmac_drbg_free( &rng_ctx_blind );
+            goto cleanup;
+        }
+#else
+        /*
+         * In the case of restartable computations we would either need to store
+         * the second RNG in the restart context too or set it up at every
+         * restart. The first option would penalize the correct application of
+         * the function and the second would defeat the purpose of the
+         * restartable feature.
+         *
+         * Therefore in this case we reuse the original RNG. This comes with the
+         * price that the resulting signature might not be a valid deterministic
+         * ECDSA signature with a very low probability (same magnitude as
+         * successfully guessing the private key). However even then it is still
+         * a valid ECDSA signature.
+         */
+        p_rng_blind_det = p_rng;
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+        /*
+         * Since the output of the RNGs is always the same for the same key and
+         * message, this limits the efficiency of blinding and leaks information
+         * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
+         * won't be a valid value for f_rng_blind anymore. Therefore it should
+         * be checked by the caller and this branch and check can be removed.
+         */
+        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+                                      mbedtls_hmac_drbg_random, p_rng,
+                                      mbedtls_hmac_drbg_random, p_rng_blind_det,
+                                      rs_ctx );
+
+#if !defined(MBEDTLS_ECP_RESTARTABLE)
+        mbedtls_hmac_drbg_free( &rng_ctx_blind );
+#endif
+    }
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 
 cleanup:
@@ -479,11 +548,14 @@
 }
 
 /*
- * Deterministic signature wrapper
+ * Deterministic signature wrappers
  */
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
-                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                    mbedtls_md_type_t md_alg )
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                            mbedtls_mpi *s, const mbedtls_mpi *d,
+                            const unsigned char *buf, size_t blen,
+                            mbedtls_md_type_t md_alg )
 {
     ECDSA_VALIDATE_RET( grp   != NULL );
     ECDSA_VALIDATE_RET( r     != NULL );
@@ -491,7 +563,28 @@
     ECDSA_VALIDATE_RET( d     != NULL );
     ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
 
-    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
+    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
+                                        NULL, NULL, NULL ) );
+}
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                                mbedtls_mpi *s, const mbedtls_mpi *d,
+                                const unsigned char *buf, size_t blen,
+                                mbedtls_md_type_t md_alg,
+                                int (*f_rng_blind)(void *, unsigned char *,
+                                                   size_t),
+                                void *p_rng_blind )
+{
+    ECDSA_VALIDATE_RET( grp   != NULL );
+    ECDSA_VALIDATE_RET( r     != NULL );
+    ECDSA_VALIDATE_RET( s     != NULL );
+    ECDSA_VALIDATE_RET( d     != NULL );
+    ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
+    ECDSA_VALIDATE_RET( f_rng_blind != NULL );
+
+    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
+                                        f_rng_blind, p_rng_blind, NULL ) );
 }
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
@@ -670,11 +763,9 @@
     mbedtls_mpi_init( &s );
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    (void) f_rng;
-    (void) p_rng;
-
     MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
-                             hash, hlen, md_alg, rs_ctx ) );
+                                                 hash, hlen, md_alg, f_rng,
+                                                 p_rng, rs_ctx ) );
 #else
     (void) md_alg;
 
@@ -682,8 +773,10 @@
     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                          hash, hlen, f_rng, p_rng ) );
 #else
+    /* Use the same RNG for both blinding and ephemeral key generation */
     MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
-                         hash, hlen, f_rng, p_rng, rs_ctx ) );
+                                             hash, hlen, f_rng, p_rng, f_rng,
+                                             p_rng, rs_ctx ) );
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
diff --git a/library/ecjpake.c b/library/ecjpake.c
index b276514..1845c93 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -226,7 +226,7 @@
     p += id_len;
 
     /* Compute hash */
-    mbedtls_md( md_info, buf, p - buf, hash );
+    MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
 
     /* Turn it into an integer mod n */
     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 282481d..dcc7073 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -836,7 +836,7 @@
 #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
 
         default:
-            mbedtls_ecp_group_free( grp );
+            grp->id = MBEDTLS_ECP_DP_NONE;
             return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
     }
 }
diff --git a/library/md.c b/library/md.c
index ac8fac5..e1b5183 100644
--- a/library/md.c
+++ b/library/md.c
@@ -35,6 +35,14 @@
 #include "mbedtls/md_internal.h"
 #include "mbedtls/platform_util.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_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
@@ -49,6 +57,83 @@
 #include <stdio.h>
 #endif
 
+#if defined(MBEDTLS_MD2_C)
+const mbedtls_md_info_t mbedtls_md2_info = {
+    "MD2",
+    MBEDTLS_MD_MD2,
+    16,
+    16,
+};
+#endif
+
+#if defined(MBEDTLS_MD4_C)
+const mbedtls_md_info_t mbedtls_md4_info = {
+    "MD4",
+    MBEDTLS_MD_MD4,
+    16,
+    64,
+};
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+const mbedtls_md_info_t mbedtls_md5_info = {
+    "MD5",
+    MBEDTLS_MD_MD5,
+    16,
+    64,
+};
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+const mbedtls_md_info_t mbedtls_ripemd160_info = {
+    "RIPEMD160",
+    MBEDTLS_MD_RIPEMD160,
+    20,
+    64,
+};
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+const mbedtls_md_info_t mbedtls_sha1_info = {
+    "SHA1",
+    MBEDTLS_MD_SHA1,
+    20,
+    64,
+};
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+const mbedtls_md_info_t mbedtls_sha224_info = {
+    "SHA224",
+    MBEDTLS_MD_SHA224,
+    28,
+    64,
+};
+
+const mbedtls_md_info_t mbedtls_sha256_info = {
+    "SHA256",
+    MBEDTLS_MD_SHA256,
+    32,
+    64,
+};
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+const mbedtls_md_info_t mbedtls_sha384_info = {
+    "SHA384",
+    MBEDTLS_MD_SHA384,
+    48,
+    128,
+};
+
+const mbedtls_md_info_t mbedtls_sha512_info = {
+    "SHA512",
+    MBEDTLS_MD_SHA512,
+    64,
+    128,
+};
+#endif
+
 /*
  * Reminder: update profiles in Mbed TLS's x509_crt.c when adding a new hash!
  */
@@ -185,7 +270,52 @@
         return;
 
     if( ctx->md_ctx != NULL )
-        ctx->md_info->ctx_free_func( ctx->md_ctx );
+    {
+        switch( ctx->md_info->type )
+        {
+#if defined(MBEDTLS_MD2_C)
+            case MBEDTLS_MD_MD2:
+                mbedtls_md2_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+            case MBEDTLS_MD_MD4:
+                mbedtls_md4_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+            case MBEDTLS_MD_MD5:
+                mbedtls_md5_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+            case MBEDTLS_MD_RIPEMD160:
+                mbedtls_ripemd160_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+            case MBEDTLS_MD_SHA1:
+                mbedtls_sha1_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+            case MBEDTLS_MD_SHA224:
+            case MBEDTLS_MD_SHA256:
+                mbedtls_sha256_free( ctx->md_ctx );
+                break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+            case MBEDTLS_MD_SHA384:
+            case MBEDTLS_MD_SHA512:
+                mbedtls_sha512_free( ctx->md_ctx );
+                break;
+#endif
+            default:
+                /* Shouldn't happen */
+                break;
+        }
+        mbedtls_free( ctx->md_ctx );
+    }
 
     if( ctx->hmac_ctx != NULL )
     {
@@ -207,7 +337,48 @@
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     }
 
-    dst->md_info->clone_func( dst->md_ctx, src->md_ctx );
+    switch( src->md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            mbedtls_md2_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            mbedtls_md4_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            mbedtls_md5_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            mbedtls_sha1_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+        case MBEDTLS_MD_SHA256:
+            mbedtls_sha256_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+        case MBEDTLS_MD_SHA512:
+            mbedtls_sha512_clone( dst->md_ctx, src->md_ctx );
+            break;
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 
     return( 0 );
 }
@@ -219,20 +390,69 @@
 }
 #endif
 
+#define ALLOC( type )                                                   \
+    do {                                                                \
+        ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \
+        if( ctx->md_ctx == NULL )                                       \
+            return( MBEDTLS_ERR_MD_ALLOC_FAILED );                      \
+        mbedtls_##type##_init( ctx->md_ctx );                           \
+    }                                                                   \
+    while( 0 )
+
 int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac )
 {
     if( md_info == NULL || ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+    switch( md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            ALLOC( md2 );
+            break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            ALLOC( md4 );
+            break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            ALLOC( md5 );
+            break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            ALLOC( ripemd160 );
+            break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            ALLOC( sha1 );
+            break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+        case MBEDTLS_MD_SHA256:
+            ALLOC( sha256 );
+            break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+        case MBEDTLS_MD_SHA512:
+            ALLOC( sha512 );
+            break;
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 
     if( hmac != 0 )
     {
         ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size );
         if( ctx->hmac_ctx == NULL )
         {
-            md_info->ctx_free_func( ctx->md_ctx );
+            mbedtls_md_free( ctx );
             return( MBEDTLS_ERR_MD_ALLOC_FAILED );
         }
     }
@@ -241,13 +461,50 @@
 
     return( 0 );
 }
+#undef ALLOC
 
 int mbedtls_md_starts( mbedtls_md_context_t *ctx )
 {
     if( ctx == NULL || ctx->md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->starts_func( ctx->md_ctx ) );
+    switch( ctx->md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            return( mbedtls_md2_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            return( mbedtls_md4_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( mbedtls_md5_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( mbedtls_sha1_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) );
+        case MBEDTLS_MD_SHA256:
+            return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) );
+        case MBEDTLS_MD_SHA512:
+            return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) );
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 }
 
 int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
@@ -255,7 +512,43 @@
     if( ctx == NULL || ctx->md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+    switch( ctx->md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) );
+        case MBEDTLS_MD_SHA256:
+            return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) );
+        case MBEDTLS_MD_SHA512:
+            return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 }
 
 int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
@@ -263,7 +556,43 @@
     if( ctx == NULL || ctx->md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+    switch( ctx->md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) );
+        case MBEDTLS_MD_SHA256:
+            return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) );
+        case MBEDTLS_MD_SHA512:
+            return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) );
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 }
 
 int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
@@ -272,7 +601,43 @@
     if( md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( md_info->digest_func( input, ilen, output ) );
+    switch( md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            return( mbedtls_md2_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            return( mbedtls_md4_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( mbedtls_md5_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            return( mbedtls_ripemd160_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( mbedtls_sha1_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
+        case MBEDTLS_MD_SHA256:
+            return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
+        case MBEDTLS_MD_SHA512:
+            return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 }
 
 #if defined(MBEDTLS_FS_IO)
@@ -295,17 +660,17 @@
     if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
         goto cleanup;
 
-    if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
+    if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 )
         goto cleanup;
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
+        if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 )
             goto cleanup;
 
     if( ferror( f ) != 0 )
         ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
     else
-        ret = md_info->finish_func( ctx.md_ctx, output );
+        ret = mbedtls_md_finish( &ctx, output );
 
 cleanup:
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -328,11 +693,11 @@
 
     if( keylen > (size_t) ctx->md_info->block_size )
     {
-        if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+        if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
             goto cleanup;
-        if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
+        if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 )
             goto cleanup;
-        if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
+        if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 )
             goto cleanup;
 
         keylen = ctx->md_info->size;
@@ -351,10 +716,10 @@
         opad[i] = (unsigned char)( opad[i] ^ key[i] );
     }
 
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
         goto cleanup;
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
-                                           ctx->md_info->block_size ) ) != 0 )
+    if( ( ret = mbedtls_md_update( ctx, ipad,
+                                   ctx->md_info->block_size ) ) != 0 )
         goto cleanup;
 
 cleanup:
@@ -368,7 +733,7 @@
     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+    return( mbedtls_md_update( ctx, input, ilen ) );
 }
 
 int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
@@ -382,17 +747,17 @@
 
     opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
 
-    if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
+    if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 )
         return( ret );
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
         return( ret );
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
-                                           ctx->md_info->block_size ) ) != 0 )
+    if( ( ret = mbedtls_md_update( ctx, opad,
+                                   ctx->md_info->block_size ) ) != 0 )
         return( ret );
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
-                                           ctx->md_info->size ) ) != 0 )
+    if( ( ret = mbedtls_md_update( ctx, tmp,
+                                   ctx->md_info->size ) ) != 0 )
         return( ret );
-    return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+    return( mbedtls_md_finish( ctx, output ) );
 }
 
 int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
@@ -405,10 +770,9 @@
 
     ipad = (unsigned char *) ctx->hmac_ctx;
 
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
         return( ret );
-    return( ctx->md_info->update_func( ctx->md_ctx, ipad,
-                                       ctx->md_info->block_size ) );
+    return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) );
 }
 
 int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
@@ -445,7 +809,43 @@
     if( ctx == NULL || ctx->md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->process_func( ctx->md_ctx, data ) );
+    switch( ctx->md_info->type )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case MBEDTLS_MD_MD2:
+            return( mbedtls_internal_md2_process( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case MBEDTLS_MD_MD4:
+            return( mbedtls_internal_md4_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case MBEDTLS_MD_MD5:
+            return( mbedtls_internal_md5_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case MBEDTLS_MD_RIPEMD160:
+            return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case MBEDTLS_MD_SHA1:
+            return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case MBEDTLS_MD_SHA224:
+            return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) );
+        case MBEDTLS_MD_SHA256:
+            return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case MBEDTLS_MD_SHA384:
+            return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) );
+        case MBEDTLS_MD_SHA512:
+            return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) );
+#endif
+        default:
+            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
 }
 
 unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
diff --git a/library/md_wrap.c b/library/md_wrap.c
deleted file mode 100644
index 32f0871..0000000
--- a/library/md_wrap.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/**
- * \file md_wrap.c
- *
- * \brief Generic message digest wrapper for mbed TLS
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_MD_C)
-
-#include "mbedtls/md_internal.h"
-
-#if defined(MBEDTLS_MD2_C)
-#include "mbedtls/md2.h"
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-#include "mbedtls/md4.h"
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-#include "mbedtls/md5.h"
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-#include "mbedtls/ripemd160.h"
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-#include "mbedtls/sha1.h"
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-#include "mbedtls/sha256.h"
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-#include "mbedtls/sha512.h"
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
-
-#if defined(MBEDTLS_MD2_C)
-
-static int md2_starts_wrap( void *ctx )
-{
-    return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) );
-}
-
-static int md2_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) );
-}
-
-static int md2_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) );
-}
-
-static void *md2_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md2_init( (mbedtls_md2_context *) ctx );
-
-    return( ctx );
-}
-
-static void md2_ctx_free( void *ctx )
-{
-    mbedtls_md2_free( (mbedtls_md2_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md2_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md2_clone( (mbedtls_md2_context *) dst,
-                 (const mbedtls_md2_context *) src );
-}
-
-static int md2_process_wrap( void *ctx, const unsigned char *data )
-{
-    ((void) data);
-
-    return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) );
-}
-
-const mbedtls_md_info_t mbedtls_md2_info = {
-    MBEDTLS_MD_MD2,
-    "MD2",
-    16,
-    16,
-    md2_starts_wrap,
-    md2_update_wrap,
-    md2_finish_wrap,
-    mbedtls_md2_ret,
-    md2_ctx_alloc,
-    md2_ctx_free,
-    md2_clone_wrap,
-    md2_process_wrap,
-};
-
-#endif /* MBEDTLS_MD2_C */
-
-#if defined(MBEDTLS_MD4_C)
-
-static int md4_starts_wrap( void *ctx )
-{
-    return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) );
-}
-
-static int md4_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) );
-}
-
-static int md4_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) );
-}
-
-static void *md4_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md4_init( (mbedtls_md4_context *) ctx );
-
-    return( ctx );
-}
-
-static void md4_ctx_free( void *ctx )
-{
-    mbedtls_md4_free( (mbedtls_md4_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md4_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md4_clone( (mbedtls_md4_context *) dst,
-                       (const mbedtls_md4_context *) src );
-}
-
-static int md4_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md4_info = {
-    MBEDTLS_MD_MD4,
-    "MD4",
-    16,
-    64,
-    md4_starts_wrap,
-    md4_update_wrap,
-    md4_finish_wrap,
-    mbedtls_md4_ret,
-    md4_ctx_alloc,
-    md4_ctx_free,
-    md4_clone_wrap,
-    md4_process_wrap,
-};
-
-#endif /* MBEDTLS_MD4_C */
-
-#if defined(MBEDTLS_MD5_C)
-
-static int md5_starts_wrap( void *ctx )
-{
-    return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) );
-}
-
-static int md5_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) );
-}
-
-static int md5_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) );
-}
-
-static void *md5_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md5_init( (mbedtls_md5_context *) ctx );
-
-    return( ctx );
-}
-
-static void md5_ctx_free( void *ctx )
-{
-    mbedtls_md5_free( (mbedtls_md5_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md5_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md5_clone( (mbedtls_md5_context *) dst,
-                       (const mbedtls_md5_context *) src );
-}
-
-static int md5_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md5_info = {
-    MBEDTLS_MD_MD5,
-    "MD5",
-    16,
-    64,
-    md5_starts_wrap,
-    md5_update_wrap,
-    md5_finish_wrap,
-    mbedtls_md5_ret,
-    md5_ctx_alloc,
-    md5_ctx_free,
-    md5_clone_wrap,
-    md5_process_wrap,
-};
-
-#endif /* MBEDTLS_MD5_C */
-
-#if defined(MBEDTLS_RIPEMD160_C)
-
-static int ripemd160_starts_wrap( void *ctx )
-{
-    return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) );
-}
-
-static int ripemd160_update_wrap( void *ctx, const unsigned char *input,
-                                   size_t ilen )
-{
-    return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx,
-                                          input, ilen ) );
-}
-
-static int ripemd160_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx,
-                                          output ) );
-}
-
-static void *ripemd160_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) );
-
-    if( ctx != NULL )
-        mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx );
-
-    return( ctx );
-}
-
-static void ripemd160_ctx_free( void *ctx )
-{
-    mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void ripemd160_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst,
-                       (const mbedtls_ripemd160_context *) src );
-}
-
-static int ripemd160_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_ripemd160_process(
-                                (mbedtls_ripemd160_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_ripemd160_info = {
-    MBEDTLS_MD_RIPEMD160,
-    "RIPEMD160",
-    20,
-    64,
-    ripemd160_starts_wrap,
-    ripemd160_update_wrap,
-    ripemd160_finish_wrap,
-    mbedtls_ripemd160_ret,
-    ripemd160_ctx_alloc,
-    ripemd160_ctx_free,
-    ripemd160_clone_wrap,
-    ripemd160_process_wrap,
-};
-
-#endif /* MBEDTLS_RIPEMD160_C */
-
-#if defined(MBEDTLS_SHA1_C)
-
-static int sha1_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) );
-}
-
-static int sha1_update_wrap( void *ctx, const unsigned char *input,
-                              size_t ilen )
-{
-    return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx,
-                                     input, ilen ) );
-}
-
-static int sha1_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) );
-}
-
-static void *sha1_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha1_init( (mbedtls_sha1_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha1_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha1_clone( (mbedtls_sha1_context *) dst,
-                  (const mbedtls_sha1_context *) src );
-}
-
-static void sha1_ctx_free( void *ctx )
-{
-    mbedtls_sha1_free( (mbedtls_sha1_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static int sha1_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx,
-                                           data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha1_info = {
-    MBEDTLS_MD_SHA1,
-    "SHA1",
-    20,
-    64,
-    sha1_starts_wrap,
-    sha1_update_wrap,
-    sha1_finish_wrap,
-    mbedtls_sha1_ret,
-    sha1_ctx_alloc,
-    sha1_ctx_free,
-    sha1_clone_wrap,
-    sha1_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA1_C */
-
-/*
- * Wrappers for generic message digests
- */
-#if defined(MBEDTLS_SHA256_C)
-
-static int sha224_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) );
-}
-
-static int sha224_update_wrap( void *ctx, const unsigned char *input,
-                                size_t ilen )
-{
-    return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx,
-                                       input, ilen ) );
-}
-
-static int sha224_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx,
-                                       output ) );
-}
-
-static int sha224_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
-}
-
-static void *sha224_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha256_init( (mbedtls_sha256_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha224_ctx_free( void *ctx )
-{
-    mbedtls_sha256_free( (mbedtls_sha256_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void sha224_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha256_clone( (mbedtls_sha256_context *) dst,
-                    (const mbedtls_sha256_context *) src );
-}
-
-static int sha224_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx,
-                                             data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha224_info = {
-    MBEDTLS_MD_SHA224,
-    "SHA224",
-    28,
-    64,
-    sha224_starts_wrap,
-    sha224_update_wrap,
-    sha224_finish_wrap,
-    sha224_wrap,
-    sha224_ctx_alloc,
-    sha224_ctx_free,
-    sha224_clone_wrap,
-    sha224_process_wrap,
-};
-
-static int sha256_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) );
-}
-
-static int sha256_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha256_info = {
-    MBEDTLS_MD_SHA256,
-    "SHA256",
-    32,
-    64,
-    sha256_starts_wrap,
-    sha224_update_wrap,
-    sha224_finish_wrap,
-    sha256_wrap,
-    sha224_ctx_alloc,
-    sha224_ctx_free,
-    sha224_clone_wrap,
-    sha224_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C)
-
-static int sha384_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) );
-}
-
-static int sha384_update_wrap( void *ctx, const unsigned char *input,
-                               size_t ilen )
-{
-    return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx,
-                                       input, ilen ) );
-}
-
-static int sha384_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx,
-                                       output ) );
-}
-
-static int sha384_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
-}
-
-static void *sha384_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha512_init( (mbedtls_sha512_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha384_ctx_free( void *ctx )
-{
-    mbedtls_sha512_free( (mbedtls_sha512_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void sha384_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha512_clone( (mbedtls_sha512_context *) dst,
-                    (const mbedtls_sha512_context *) src );
-}
-
-static int sha384_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx,
-                                             data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha384_info = {
-    MBEDTLS_MD_SHA384,
-    "SHA384",
-    48,
-    128,
-    sha384_starts_wrap,
-    sha384_update_wrap,
-    sha384_finish_wrap,
-    sha384_wrap,
-    sha384_ctx_alloc,
-    sha384_ctx_free,
-    sha384_clone_wrap,
-    sha384_process_wrap,
-};
-
-static int sha512_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) );
-}
-
-static int sha512_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha512_info = {
-    MBEDTLS_MD_SHA512,
-    "SHA512",
-    64,
-    128,
-    sha512_starts_wrap,
-    sha384_update_wrap,
-    sha384_finish_wrap,
-    sha512_wrap,
-    sha384_ctx_alloc,
-    sha384_ctx_free,
-    sha384_clone_wrap,
-    sha384_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA512_C */
-
-#endif /* MBEDTLS_MD_C */
diff --git a/library/platform_util.c b/library/platform_util.c
index 756e226..b1f7450 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -72,7 +72,10 @@
 
 void mbedtls_platform_zeroize( void *buf, size_t len )
 {
-    memset_func( buf, 0, len );
+    MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL );
+
+    if( len > 0 )
+        memset_func( buf, 0, len );
 }
 #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index ef2d50e..98239c3 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -2735,7 +2735,7 @@
     status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
 
 cleanup:
-    mbedtls_platform_zeroize( ipad, key_length );
+    mbedtls_platform_zeroize( ipad, sizeof(ipad) );
 
     return( status );
 }
@@ -3271,9 +3271,11 @@
         psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
         const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
         mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
-        MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp->grp, &r, &s, &ecp->d,
-                                                 hash, hash_length,
-                                                 md_alg ) );
+        MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s,
+                                                     &ecp->d, hash,
+                                                     hash_length, md_alg,
+                                                     mbedtls_ctr_drbg_random,
+                                                     &global_data.ctr_drbg ) );
     }
     else
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
diff --git a/library/psa_its_file.c b/library/psa_its_file.c
index 05ca8af..0935b27 100644
--- a/library/psa_its_file.c
+++ b/library/psa_its_file.c
@@ -214,9 +214,12 @@
     n = fwrite( &header, 1, sizeof( header ), stream );
     if( n != sizeof( header ) )
         goto exit;
-    n = fwrite( p_data, 1, data_length, stream );
-    if( n != data_length )
-        goto exit;
+    if( data_length != 0 )
+    {
+        n = fwrite( p_data, 1, data_length, stream );
+        if( n != data_length )
+            goto exit;
+    }
     status = PSA_SUCCESS;
 
 exit:
diff --git a/tests/.gitignore b/tests/.gitignore
index 3c9b0cf..fbbd0df 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -7,3 +7,5 @@
 data_files/hmac_drbg_seed
 data_files/ctr_drbg_seed
 data_files/entropy_seed
+
+/instrument_record_status.h
diff --git a/tests/Makefile b/tests/Makefile
index 4eb9142..f7505b6 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -28,6 +28,10 @@
 LOCAL_CFLAGS += -g3
 endif
 
+ifdef RECORD_PSA_STATUS_COVERAGE_LOG
+LOCAL_CFLAGS += -Werror -DRECORD_PSA_STATUS_COVERAGE_LOG
+endif
+
 # if we're running on Windows, build for Windows
 ifdef WINDOWS
 WINDOWS_BUILD=1
@@ -163,3 +167,9 @@
 endef
 $(foreach app, $(APPS), $(foreach file, $(wildcard *.h), \
 	$(eval $(call copy_header_to_target,$(app),$(file)))))
+
+ifdef RECORD_PSA_STATUS_COVERAGE_LOG
+$(BINARIES): instrument_record_status.h
+instrument_record_status.h: ../include/psa/crypto.h Makefile
+	sed <../include/psa/crypto.h >$@ -n 's/^psa_status_t \([A-Za-z0-9_]*\)(.*/#define \1(...) RECORD_STATUS("\1", \1(__VA_ARGS__))/p'
+endif
diff --git a/tests/psa_crypto_helpers.h b/tests/psa_crypto_helpers.h
index 3780d16..19303de 100644
--- a/tests/psa_crypto_helpers.h
+++ b/tests/psa_crypto_helpers.h
@@ -72,4 +72,59 @@
  */
 #define PSA_DONE( ) test_helper_psa_done( __LINE__, __FILE__ )
 
+
+
+#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+#include <psa/crypto.h>
+
+/** Name of the file where return statuses are logged by #RECORD_STATUS. */
+#define STATUS_LOG_FILE_NAME "statuses.log"
+
+static psa_status_t record_status( psa_status_t status,
+                                   const char *func,
+                                   const char *file, int line,
+                                   const char *expr )
+{
+    /* We open the log file on first use.
+     * We never close the log file, so the record_status feature is not
+     * compatible with resource leak detectors such as Asan.
+     */
+    static FILE *log;
+    if( log == NULL )
+        log = fopen( STATUS_LOG_FILE_NAME, "a" );
+    fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
+    return( status );
+}
+
+/** Return value logging wrapper macro.
+ *
+ * Evaluate \p expr. Write a line recording its value to the log file
+ * #STATUS_LOG_FILE_NAME and return the value. The line is a colon-separated
+ * list of fields:
+ * ```
+ * value of expr:string:__FILE__:__LINE__:expr
+ * ```
+ *
+ * The test code does not call this macro explicitly because that would
+ * be very invasive. Instead, we instrument the source code by defining
+ * a bunch of wrapper macros like
+ * ```
+ * #define psa_crypto_init() RECORD_STATUS("psa_crypto_init", psa_crypto_init())
+ * ```
+ * These macro definitions must be present in `instrument_record_status.h`
+ * when building the test suites.
+ *
+ * \param string    A string, normally a function name.
+ * \param expr      An expression to evaluate, normally a call of the function
+ *                  whose name is in \p string. This expression must return
+ *                  a value of type #psa_status_t.
+ * \return          The value of \p expr.
+ */
+#define RECORD_STATUS( string, expr )                                   \
+    record_status( ( expr ), string, __FILE__, __LINE__, #expr )
+
+#include "instrument_record_status.h"
+
+#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
 #endif /* PSA_CRYPTO_HELPERS_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 244fdc3..e3a8c0e 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -629,6 +629,16 @@
     make test
 }
 
+component_test_psa_collect_statuses () {
+  msg "build+test: psa_collect_statuses" # ~30s
+  scripts/config.pl full
+  scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # slow and irrelevant
+  record_status tests/scripts/psa_collect_statuses.py
+  # Check that psa_crypto_init() succeeded at least once
+  record_status grep -q '^0:psa_crypto_init:' tests/statuses.log
+  rm -f tests/statuses.log
+}
+
 component_test_full_cmake_clang () {
     msg "build: cmake, full config, clang" # ~ 50s
     scripts/config.pl full
@@ -701,7 +711,7 @@
     # full minus MBEDTLS_USE_PSA_CRYPTO: run the same set of tests as basic-build-test.sh
     msg "build: cmake, full config + MBEDTLS_USE_PSA_CRYPTO, ASan"
     scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl set MBEDTLS_ECP_RESTARTABLE  # not using PSA, so enable restartable ECC
     scripts/config.pl set MBEDTLS_PSA_CRYPTO_C
     scripts/config.pl unset MBEDTLS_USE_PSA_CRYPTO
diff --git a/tests/scripts/psa_collect_statuses.py b/tests/scripts/psa_collect_statuses.py
new file mode 100755
index 0000000..e38beea
--- /dev/null
+++ b/tests/scripts/psa_collect_statuses.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+"""Describe the test coverage of PSA functions in terms of return statuses.
+
+1. Build Mbed Crypto with -DRECORD_PSA_STATUS_COVERAGE_LOG
+2. Run psa_collect_statuses.py
+
+The output is a series of line of the form "psa_foo PSA_ERROR_XXX". Each
+function/status combination appears only once.
+
+This script must be run from the top of an Mbed Crypto source tree.
+The build command is "make -DRECORD_PSA_STATUS_COVERAGE_LOG", which is
+only supported with make (as opposed to CMake or other build methods).
+"""
+
+import argparse
+import os
+import subprocess
+import sys
+
+DEFAULT_STATUS_LOG_FILE = 'tests/statuses.log'
+DEFAULT_PSA_CONSTANT_NAMES = 'programs/psa/psa_constant_names'
+
+class Statuses:
+    """Information about observed return statues of API functions."""
+
+    def __init__(self):
+        self.functions = {}
+        self.codes = set()
+        self.status_names = {}
+
+    def collect_log(self, log_file_name):
+        """Read logs from RECORD_PSA_STATUS_COVERAGE_LOG.
+
+        Read logs produced by running Mbed Crypto test suites built with
+        -DRECORD_PSA_STATUS_COVERAGE_LOG.
+        """
+        with open(log_file_name) as log:
+            for line in log:
+                value, function, tail = line.split(':', 2)
+                if function not in self.functions:
+                    self.functions[function] = {}
+                fdata = self.functions[function]
+                if value not in self.functions[function]:
+                    fdata[value] = []
+                fdata[value].append(tail)
+                self.codes.add(int(value))
+
+    def get_constant_names(self, psa_constant_names):
+        """Run psa_constant_names to obtain names for observed numerical values."""
+        values = [str(value) for value in self.codes]
+        cmd = [psa_constant_names, 'status'] + values
+        output = subprocess.check_output(cmd).decode('ascii')
+        for value, name in zip(values, output.rstrip().split('\n')):
+            self.status_names[value] = name
+
+    def report(self):
+        """Report observed return values for each function.
+
+        The report is a series of line of the form "psa_foo PSA_ERROR_XXX".
+        """
+        for function in sorted(self.functions.keys()):
+            fdata = self.functions[function]
+            names = [self.status_names[value] for value in fdata.keys()]
+            for name in sorted(names):
+                sys.stdout.write('{} {}\n'.format(function, name))
+
+def collect_status_logs(options):
+    """Build and run unit tests and report observed function return statuses.
+
+    Build Mbed Crypto with -DRECORD_PSA_STATUS_COVERAGE_LOG, run the
+    test suites and display information about observed return statuses.
+    """
+    rebuilt = False
+    if not options.use_existing_log and os.path.exists(options.log_file):
+        os.remove(options.log_file)
+    if not os.path.exists(options.log_file):
+        if options.clean_before:
+            subprocess.check_call(['make', 'clean'],
+                                  cwd='tests',
+                                  stdout=sys.stderr)
+        with open(os.devnull, 'w') as devnull:
+            make_q_ret = subprocess.call(['make', '-q', 'lib', 'tests'],
+                                         stdout=devnull, stderr=devnull)
+        if make_q_ret != 0:
+            subprocess.check_call(['make', 'RECORD_PSA_STATUS_COVERAGE_LOG=1'],
+                                  stdout=sys.stderr)
+            rebuilt = True
+        subprocess.check_call(['make', 'test'],
+                              stdout=sys.stderr)
+    data = Statuses()
+    data.collect_log(options.log_file)
+    data.get_constant_names(options.psa_constant_names)
+    if rebuilt and options.clean_after:
+        subprocess.check_call(['make', 'clean'],
+                              cwd='tests',
+                              stdout=sys.stderr)
+    return data
+
+def main():
+    parser = argparse.ArgumentParser(description=globals()['__doc__'])
+    parser.add_argument('--clean-after',
+                        action='store_true',
+                        help='Run "make clean" after rebuilding')
+    parser.add_argument('--clean-before',
+                        action='store_true',
+                        help='Run "make clean" before regenerating the log file)')
+    parser.add_argument('--log-file', metavar='FILE',
+                        default=DEFAULT_STATUS_LOG_FILE,
+                        help='Log file location (default: {})'.format(
+                            DEFAULT_STATUS_LOG_FILE
+                        ))
+    parser.add_argument('--psa-constant-names', metavar='PROGRAM',
+                        default=DEFAULT_PSA_CONSTANT_NAMES,
+                        help='Path to psa_constant_names (default: {})'.format(
+                            DEFAULT_PSA_CONSTANT_NAMES
+                        ))
+    parser.add_argument('--use-existing-log', '-e',
+                        action='store_true',
+                        help='Don\'t regenerate the log file if it exists')
+    options = parser.parse_args()
+    data = collect_status_logs(options)
+    data.report()
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index 22d92b6..ab3db3a 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -55,25 +55,30 @@
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-                       mbedtls_ecdsa_sign_det( NULL, &m, &m, &m,
-                                                buf, sizeof( buf ),
-                                                valid_md ) );
+                       mbedtls_ecdsa_sign_det_ext( NULL, &m, &m, &m,
+                                                   buf, sizeof( buf ),
+                                                   valid_md,
+                                                   rnd_std_rand, NULL ) );
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-                       mbedtls_ecdsa_sign_det( &grp, NULL, &m, &m,
-                                                buf, sizeof( buf ),
-                                                valid_md ) );
+                       mbedtls_ecdsa_sign_det_ext( &grp, NULL, &m, &m,
+                                                   buf, sizeof( buf ),
+                                                   valid_md,
+                                                   rnd_std_rand, NULL ) );
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-                       mbedtls_ecdsa_sign_det( &grp, &m, NULL, &m,
-                                                buf, sizeof( buf ),
-                                                valid_md ) );
+                       mbedtls_ecdsa_sign_det_ext( &grp, &m, NULL, &m,
+                                                   buf, sizeof( buf ),
+                                                   valid_md,
+                                                   rnd_std_rand, NULL ) );
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-                       mbedtls_ecdsa_sign_det( &grp, &m, &m, NULL,
-                                                buf, sizeof( buf ),
-                                                valid_md ) );
+                       mbedtls_ecdsa_sign_det_ext( &grp, &m, &m, NULL,
+                                                   buf, sizeof( buf ),
+                                                   valid_md,
+                                                   rnd_std_rand, NULL ) );
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-                       mbedtls_ecdsa_sign_det( &grp, &m, &m, &m,
-                                                NULL, sizeof( buf ),
-                                                valid_md ) );
+                       mbedtls_ecdsa_sign_det_ext( &grp, &m, &m, &m,
+                                                   NULL, sizeof( buf ),
+                                                   valid_md,
+                                                   rnd_std_rand, NULL ) );
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
@@ -325,7 +330,10 @@
     TEST_ASSERT( mbedtls_md( md_info, (const unsigned char *) msg,
                  strlen( msg ), hash ) == 0 );
 
-    TEST_ASSERT( mbedtls_ecdsa_sign_det( &grp, &r, &s, &d, hash, hlen, md_alg ) == 0 );
+    TEST_ASSERT(
+                mbedtls_ecdsa_sign_det_ext( &grp, &r, &s, &d, hash, hlen,
+                                            md_alg, rnd_std_rand, NULL )
+                == 0 );
 
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 84c99c9..ffa59e5 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -4,6 +4,9 @@
 ECJPAKE selftest
 ecjpake_selftest:
 
+ECJPAKE fail read corrupt MD
+read_bad_md:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51620934d74eb43e54df424fd96306c0117bf131afabf90a9d33d1198d905193735144104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb12"
+
 ECJPAKE round one: client, valid
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51620934d74eb43e54df424fd96306c0117bf131afabf90a9d33d1198d905193735144104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb12":0
 
diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function
index d267295..38f190d 100644
--- a/tests/suites/test_suite_ecjpake.function
+++ b/tests/suites/test_suite_ecjpake.function
@@ -237,6 +237,27 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
+void read_bad_md( data_t *msg )
+{
+    mbedtls_ecjpake_context corrupt_ctx;
+    const unsigned char * pw = NULL;
+    const size_t pw_len = 0;
+    int any_role = MBEDTLS_ECJPAKE_CLIENT;
+
+    mbedtls_ecjpake_init( &corrupt_ctx );
+    TEST_ASSERT( mbedtls_ecjpake_setup( &corrupt_ctx, any_role,
+                 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw, pw_len ) == 0 );
+    corrupt_ctx.md_info = NULL;
+
+    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &corrupt_ctx, msg->x,
+                 msg->len ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+exit:
+    mbedtls_ecjpake_free( &corrupt_ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
 void read_round_one( int role, data_t * msg, int ref_ret )
 {
     mbedtls_ecjpake_context ctx;
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 8eee989..58b7eab 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -799,6 +799,14 @@
 # Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
 
+PSA MAC setup: algorithm known but not supported, long key
+depends_on:!MBEDTLS_MD5_C
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f":PSA_ALG_HMAC(PSA_ALG_MD5):PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC setup: algorithm known but not supported, short key
+depends_on:!MBEDTLS_MD5_C
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708":PSA_ALG_HMAC(PSA_ALG_MD5):PSA_ERROR_NOT_SUPPORTED
+
 PSA MAC: bad order function calls
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
 mac_bad_order:
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 0456bc2..7f71a5a 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -269,7 +269,6 @@
     <ClCompile Include="..\..\library\md2.c" />

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

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

-    <ClCompile Include="..\..\library\md_wrap.c" />

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

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

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