Merge pull request #284 from gilles-peskine-arm/bk-warning-fixes-crypto

Fix some possibly-undefined variable warnings
diff --git a/configs/config-symmetric-only.h b/configs/config-symmetric-only.h
new file mode 100644
index 0000000..94e80ab
--- /dev/null
+++ b/configs/config-symmetric-only.h
@@ -0,0 +1,99 @@
+/**
+ * \file config-symmetric-only.h
+ *
+ * \brief Configuration without any asymmetric cryptography.
+ */
+/*
+ *  Copyright (C) 2019, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_ASM
+#define MBEDTLS_HAVE_TIME
+#define MBEDTLS_HAVE_TIME_DATE
+
+/* Mbed Crypto feature support */
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_CIPHER_MODE_CFB
+#define MBEDTLS_CIPHER_MODE_CTR
+#define MBEDTLS_CIPHER_MODE_OFB
+#define MBEDTLS_CIPHER_MODE_XTS
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_FS_IO
+#define MBEDTLS_ENTROPY_NV_SEED
+#define MBEDTLS_SELF_TEST
+#define MBEDTLS_USE_PSA_CRYPTO
+#define MBEDTLS_VERSION_FEATURES
+
+/* Mbed Crypto modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BLOWFISH_C
+#define MBEDTLS_CAMELLIA_C
+#define MBEDTLS_ARIA_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CHACHA20_C
+#define MBEDTLS_CHACHAPOLY_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CMAC_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_DES_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
+//#define MBEDTLS_HAVEGE_C
+#define MBEDTLS_HKDF_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_NIST_KW_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_MD2_C
+#define MBEDTLS_MD4_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PKCS12_C
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_POLY1305_C
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_SE_C
+#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+#define MBEDTLS_PSA_ITS_FILE_C
+#define MBEDTLS_RIPEMD160_C
+#define MBEDTLS_SHA1_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA512_C
+//#define MBEDTLS_THREADING_C
+#define MBEDTLS_TIMING_C
+#define MBEDTLS_VERSION_C
+#define MBEDTLS_XTEA_C
+
+#include "check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 236c1a2..9938909 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -72,9 +72,10 @@
 
 This example shows how to import a key:
 ```C
+void import_a_key(const uint8_t *key, size_t key_len)
+{
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    uint8_t data[] = AES_KEY;
     psa_key_handle_t handle;
 
     printf("Import an AES key...\t");
@@ -94,7 +95,7 @@
     psa_set_key_bits(&attributes, 128);
 
     /* Import the key */
-    status = psa_import_key(&attributes, data, sizeof(data), &handle);
+    status = psa_import_key(&attributes, key, key_len, &handle);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
@@ -108,6 +109,7 @@
     psa_destroy_key(handle);
 
     mbedtls_psa_crypto_free();
+}
 ```
 
 ### Signing a message using RSA
@@ -123,9 +125,10 @@
 
 This example shows how to sign a hash that has already been calculated:
 ```C
+void sign_a_message_using_rsa(const uint8_t *key, size_t key_len)
+{
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    uint8_t key[] = RSA_KEY;
     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,
@@ -151,7 +154,7 @@
     psa_set_key_bits(&attributes, 1024);
 
     /* Import the key */
-    status = psa_import_key(&attributes, key, sizeof(key), &handle);
+    status = psa_import_key(&attributes, key, key_len, &handle);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
@@ -176,6 +179,7 @@
     psa_destroy_key(handle);
 
     mbedtls_psa_crypto_free();
+}
 ```
 
 ### Using symmetric ciphers
@@ -196,6 +200,8 @@
 
 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
+void encrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
+{
     enum {
         block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
     };
@@ -205,7 +211,6 @@
     uint8_t plaintext[block_size] = SOME_PLAINTEXT;
     uint8_t iv[block_size];
     size_t iv_len;
-    uint8_t key[] = AES_KEY;
     uint8_t output[block_size];
     size_t output_len;
     psa_key_handle_t handle;
@@ -227,7 +232,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, sizeof(key), &handle);
+    status = psa_import_key(&attributes, key, key_len, &handle);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -266,6 +271,7 @@
     psa_destroy_key(handle);
 
     mbedtls_psa_crypto_free();
+}
 ```
 
 **To decrypt a message with a symmetric cipher:**
@@ -279,6 +285,8 @@
 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
+void decrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
+{
     enum {
         block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
     };
@@ -288,7 +296,6 @@
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     uint8_t ciphertext[block_size] = SOME_CIPHERTEXT;
     uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
-    uint8_t key[] = AES_KEY;
     uint8_t output[block_size];
     size_t output_len;
     psa_key_handle_t handle;
@@ -309,7 +316,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, sizeof(key), &handle);
+    status = psa_import_key(&attributes, key, key_len, &handle);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -348,6 +355,7 @@
     psa_destroy_key(handle);
 
     mbedtls_psa_crypto_free();
+}
 ```
 
 #### Handling cipher operation contexts
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index ab947ab..1a76111 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -52,7 +52,7 @@
 #define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
 #define MBEDTLS_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
 #define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
-#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. (not used) */
+#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. */
 #define MBEDTLS_ERR_ASN1_ALLOC_FAILED                     -0x006A  /**< Memory allocation failed */
 #define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
 
@@ -176,119 +176,203 @@
  * \brief       Get the length of an ASN.1 element.
  *              Updates the pointer to immediately behind the length.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param len   The variable that will receive the value
+ * \param p     On entry, \c *p points to the first byte of the length,
+ *              i.e. immediately after the tag.
+ *              On successful completion, \c *p points to the first byte
+ *              after the length, i.e. the first byte of the content.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param len   On successful completion, \c *len contains the length
+ *              read from the ASN.1 input.
  *
- * \return      0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching
- *              end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is
- *              unparseable.
+ * \return      0 if successful.
+ * \return      #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
+ *              would end beyond \p end.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
  */
 int mbedtls_asn1_get_len( unsigned char **p,
-                  const unsigned char *end,
-                  size_t *len );
+                          const unsigned char *end,
+                          size_t *len );
 
 /**
- * \brief       Get the tag and length of the tag. Check for the requested tag.
+ * \brief       Get the tag and length of the element.
+ *              Check for the requested tag.
  *              Updates the pointer to immediately behind the tag and length.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param len   The variable that will receive the length
- * \param tag   The expected tag
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              after the length, i.e. the first byte of the content.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param len   On successful completion, \c *len contains the length
+ *              read from the ASN.1 input.
+ * \param tag   The expected tag.
  *
- * \return      0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did
- *              not match requested tag, or another specific ASN.1 error code.
+ * \return      0 if successful.
+ * \return      #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start
+ *              with the requested tag.
+ * \return      #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
+ *              would end beyond \p end.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
  */
 int mbedtls_asn1_get_tag( unsigned char **p,
-                  const unsigned char *end,
-                  size_t *len, int tag );
+                          const unsigned char *end,
+                          size_t *len, int tag );
 
 /**
  * \brief       Retrieve a boolean ASN.1 tag and its value.
  *              Updates the pointer to immediately behind the full tag.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param val   The variable that will receive the value
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              beyond the ASN.1 element.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param val   On success, the parsed value (\c 0 or \c 1).
  *
- * \return      0 if successful or a specific ASN.1 error code.
+ * \return      0 if successful.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 BOOLEAN.
  */
 int mbedtls_asn1_get_bool( unsigned char **p,
-                   const unsigned char *end,
-                   int *val );
+                           const unsigned char *end,
+                           int *val );
 
 /**
  * \brief       Retrieve an integer ASN.1 tag and its value.
  *              Updates the pointer to immediately behind the full tag.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param val   The variable that will receive the value
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              beyond the ASN.1 element.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param val   On success, the parsed value.
  *
- * \return      0 if successful or a specific ASN.1 error code.
+ * \return      0 if successful.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 INTEGER.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ *              not fit in an \c int.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 INTEGER.
  */
 int mbedtls_asn1_get_int( unsigned char **p,
-                  const unsigned char *end,
-                  int *val );
+                          const unsigned char *end,
+                          int *val );
 
 /**
  * \brief       Retrieve a bitstring ASN.1 tag and its value.
  *              Updates the pointer to immediately behind the full tag.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param bs    The variable that will receive the value
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p is equal to \p end.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param bs    On success, ::mbedtls_asn1_bitstring information about
+ *              the parsed value.
  *
- * \return      0 if successful or a specific ASN.1 error code.
+ * \return      0 if successful.
+ * \return      #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
+ *              extra data after a valid BIT STRING.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 BIT STRING.
  */
 int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
-                        mbedtls_asn1_bitstring *bs);
+                                mbedtls_asn1_bitstring *bs );
 
 /**
  * \brief       Retrieve a bitstring ASN.1 tag without unused bits and its
  *              value.
  *              Updates the pointer to the beginning of the bit/octet string.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param len   Length of the actual bit/octect string in bytes
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              of the content of the BIT STRING.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param len   On success, \c *len is the length of the content in bytes.
  *
- * \return      0 if successful or a specific ASN.1 error code.
+ * \return      0 if successful.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with
+ *              a valid BIT STRING with a nonzero number of unused bits.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 BIT STRING.
  */
-int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
-                             size_t *len );
+int mbedtls_asn1_get_bitstring_null( unsigned char **p,
+                                     const unsigned char *end,
+                                     size_t *len );
 
 /**
- * \brief       Parses and splits an ASN.1 "SEQUENCE OF <tag>"
- *              Updated the pointer to immediately behind the full sequence tag.
+ * \brief       Parses and splits an ASN.1 "SEQUENCE OF <tag>".
+ *              Updates the pointer to immediately behind the full sequence tag.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param cur   First variable in the chain to fill
- * \param tag   Type of sequence
+ * \note        On error, this function may return a partial list in \p cur.
+ *              You must set `cur->next = NULL` before calling this function!
+ *              Otherwise it is impossible to distinguish a previously non-null
+ *              pointer from a pointer to an object allocated by this function.
  *
- * \return      0 if successful or a specific ASN.1 error code.
+ * \note        If the sequence is empty, this function does not modify
+ *              \c *cur. If the sequence is valid and non-empty, this
+ *              function sets `cur->buf.tag` to \p tag. This allows
+ *              callers to distinguish between an empty sequence and
+ *              a one-element sequence.
+ *
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p is equal to \p end.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param cur   A ::mbedtls_asn1_sequence which this function fills.
+ *              When this function returns, \c *cur is the head of a linked
+ *              list. Each node in this list is allocated with
+ *              mbedtls_calloc() apart from \p cur itself, and should
+ *              therefore be freed with mbedtls_free().
+ *              The list describes the content of the sequence.
+ *              The head of the list (i.e. \c *cur itself) describes the
+ *              first element, `*cur->next` describes the second element, etc.
+ *              For each element, `buf.tag == tag`, `buf.len` is the length
+ *              of the content of the content of the element, and `buf.p`
+ *              points to the first byte of the content (i.e. immediately
+ *              past the length of the element).
+ *              Note that list elements may be allocated even on error.
+ * \param tag   Each element of the sequence must have this tag.
+ *
+ * \return      0 if successful.
+ * \return      #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
+ *              extra data after a valid SEQUENCE OF \p tag.
+ * \return      #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 BIT STRING.
  */
 int mbedtls_asn1_get_sequence_of( unsigned char **p,
-                          const unsigned char *end,
-                          mbedtls_asn1_sequence *cur,
-                          int tag);
+                                  const unsigned char *end,
+                                  mbedtls_asn1_sequence *cur,
+                                  int tag );
 
 #if defined(MBEDTLS_BIGNUM_C)
 /**
- * \brief       Retrieve a MPI value from an integer ASN.1 tag.
+ * \brief       Retrieve an integer ASN.1 tag and its value.
  *              Updates the pointer to immediately behind the full tag.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param X     The MPI that will receive the value
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              beyond the ASN.1 element.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param X     On success, the parsed value.
  *
- * \return      0 if successful or a specific ASN.1 or MPI error code.
+ * \return      0 if successful.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 INTEGER.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ *              not fit in an \c int.
+ * \return      An MPI error code if the parsed value is too large.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 INTEGER.
  */
 int mbedtls_asn1_get_mpi( unsigned char **p,
-                  const unsigned char *end,
-                  mbedtls_mpi *X );
+                          const unsigned char *end,
+                          mbedtls_mpi *X );
 #endif /* MBEDTLS_BIGNUM_C */
 
 /**
@@ -296,10 +380,14 @@
  *              Updates the pointer to immediately behind the full
  *              AlgorithmIdentifier.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param alg   The buffer to receive the OID
- * \param params The buffer to receive the params (if any)
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              beyond the AlgorithmIdentifier element.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param alg   The buffer to receive the OID.
+ * \param params The buffer to receive the parameters.
+ *              This is zeroized if there are no parameters.
  *
  * \return      0 if successful or a specific ASN.1 or MPI error code.
  */
@@ -313,9 +401,12 @@
  *              Updates the pointer to immediately behind the full
  *              AlgorithmIdentifier.
  *
- * \param p     The position in the ASN.1 data
- * \param end   End of data
- * \param alg   The buffer to receive the OID
+ * \param p     On entry, \c *p points to the start of the ASN.1 element.
+ *              On successful completion, \c *p points to the first byte
+ *              beyond the AlgorithmIdentifier element.
+ *              On error, the value of \c *p is undefined.
+ * \param end   End of data.
+ * \param alg   The buffer to receive the OID.
  *
  * \return      0 if successful or a specific ASN.1 or MPI error code.
  */
@@ -339,15 +430,19 @@
 /**
  * \brief       Free a mbedtls_asn1_named_data entry
  *
- * \param entry The named data entry to free
+ * \param entry The named data entry to free.
+ *              This function calls mbedtls_free() on
+ *              `entry->oid.p` and `entry->val.p`.
  */
 void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
 
 /**
- * \brief       Free all entries in a mbedtls_asn1_named_data list
- *              Head will be set to NULL
+ * \brief       Free all entries in a mbedtls_asn1_named_data list.
  *
- * \param head  Pointer to the head of the list of named data entries to free
+ * \param head  Pointer to the head of the list of named data entries to free.
+ *              This function calls mbedtls_asn1_free_named_data() and
+ *              mbedtls_free() on each list element and
+ *              sets \c *head to \c NULL.
  */
 void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
 
diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h
index 336f2da..9824146 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -100,6 +100,7 @@
  * \param p         The reference to the current position pointer.
  * \param start     The start of the buffer, for bounds-checking.
  * \param X         The MPI to write.
+ *                  It must be non-negative.
  *
  * \return          The number of bytes written to \p p on success.
  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
@@ -184,6 +185,7 @@
  * \param p         The reference to the current position pointer.
  * \param start     The start of the buffer, for bounds-checking.
  * \param val       The integer value to write.
+ *                  It must be non-negative.
  *
  * \return          The number of bytes written to \p p on success.
  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
@@ -232,7 +234,7 @@
 
 /**
  * \brief           Write a UTF8 string in ASN.1 format using the UTF8String
- *                  string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
+ *                  string encoding tag (#MBEDTLS_ASN1_UTF8_STRING).
  *
  * \note            This function works backwards in data buffer.
  *
@@ -332,9 +334,13 @@
  *                  through (will be updated in case of a new entry).
  * \param oid       The OID to look for.
  * \param oid_len   The size of the OID.
- * \param val       The data to store (can be \c NULL if you want to fill
- *                  it by hand).
+ * \param val       The associated data to store. If this is \c NULL,
+ *                  no data is copied to the new or existing buffer.
  * \param val_len   The minimum length of the data buffer needed.
+ *                  If this is 0, do not allocate a buffer for the associated
+ *                  data.
+ *                  If the OID was already present, enlarge, shrink or free
+ *                  the existing buffer to fit \p val_len.
  *
  * \return          A pointer to the new / existing entry on success.
  * \return          \c NULL if if there was a memory allocation error.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index e14fc74..a4db6ba 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -671,6 +671,13 @@
 #define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
 #define MBEDTLS_CIPHER_PADDING_ZEROS
 
+/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ *
+ * Uncomment this macro to use a 128-bit key in the CTR_DRBG module.
+ * By default, CTR_DRBG uses a 256-bit key.
+ */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+
 /**
  * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
  *
@@ -1295,7 +1302,11 @@
  *
  * Enable the CTR_DRBG AES-based random generator.
  * The CTR_DRBG generator uses AES-256 by default.
- * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above.
+ *
+ * \note To achieve a 256-bit security strength with CTR_DRBG,
+ *       you must use AES-256 *and* use sufficient entropy.
+ *       See ctr_drbg.h for more details.
  *
  * Module:  library/ctr_drbg.c
  * Caller:
@@ -1971,7 +1982,6 @@
 //#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
 //#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
 //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
-//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY              /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
 
 /* HMAC_DRBG options */
 //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index ffaf8ad..091f15a 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -1,7 +1,8 @@
 /**
  * \file ctr_drbg.h
  *
- * \brief    This file contains CTR_DRBG definitions and functions.
+ * \brief    This file contains definitions and functions for the
+ *           CTR_DRBG pseudorandom generator.
  *
  * CTR_DRBG is a standardized way of building a PRNG from a block-cipher
  * in counter mode operation, as defined in <em>NIST SP 800-90A:
@@ -9,13 +10,19 @@
  * Bit Generators</em>.
  *
  * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
- * as the underlying block cipher.
+ * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
+ * as the underlying block cipher, with a derivation function.
  *
- *  \warning Using 128-bit keys for CTR_DRBG limits the security of generated
- *  keys and operations that use random values generated to 128-bit security.
+ * The security strength as defined in NIST SP 800-90A is
+ * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
+ * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
+ * kept at its default value (and not overridden in config.h) and that the
+ * DRBG instance is set up with default parameters.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more
+ * information.
  */
 /*
- *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -56,9 +63,19 @@
 #define MBEDTLS_CTR_DRBG_BLOCKSIZE          16 /**< The block size used by the cipher. */
 
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-#define MBEDTLS_CTR_DRBG_KEYSIZE            16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE            16
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 16 bytes (128 bits)
+ * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled.
+ */
 #else
-#define MBEDTLS_CTR_DRBG_KEYSIZE            32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE            32
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 32 bytes (256 bits)
+ * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled.
+ */
 #endif
 
 #define MBEDTLS_CTR_DRBG_KEYBITS            ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
@@ -73,21 +90,31 @@
  * \{
  */
 
+/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN
+ *
+ * \brief The amount of entropy used per seed by default, in bytes.
+ */
 #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)
 #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
+/** This is 48 bytes because the entropy module uses SHA-512
+ * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled).
+ */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        48
-/**< The amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
+
+#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+
+/** This is 32 bytes because the entropy module uses SHA-256
+ * (the SHA512 module is disabled or
+ * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled).
  */
-#else
+#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+/** \warning To achieve a 256-bit security strength, you must pass a nonce
+ *           to mbedtls_ctr_drbg_seed().
+ */
+#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        32
-/**< Amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
- */
-#endif
-#endif
+#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */
 
 #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)
 #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL    10000
@@ -106,7 +133,7 @@
 
 #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
 #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT     384
-/**< The maximum size of seed or reseed buffer. */
+/**< The maximum size of seed or reseed buffer in bytes. */
 #endif
 
 /* \} name SECTION: Module settings */
@@ -120,20 +147,47 @@
 extern "C" {
 #endif
 
+#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is \c 0 because a single read from the entropy source is sufficient
+ * to include a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0
+#else
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is half of the default entropy length because a single read from
+ * the entropy source does not provide enough material to form a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2
+#endif
+
 /**
  * \brief          The CTR_DRBG context structure.
  */
 typedef struct mbedtls_ctr_drbg_context
 {
     unsigned char counter[16];  /*!< The counter (V). */
-    int reseed_counter;         /*!< The reseed counter. */
+    int reseed_counter;         /*!< The reseed counter.
+                                 * This is the number of requests that have
+                                 * been made since the last (re)seeding,
+                                 * minus one.
+                                 * Before the initial seeding, this field
+                                 * contains the amount of entropy in bytes
+                                 * to use as a nonce for the initial seeding.
+                                 */
     int prediction_resistance;  /*!< This determines whether prediction
                                      resistance is enabled, that is
                                      whether to systematically reseed before
                                      each random generation. */
     size_t entropy_len;         /*!< The amount of entropy grabbed on each
-                                     seed or reseed operation. */
-    int reseed_interval;        /*!< The reseed interval. */
+                                     seed or reseed operation, in bytes. */
+    int reseed_interval;        /*!< The reseed interval.
+                                 * This is the maximum number of requests
+                                 * that can be made between reseedings. */
 
     mbedtls_aes_context aes_ctx;        /*!< The AES context. */
 
@@ -164,17 +218,86 @@
  * \brief               This function seeds and sets up the CTR_DRBG
  *                      entropy source for future reseeds.
  *
- * \note Personalization data can be provided in addition to the more generic
- *       entropy source, to make this instantiation as unique as possible.
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ *   with mbedtls_entropy_init() (which registers the platform's default
+ *   entropy sources).
+ *
+ * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
+ * You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
+ *
+ * The entropy nonce length is:
+ * - \c 0 if the entropy length is at least 3/2 times the entropy length,
+ *   which guarantees that the security strength is the maximum permitted
+ *   by the key size and entropy length according to NIST SP 800-90A §10.2.1;
+ * - Half the entropy length otherwise.
+ * You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
+ * With the default entropy length, the entropy nonce length is
+ * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
+ *
+ * You can provide a nonce and personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ * See SP 800-90A §8.6.7 for more details about nonces.
+ *
+ * The _seed_material_ value passed to the derivation function in
+ * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2
+ * is the concatenation of the following strings:
+ * - A string obtained by calling \p f_entropy function for the entropy
+ *   length.
+ */
+#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
+/**
+ * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
+ *   obtained by calling \p f_entropy function for the specified length.
+ */
+#else
+/**
+ * - A string obtained by calling \p f_entropy function for the entropy nonce
+ *   length. If the entropy nonce length is \c 0, this function does not
+ *   make a second call to \p f_entropy.
+ */
+#endif
+/**
+ * - The \p custom string.
+ *
+ * \note                To achieve the nominal security strength permitted
+ *                      by CTR_DRBG, the entropy length must be:
+ *                      - at least 16 bytes for a 128-bit strength
+ *                      (maximum achievable strength when using AES-128);
+ *                      - at least 32 bytes for a 256-bit strength
+ *                      (maximum achievable strength when using AES-256).
+ *
+ *                      In addition, if you do not pass a nonce in \p custom,
+ *                      the sum of the entropy length
+ *                      and the entropy nonce length must be:
+ *                      - at least 24 bytes for a 128-bit strength
+ *                      (maximum achievable strength when using AES-128);
+ *                      - at least 48 bytes for a 256-bit strength
+ *                      (maximum achievable strength when using AES-256).
  *
  * \param ctx           The CTR_DRBG context to seed.
+ *                      It must have been initialized with
+ *                      mbedtls_ctr_drbg_init().
+ *                      After a successful call to mbedtls_ctr_drbg_seed(),
+ *                      you may not call mbedtls_ctr_drbg_seed() again on
+ *                      the same context unless you call
+ *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
+ *                      again first.
  * \param f_entropy     The entropy callback, taking as arguments the
  *                      \p p_entropy context, the buffer to fill, and the
-                        length of the buffer.
- * \param p_entropy     The entropy context.
- * \param custom        Personalization data, that is device-specific
-                        identifiers. Can be NULL.
- * \param len           The length of the personalization data.
+ *                      length of the buffer.
+ *                      \p f_entropy is always called with a buffer size
+ *                      less than or equal to the entropy length.
+ * \param p_entropy     The entropy context to pass to \p f_entropy.
+ * \param custom        The personalization string.
+ *                      This can be \c NULL, in which case the personalization
+ *                      string is empty regardless of the value of \p len.
+ * \param len           The length of the personalization string.
+ *                      This must be at most
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ *                      - #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -197,7 +320,8 @@
  *                      The default value is off.
  *
  * \note                If enabled, entropy is gathered at the beginning of
- *                      every call to mbedtls_ctr_drbg_random_with_add().
+ *                      every call to mbedtls_ctr_drbg_random_with_add()
+ *                      or mbedtls_ctr_drbg_random().
  *                      Only use this if your entropy source has sufficient
  *                      throughput.
  *
@@ -209,18 +333,61 @@
 
 /**
  * \brief               This function sets the amount of entropy grabbed on each
- *                      seed or reseed. The default value is
- *                      #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ *                      seed or reseed.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ *
+ * \note                The security strength of CTR_DRBG is bounded by the
+ *                      entropy length. Thus:
+ *                      - When using AES-256
+ *                        (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled,
+ *                        which is the default),
+ *                        \p len must be at least 32 (in bytes)
+ *                        to achieve a 256-bit strength.
+ *                      - When using AES-128
+ *                        (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled)
+ *                        \p len must be at least 16 (in bytes)
+ *                        to achieve a 128-bit strength.
  *
  * \param ctx           The CTR_DRBG context.
- * \param len           The amount of entropy to grab.
+ * \param len           The amount of entropy to grab, in bytes.
+ *                      This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ *                      and at most the maximum length accepted by the
+ *                      entropy function that is set in the context.
  */
 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
                                size_t len );
 
 /**
+ * \brief               This function sets the amount of entropy grabbed
+ *                      as a nonce for the initial seeding.
+ *
+ * Call this function before calling mbedtls_ctr_drbg_seed() to read
+ * a nonce from the entropy source during the initial seeding.
+ *
+ * \param ctx           The CTR_DRBG context.
+ * \param len           The amount of entropy to grab for the nonce, in bytes.
+ *                      This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ *                      and at most the maximum length accepted by the
+ *                      entropy function that is set in the context.
+ *
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is
+ *                      more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if the initial seeding has already taken place.
+ */
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+                                    size_t len );
+
+/**
  * \brief               This function sets the reseed interval.
- *                      The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
+ *
+ * The reseed interval is the number of calls to mbedtls_ctr_drbg_random()
+ * or mbedtls_ctr_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
  *
  * \param ctx           The CTR_DRBG context.
  * \param interval      The reseed interval.
@@ -233,8 +400,12 @@
  *                      extracts data from the entropy source.
  *
  * \param ctx           The CTR_DRBG context.
- * \param additional    Additional data to add to the state. Can be NULL.
+ * \param additional    Additional data to add to the state. Can be \c NULL.
  * \param len           The length of the additional data.
+ *                      This must be less than
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ *                      where \c entropy_len is the entropy length
+ *                      configured for the context.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -246,7 +417,8 @@
  * \brief              This function updates the state of the CTR_DRBG context.
  *
  * \param ctx          The CTR_DRBG context.
- * \param additional   The data to update the state with.
+ * \param additional   The data to update the state with. This must not be
+ *                     \c NULL unless \p add_len is \c 0.
  * \param add_len      Length of \p additional in bytes. This must be at
  *                     most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
  *
@@ -264,14 +436,23 @@
  * \brief   This function updates a CTR_DRBG instance with additional
  *          data and uses it to generate random data.
  *
- * \note    The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
- * \param output_len    The length of the buffer.
- * \param additional    Additional data to update. Can be NULL.
- * \param add_len       The length of the additional data.
+ * \param output_len    The length of the buffer in bytes.
+ * \param additional    Additional data to update. Can be \c NULL, in which
+ *                      case the additional data is empty regardless of
+ *                      the value of \p add_len.
+ * \param add_len       The length of the additional data
+ *                      if \p additional is not \c NULL.
+ *                      This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT
+ *                      and less than
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ *                      where \c entropy_len is the entropy length
+ *                      configured for the context.
  *
  * \return    \c 0 on success.
  * \return    #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -284,12 +465,14 @@
 /**
  * \brief   This function uses CTR_DRBG to generate random data.
  *
- * \note    The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
+ *
  *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
- * \param output_len    The length of the buffer.
+ * \param output_len    The length of the buffer in bytes.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -336,7 +519,7 @@
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed
  *                      failure.
  */
 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
@@ -350,8 +533,10 @@
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
- *                      #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ *                      reseed failure.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing
+ *                      seed file is too large.
  */
 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
 #endif /* MBEDTLS_FS_IO */
@@ -368,11 +553,6 @@
 
 #endif /* MBEDTLS_SELF_TEST */
 
-/* Internal functions (do not call directly) */
-int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *,
-                               int (*)(void *, unsigned char *, size_t), void *,
-                               const unsigned char *, size_t, size_t );
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 46536a1..00be9df 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -1,10 +1,14 @@
 /**
  * \file hmac_drbg.h
  *
- * \brief HMAC_DRBG (NIST SP 800-90A)
+ * \brief The HMAC_DRBG pseudorandom generator.
+ *
+ * This module implements the HMAC_DRBG pseudorandom generator described
+ * in <em>NIST SP 800-90A: Recommendation for Random Number Generation Using
+ * Deterministic Random Bit Generators</em>.
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2019, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -104,38 +108,72 @@
 } mbedtls_hmac_drbg_context;
 
 /**
- * \brief               HMAC_DRBG context initialization
- *                      Makes the context ready for mbedtls_hmac_drbg_seed(),
- *                      mbedtls_hmac_drbg_seed_buf() or
- *                      mbedtls_hmac_drbg_free().
+ * \brief               HMAC_DRBG context initialization.
  *
- * \param ctx           HMAC_DRBG context to be initialized
+ * This function makes the context ready for mbedtls_hmac_drbg_seed(),
+ * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().
+ *
+ * \param ctx           HMAC_DRBG context to be initialized.
  */
 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
 
 /**
- * \brief               HMAC_DRBG initial seeding
- *                      Seed and setup entropy source for future reseeds.
+ * \brief               HMAC_DRBG initial seeding.
  *
- * \param ctx           HMAC_DRBG context to be seeded
- * \param md_info       MD algorithm to use for HMAC_DRBG
- * \param f_entropy     Entropy callback (p_entropy, buffer to fill, buffer
- *                      length)
- * \param p_entropy     Entropy context
- * \param custom        Personalization data (Device specific identifiers)
- *                      (Can be NULL)
- * \param len           Length of personalization data
+ * Set the initial seed and set up the entropy source for future reseeds.
  *
- * \note                The "security strength" as defined by NIST is set to:
- *                      128 bits if md_alg is SHA-1,
- *                      192 bits if md_alg is SHA-224,
- *                      256 bits if md_alg is SHA-256 or higher.
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ *   with mbedtls_entropy_init() (which registers the platform's default
+ *   entropy sources).
+ *
+ * You can provide a personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ *
+ * \note                By default, the security strength as defined by NIST is:
+ *                      - 128 bits if \p md_info is SHA-1;
+ *                      - 192 bits if \p md_info is SHA-224;
+ *                      - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512.
  *                      Note that SHA-256 is just as efficient as SHA-224.
+ *                      The security strength can be reduced if a smaller
+ *                      entropy length is set with
+ *                      mbedtls_hmac_drbg_set_entropy_len().
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- *                      MBEDTLS_ERR_MD_ALLOC_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ * \note                The default entropy length is the security strength
+ *                      (converted from bits to bytes). You can override
+ *                      it by calling mbedtls_hmac_drbg_set_entropy_len().
+ *
+ * \note                During the initial seeding, this function calls
+ *                      the entropy source to obtain a nonce
+ *                      whose length is half the entropy length.
+ *
+ * \param ctx           HMAC_DRBG context to be seeded.
+ * \param md_info       MD algorithm to use for HMAC_DRBG.
+ * \param f_entropy     The entropy callback, taking as arguments the
+ *                      \p p_entropy context, the buffer to fill, and the
+ *                      length of the buffer.
+ *                      \p f_entropy is always called with a length that is
+ *                      less than or equal to the entropy length.
+ * \param p_entropy     The entropy context to pass to \p f_entropy.
+ * \param custom        The personalization string.
+ *                      This can be \c NULL, in which case the personalization
+ *                      string is empty regardless of the value of \p len.
+ * \param len           The length of the personalization string.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ *                      and also at most
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
+ *                      where \p entropy_len is the entropy length
+ *                      described above.
+ *
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ *                      invalid.
+ * \return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ *                      memory to allocate context data.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if the call to \p f_entropy failed.
  */
 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
                     const mbedtls_md_info_t * md_info,
@@ -146,98 +184,131 @@
 
 /**
  * \brief               Initilisation of simpified HMAC_DRBG (never reseeds).
- *                      (For use with deterministic ECDSA.)
  *
- * \param ctx           HMAC_DRBG context to be initialised
- * \param md_info       MD algorithm to use for HMAC_DRBG
- * \param data          Concatenation of entropy string and additional data
- * \param data_len      Length of data in bytes
+ * This function is meant for use in algorithms that need a pseudorandom
+ * input such as deterministic ECDSA.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- *                      MBEDTLS_ERR_MD_ALLOC_FAILED.
+ * \param ctx           HMAC_DRBG context to be initialised.
+ * \param md_info       MD algorithm to use for HMAC_DRBG.
+ * \param data          Concatenation of the initial entropy string and
+ *                      the additional data.
+ * \param data_len      Length of \p data in bytes.
+ *
+ * \return              \c 0 if successful. or
+ * \return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ *                      invalid.
+ * \return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ *                      memory to allocate context data.
  */
 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
                         const mbedtls_md_info_t * md_info,
                         const unsigned char *data, size_t data_len );
 
 /**
- * \brief               Enable / disable prediction resistance (Default: Off)
+ * \brief               This function turns prediction resistance on or off.
+ *                      The default value is off.
  *
- * Note: If enabled, entropy is used for ctx->entropy_len before each call!
- *       Only use this if you have ample supply of good entropy!
+ * \note                If enabled, entropy is gathered at the beginning of
+ *                      every call to mbedtls_hmac_drbg_random_with_add()
+ *                      or mbedtls_hmac_drbg_random().
+ *                      Only use this if your entropy source has sufficient
+ *                      throughput.
  *
- * \param ctx           HMAC_DRBG context
- * \param resistance    MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF
+ * \param ctx           The HMAC_DRBG context.
+ * \param resistance    #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF.
  */
 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
                                           int resistance );
 
 /**
- * \brief               Set the amount of entropy grabbed on each reseed
- *                      (Default: given by the security strength, which
- *                      depends on the hash used, see \c mbedtls_hmac_drbg_init() )
+ * \brief               This function sets the amount of entropy grabbed on each
+ *                      seed or reseed.
  *
- * \param ctx           HMAC_DRBG context
- * \param len           Amount of entropy to grab, in bytes
+ * See the documentation of mbedtls_hmac_drbg_seed() for the default value.
+ *
+ * \param ctx           The HMAC_DRBG context.
+ * \param len           The amount of entropy to grab, in bytes.
  */
 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
                                 size_t len );
 
 /**
- * \brief               Set the reseed interval
- *                      (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
+ * \brief               Set the reseed interval.
  *
- * \param ctx           HMAC_DRBG context
- * \param interval      Reseed interval
+ * The reseed interval is the number of calls to mbedtls_hmac_drbg_random()
+ * or mbedtls_hmac_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL.
+ *
+ * \param ctx           The HMAC_DRBG context.
+ * \param interval      The reseed interval.
  */
 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
                                     int interval );
 
 /**
- * \brief               HMAC_DRBG update state
+ * \brief               This function updates the state of the HMAC_DRBG context.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to update state with, or NULL
- * \param add_len       Length of additional data, or 0
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    The data to update the state with.
+ *                      If this is \c NULL, there is no additional data.
+ * \param add_len       Length of \p additional in bytes.
+ *                      Unused if \p additional is \c NULL.
  *
  * \return              \c 0 on success, or an error from the underlying
  *                      hash calculation.
- *
- * \note                Additional data is optional, pass NULL and 0 as second
- *                      third argument if no additional data is being used.
  */
 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
                        const unsigned char *additional, size_t add_len );
 
 /**
- * \brief               HMAC_DRBG reseeding (extracts data from entropy source)
+ * \brief               This function reseeds the HMAC_DRBG context, that is
+ *                      extracts data from the entropy source.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to add to state (Can be NULL)
- * \param len           Length of additional data
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    Additional data to add to the state.
+ *                      If this is \c NULL, there is no additional data
+ *                      and \p len should be \c 0.
+ * \param len           The length of the additional data.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ *                      and also at most
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
+ *                      where \p entropy_len is the entropy length
+ *                      (see mbedtls_hmac_drbg_set_entropy_len()).
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy function failed.
  */
 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
                       const unsigned char *additional, size_t len );
 
 /**
- * \brief               HMAC_DRBG generate random with additional update input
+ * \brief   This function updates an HMAC_DRBG instance with additional
+ *          data and uses it to generate random data.
  *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
- * \param p_rng         HMAC_DRBG context
- * \param output        Buffer to fill
- * \param output_len    Length of the buffer
- * \param additional    Additional data to update with (can be NULL)
- * \param add_len       Length of additional data (can be 0)
+ * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
+ *                      #mbedtls_hmac_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param output_len    The length of the buffer in bytes.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \param additional    Additional data to update with.
+ *                      If this is \c NULL, there is no additional data
+ *                      and \p add_len should be \c 0.
+ * \param add_len       The length of the additional data.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
- *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy source failed.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ *                      \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if
+ *                      \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT.
  */
 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
                                unsigned char *output, size_t output_len,
@@ -245,24 +316,29 @@
                                size_t add_len );
 
 /**
- * \brief               HMAC_DRBG generate random
+ * \brief   This function uses HMAC_DRBG to generate random data.
  *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
- * \param p_rng         HMAC_DRBG context
- * \param output        Buffer to fill
- * \param out_len       Length of the buffer
+ * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
+ *                      #mbedtls_hmac_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param out_len       The length of the buffer in bytes.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy source failed.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ *                      \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
  */
 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
 
 /**
  * \brief               Free an HMAC_DRBG context
  *
- * \param ctx           HMAC_DRBG context to free.
+ * \param ctx           The HMAC_DRBG context to free.
  */
 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
 
@@ -273,17 +349,16 @@
 #define MBEDTLS_DEPRECATED
 #endif
 /**
- * \brief               HMAC_DRBG update state
+ * \brief               This function updates the state of the HMAC_DRBG context.
  *
  * \deprecated          Superseded by mbedtls_hmac_drbg_update_ret()
  *                      in 2.16.0.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to update state with, or NULL
- * \param add_len       Length of additional data, or 0
- *
- * \note                Additional data is optional, pass NULL and 0 as second
- *                      third argument if no additional data is being used.
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    The data to update the state with.
+ *                      If this is \c NULL, there is no additional data.
+ * \param add_len       Length of \p additional in bytes.
+ *                      Unused if \p additional is \c NULL.
  */
 MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
     mbedtls_hmac_drbg_context *ctx,
@@ -293,26 +368,31 @@
 
 #if defined(MBEDTLS_FS_IO)
 /**
- * \brief               Write a seed file
+ * \brief               This function writes a seed file.
  *
- * \param ctx           HMAC_DRBG context
- * \param path          Name of the file
+ * \param ctx           The HMAC_DRBG context.
+ * \param path          The name of the file.
  *
- * \return              0 if successful, 1 on file error, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed
+ *                      failure.
  */
 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
 
 /**
- * \brief               Read and update a seed file. Seed is added to this
- *                      instance
+ * \brief               This function reads and updates a seed file. The seed
+ *                      is added to this instance.
  *
- * \param ctx           HMAC_DRBG context
- * \param path          Name of the file
+ * \param ctx           The HMAC_DRBG context.
+ * \param path          The name of the file.
  *
- * \return              0 if successful, 1 on file error,
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
- *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on
+ *                      reseed failure.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing
+ *                      seed file is too large.
  */
 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
 #endif /* MBEDTLS_FS_IO */
@@ -320,9 +400,10 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 /**
- * \brief               Checkup routine
+ * \brief               The HMAC_DRBG Checkup routine.
  *
- * \return              0 if successful, or 1 if the test failed
+ * \return              \c 0 if successful.
+ * \return              \c 1 if the test failed.
  */
 int mbedtls_hmac_drbg_self_test( int verbose );
 #endif
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index 8d18fcc..a87ca81 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -230,9 +230,11 @@
             *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 );
             return( 0 );
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+        default:
+            (void) oid;
+            (void) oid_len;
+            return( -1 );
     }
-
-     return( -1 );
 }
 
 #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 1e7aaa8..7291c3e 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -57,6 +57,22 @@
  * algorithms, key types, policies, etc. */
 #include "crypto_types.h"
 
+/** \defgroup version API version
+ * @{
+ */
+
+/**
+ * The major version of this implementation of the PSA Crypto API
+ */
+#define PSA_CRYPTO_API_VERSION_MAJOR 1
+
+/**
+ * The minor version of this implementation of the PSA Crypto API
+ */
+#define PSA_CRYPTO_API_VERSION_MINOR 0
+
+/**@}*/
+
 /* The file "crypto_values.h" declares macros to build and analyze values
  * of integral types defined in "crypto_types.h". */
 #include "crypto_values.h"
@@ -443,9 +459,12 @@
  * maintain the key handle until after the multipart operation has finished.
  *
  * \param handle        The key handle to close.
+ *                      If this is \c 0, do nothing and return \c PSA_SUCCESS.
  *
  * \retval #PSA_SUCCESS
+ *         \p handle was a valid handle or \c 0. It is now closed.
  * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p handle is not a valid handle nor \c 0.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_BAD_STATE
@@ -563,13 +582,17 @@
  * key will cause the multipart operation to fail.
  *
  * \param handle        Handle to the key to erase.
+ *                      If this is \c 0, do nothing and return \c PSA_SUCCESS.
  *
  * \retval #PSA_SUCCESS
- *         The key material has been erased.
+ *         \p handle was a valid handle and the key material that it
+ *         referred to has been erased.
+ *         Alternatively, \p handle is \c 0.
  * \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
+ *         \p handle is not a valid handle nor \c 0.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  *         There was an failure in communication with the cryptoprocessor.
  *         The key material may still be present in the cryptoprocessor.
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index f0e4782..c5313d6 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -186,6 +186,9 @@
  * \retval #PSA_ERROR_ALREADY_EXISTS
  *         There is already a key with the identifier specified in
  *         \p attributes.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The secure element driver for the specified lifetime does not
+ *         support registering a key.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p attributes specifies a lifetime which is not located
  *         in a secure element.
@@ -428,8 +431,9 @@
  * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM), the group data comes
  * from domain parameters set by psa_set_key_domain_parameters().
  */
-/* This value is reserved for private use in the TLS named group registry. */
-#define PSA_DH_GROUP_CUSTOM             ((psa_dh_group_t) 0x01fc)
+/* This value is a deprecated value meaning an explicit curve in the IANA
+ * registry. */
+#define PSA_DH_GROUP_CUSTOM             ((psa_dh_group_t) 0xff01)
 
 
 /**
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index a43e0db..7ac1ed1 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -927,7 +927,14 @@
  * sake of initial device provisioning or onboarding. Such a mechanism may
  * be added to a future version of the PSA Cryptography API specification.
  *
+ * This function may update the driver's persistent data through
+ * \p persistent_data. The core will save the updated persistent data at the
+ * end of the key creation process. See the description of
+ * ::psa_drv_se_allocate_key_t for more information.
+ *
  * \param[in,out] drv_context   The driver context structure.
+ * \param[in,out] persistent_data   A pointer to the persistent data
+ *                                  that allows writing.
  * \param[in] attributes        Attributes of the key.
  * \param method                The way in which the key is being created.
  * \param[in] key_slot          Slot where the key is to be stored.
@@ -946,6 +953,7 @@
  */
 typedef psa_status_t (*psa_drv_se_validate_slot_number_t)(
     psa_drv_se_context_t *drv_context,
+    void *persistent_data,
     const psa_key_attributes_t *attributes,
     psa_key_creation_method_t method,
     psa_key_slot_number_t key_slot);
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index b6b6198..c4f9acd 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -65,10 +65,82 @@
  */
 typedef uint32_t psa_key_type_t;
 
-/** The type of PSA elliptic curve identifiers. */
+/** The type of PSA elliptic curve identifiers.
+ *
+ * The curve identifier is required to create an ECC key using the
+ * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY()
+ * macros.
+ *
+ * The encoding of curve identifiers is taken from the
+ * TLS Supported Groups Registry (formerly known as the
+ * TLS EC Named Curve Registry)
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
+ *
+ * This specification defines identifiers for some of the curves in the IANA
+ * registry. Implementations that support other curves that are in the IANA
+ * registry should use the IANA value and a implementation-specific identifier.
+ * Implemenations that support non-IANA curves should use one of the following
+ * approaches for allocating a key type:
+ *
+ * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to
+ *    #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use
+ *    range.
+ * 2. Use a ::psa_key_type_t value that is vendor-defined.
+ *
+ * The first option is recommended.
+ */
 typedef uint16_t psa_ecc_curve_t;
 
-/** The type of PSA Diffie-Hellman group identifiers. */
+/** The type of PSA Diffie-Hellman group identifiers.
+ *
+ * The group identifier is required to create an Diffie-Hellman key using the
+ * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY()
+ * macros.
+ *
+ * The encoding of group identifiers is taken from the
+ * TLS Supported Groups Registry (formerly known as the
+ * TLS EC Named Curve Registry)
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
+ *
+ * This specification defines identifiers for some of the groups in the IANA
+ * registry. Implementations that support other groups that are in the IANA
+ * registry should use the IANA value and a implementation-specific identifier.
+ * Implemenations that support non-IANA groups should use one of the following
+ * approaches for allocating a key type:
+ *
+ * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to
+ *    #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use
+ *    range.
+ * 2. Select a ::psa_dh_group_t value from the named groups allocated for
+ *    GREASE in the IETF draft specification. The GREASE specification and
+ *    values are listed below.
+ * 3. Use a ::psa_key_type_t value that is vendor-defined.
+ *
+ * Option 1 or 2 are recommended.
+ *
+ * The current draft of the GREASE specification is
+ * https://datatracker.ietf.org/doc/draft-ietf-tls-grease
+ *
+ * The following GREASE values are allocated for named groups:
+ * \code
+ * 0x0A0A
+ * 0x1A1A
+ * 0x2A2A
+ * 0x3A3A
+ * 0x4A4A
+ * 0x5A5A
+ * 0x6A6A
+ * 0x7A7A
+ * 0x8A8A
+ * 0x9A9A
+ * 0xAAAA
+ * 0xBABA
+ * 0xCACA
+ * 0xDADA
+ * 0xEAEA
+ * 0xFAFA
+ * \endcode
+ */
 typedef uint16_t psa_dh_group_t;
 
 /** \brief Encoding of a cryptographic algorithm.
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 6b6a9f8..1e0c213 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -424,10 +424,18 @@
 #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE        ((psa_key_type_t)0x60030000)
 #define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE           ((psa_key_type_t)0x70030000)
 #define PSA_KEY_TYPE_ECC_CURVE_MASK             ((psa_key_type_t)0x0000ffff)
-/** Elliptic curve key pair. */
+/** Elliptic curve key pair.
+ *
+ * \param curve     A value of type ::psa_ecc_curve_t that identifies the
+ *                  ECC curve to be used.
+ */
 #define PSA_KEY_TYPE_ECC_KEY_PAIR(curve)         \
     (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve))
-/** Elliptic curve public key. */
+/** Elliptic curve public key.
+ *
+ * \param curve     A value of type ::psa_ecc_curve_t that identifies the
+ *                  ECC curve to be used.
+ */
 #define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)              \
     (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))
 
@@ -498,13 +506,34 @@
  */
 #define PSA_ECC_CURVE_CURVE448          ((psa_ecc_curve_t) 0x001e)
 
+/** Minimum value for a vendor-defined ECC curve identifier
+ *
+ * The range for vendor-defined curve identifiers is a subset of the IANA
+ * registry private use range, `0xfe00` - `0xfeff`.
+ */
+#define PSA_ECC_CURVE_VENDOR_MIN        ((psa_ecc_curve_t) 0xfe00)
+/** Maximum value for a vendor-defined ECC curve identifier
+ *
+ * The range for vendor-defined curve identifiers is a subset of the IANA
+ * registry private use range, `0xfe00` - `0xfeff`.
+ */
+#define PSA_ECC_CURVE_VENDOR_MAX        ((psa_ecc_curve_t) 0xfe7f)
+
 #define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE         ((psa_key_type_t)0x60040000)
 #define PSA_KEY_TYPE_DH_KEY_PAIR_BASE            ((psa_key_type_t)0x70040000)
 #define PSA_KEY_TYPE_DH_GROUP_MASK              ((psa_key_type_t)0x0000ffff)
-/** Diffie-Hellman key pair. */
+/** Diffie-Hellman key pair.
+ *
+ * \param group     A value of type ::psa_dh_group_t that identifies the
+ *                  Diffie-Hellman group to be used.
+ */
 #define PSA_KEY_TYPE_DH_KEY_PAIR(group)          \
     (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group))
-/** Diffie-Hellman public key. */
+/** Diffie-Hellman public key.
+ *
+ * \param group     A value of type ::psa_dh_group_t that identifies the
+ *                  Diffie-Hellman group to be used.
+ */
 #define PSA_KEY_TYPE_DH_PUBLIC_KEY(group)               \
     (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group))
 
@@ -538,6 +567,19 @@
 #define PSA_DH_GROUP_FFDHE6144          ((psa_dh_group_t) 0x0103)
 #define PSA_DH_GROUP_FFDHE8192          ((psa_dh_group_t) 0x0104)
 
+/** Minimum value for a vendor-defined Diffie Hellman group identifier
+ *
+ * The range for vendor-defined group identifiers is a subset of the IANA
+ * registry private use range, `0x01fc` - `0x01ff`.
+ */
+#define PSA_DH_GROUP_VENDOR_MIN         ((psa_dh_group_t) 0x01fc)
+/** Maximum value for a vendor-defined Diffie Hellman group identifier
+ *
+ * The range for vendor-defined group identifiers is a subset of the IANA
+ * registry private use range, `0x01fc` - `0x01ff`.
+ */
+#define PSA_DH_GROUP_VENDOR_MAX         ((psa_dh_group_t) 0x01fd)
+
 /** The block size of a block cipher.
  *
  * \param type  A cipher key type (value of type #psa_key_type_t).
@@ -680,11 +722,15 @@
     (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
 
 #define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
-
+/** MD2 */
 #define PSA_ALG_MD2                             ((psa_algorithm_t)0x01000001)
+/** MD4 */
 #define PSA_ALG_MD4                             ((psa_algorithm_t)0x01000002)
+/** MD5 */
 #define PSA_ALG_MD5                             ((psa_algorithm_t)0x01000003)
+/** PSA_ALG_RIPEMD160 */
 #define PSA_ALG_RIPEMD160                       ((psa_algorithm_t)0x01000004)
+/** SHA1 */
 #define PSA_ALG_SHA_1                           ((psa_algorithm_t)0x01000005)
 /** SHA2-224 */
 #define PSA_ALG_SHA_224                         ((psa_algorithm_t)0x01000008)
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 171c340..412259e 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -149,11 +149,28 @@
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
         return( ret );
 
-    if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+    /* len==0 is malformed (0 must be represented as 020100). */
+    if( len == 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    /* This is a cryptography library. Reject negative integers. */
+    if( ( **p & 0x80 ) != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+    /* Skip leading zeros. */
+    while( len > 0 && **p == 0 )
+    {
+        ++( *p );
+        --len;
+    }
+
+    /* Reject integers that don't fit in an int. This code assumes that
+     * the int type has no padding bit. */
+    if( len > sizeof( int ) )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if( len == sizeof( int ) && ( **p & 0x80 ) != 0 )
         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
 
     *val = 0;
-
     while( len-- > 0 )
     {
         *val = ( *val << 8 ) | **p;
@@ -223,8 +240,13 @@
     if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
         return( ret );
 
-    if( (*len)-- < 2 || *(*p)++ != 0 )
+    if( *len == 0 )
         return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+    --( *len );
+
+    if( **p != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+    ++( *p );
 
     return( 0 );
 }
diff --git a/library/asn1write.c b/library/asn1write.c
index b54e26b..a138d0b 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -236,17 +236,20 @@
     int ret;
     size_t len = 0;
 
-    if( *p - start < 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-
-    len += 1;
-    *--(*p) = val;
-
-    if( val > 0 && **p & 0x80 )
+    do
     {
         if( *p - start < 1 )
             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+        len += 1;
+        *--(*p) = val & 0xff;
+        val >>= 8;
+    }
+    while( val > 0 );
 
+    if( **p & 0x80 )
+    {
+        if( *p - start < 1 )
+            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
         *--(*p) = 0x00;
         len += 1;
     }
@@ -429,18 +432,26 @@
         memcpy( cur->oid.p, oid, oid_len );
 
         cur->val.len = val_len;
-        cur->val.p = mbedtls_calloc( 1, val_len );
-        if( cur->val.p == NULL )
+        if( val_len != 0 )
         {
-            mbedtls_free( cur->oid.p );
-            mbedtls_free( cur );
-            return( NULL );
+            cur->val.p = mbedtls_calloc( 1, val_len );
+            if( cur->val.p == NULL )
+            {
+                mbedtls_free( cur->oid.p );
+                mbedtls_free( cur );
+                return( NULL );
+            }
         }
 
         cur->next = *head;
         *head = cur;
     }
-    else if( cur->val.len < val_len )
+    else if( val_len == 0 )
+    {
+        mbedtls_free( cur->val.p );
+        cur->val.p = NULL;
+    }
+    else if( cur->val.len != val_len )
     {
         /*
          * Enlarge existing value buffer if needed
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 0db7beb..047bb2a 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -56,76 +56,15 @@
 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+    /* Indicate that the entropy nonce length is not set explicitly.
+     * See mbedtls_ctr_drbg_set_nonce_len(). */
+    ctx->reseed_counter = -1;
 
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_init( &ctx->mutex );
 #endif
 }
 
-/*
- * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
- * NIST tests to succeed (which require known length fixed entropy)
- */
-/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
- * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
- *                                   custom, len, entropy_len)
- * implements
- * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
- *                      security_strength) -> initial_working_state
- * with inputs
- *   custom[:len] = nonce || personalization_string
- * where entropy_input comes from f_entropy for entropy_len bytes
- * and with outputs
- *   ctx = initial_working_state
- */
-int mbedtls_ctr_drbg_seed_entropy_len(
-                   mbedtls_ctr_drbg_context *ctx,
-                   int (*f_entropy)(void *, unsigned char *, size_t),
-                   void *p_entropy,
-                   const unsigned char *custom,
-                   size_t len,
-                   size_t entropy_len )
-{
-    int ret;
-    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
-
-    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
-
-    mbedtls_aes_init( &ctx->aes_ctx );
-
-    ctx->f_entropy = f_entropy;
-    ctx->p_entropy = p_entropy;
-
-    ctx->entropy_len = entropy_len;
-    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-    /*
-     * Initialize with an empty key
-     */
-    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
-                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
-    {
-        return( ret );
-    }
-    return( 0 );
-}
-
-int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
-                   int (*f_entropy)(void *, unsigned char *, size_t),
-                   void *p_entropy,
-                   const unsigned char *custom,
-                   size_t len )
-{
-    return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
-                                               custom, len,
-                                               MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
-}
-
 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
 {
     if( ctx == NULL )
@@ -150,6 +89,32 @@
     ctx->entropy_len = len;
 }
 
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+                                    size_t len )
+{
+    /* If mbedtls_ctr_drbg_seed() has already been called, it's
+     * too late. Return the error code that's closest to making sense. */
+    if( ctx->f_entropy != NULL )
+        return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+
+    if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#if SIZE_MAX > INT_MAX
+    /* This shouldn't be an issue because
+     * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
+     * configuration, but make sure anyway. */
+    if( len > INT_MAX )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#endif
+
+    /* For backward compatibility with Mbed TLS <= 2.19, store the
+     * entropy nonce length in a field that already exists, but isn't
+     * used until after the initial seeding. */
+    /* Due to the capping of len above, the value fits in an int. */
+    ctx->reseed_counter = (int) len;
+    return( 0 );
+}
+
 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
                                            int interval )
 {
@@ -383,7 +348,7 @@
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
 /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
- * mbedtls_ctr_drbg_reseed(ctx, additional, len)
+ * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
  * implements
  * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
  *                -> new_working_state
@@ -391,51 +356,57 @@
  *   ctx contains working_state
  *   additional[:len] = additional_input
  * and entropy_input comes from calling ctx->f_entropy
+ *                              for (ctx->entropy_len + nonce_len) bytes
  * and with output
  *   ctx contains new_working_state
  */
-int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
-                     const unsigned char *additional, size_t len )
+static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
+                                             const unsigned char *additional,
+                                             size_t len,
+                                             size_t nonce_len )
 {
     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
     size_t seedlen = 0;
     int ret;
 
-    if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
-        len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+    if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
         return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
 
     memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
 
-    /*
-     * Gather entropy_len bytes of entropy to seed state
-     */
-    if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
-                             ctx->entropy_len ) )
+    /* Gather entropy_len bytes of entropy to seed state. */
+    if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
     {
         return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
     }
-
     seedlen += ctx->entropy_len;
 
-    /*
-     * Add additional data
-     */
-    if( additional && len )
+    /* Gather entropy for a nonce if requested. */
+    if( nonce_len != 0 )
+    {
+        if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
+        {
+            return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+        }
+        seedlen += nonce_len;
+    }
+
+    /* Add additional data if provided. */
+    if( additional != NULL && len != 0 )
     {
         memcpy( seed + seedlen, additional, len );
         seedlen += len;
     }
 
-    /*
-     * Reduce to 384 bits
-     */
+    /* Reduce to 384 bits. */
     if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
         goto exit;
 
-    /*
-     * Update state
-     */
+    /* Update state. */
     if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
         goto exit;
     ctx->reseed_counter = 1;
@@ -445,6 +416,81 @@
     return( ret );
 }
 
+int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
+                             const unsigned char *additional, size_t len )
+{
+    return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
+}
+
+/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
+ * is sufficient to achieve the maximum security strength given the key
+ * size and entropy length. If there is enough entropy in the initial
+ * call to the entropy function to serve as both the entropy input and
+ * the nonce, don't make a second call to get a nonce. */
+static size_t good_nonce_len( size_t entropy_len )
+{
+    if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
+        return( 0 );
+    else
+        return( ( entropy_len + 1 ) / 2 );
+}
+
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ *                      security_strength) -> initial_working_state
+ * with inputs
+ *   custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for ctx->entropy_len bytes
+ * and with outputs
+ *   ctx = initial_working_state
+ */
+int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
+                           int (*f_entropy)(void *, unsigned char *, size_t),
+                           void *p_entropy,
+                           const unsigned char *custom,
+                           size_t len )
+{
+    int ret;
+    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+    size_t nonce_len;
+
+    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+
+    mbedtls_aes_init( &ctx->aes_ctx );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    if( ctx->entropy_len == 0 )
+        ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    /* ctx->reseed_counter contains the desired amount of entropy to
+     * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
+     * If it's -1, indicating that the entropy nonce length was not set
+     * explicitly, use a sufficiently large nonce for security. */
+    nonce_len = ( ctx->reseed_counter >= 0 ?
+                  (size_t) ctx->reseed_counter :
+                  good_nonce_len( ctx->entropy_len ) );
+
+    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
+    /* Initialize with an empty key. */
+    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
+                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Do the initial seeding. */
+    if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
+                                                  nonce_len ) ) != 0 )
+    {
+        return( ret );
+    }
+    return( 0 );
+}
+
 /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
  * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
  * implements
@@ -708,8 +754,12 @@
         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
 
     test_offset = 0;
-    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
-                         (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+    mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+    CHK( mbedtls_ctr_drbg_seed( &ctx,
+                                ctr_drbg_self_test_entropy,
+                                (void *) entropy_source_pr,
+                                nonce_pers_pr, 16 ) );
     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
@@ -729,8 +779,12 @@
     mbedtls_ctr_drbg_init( &ctx );
 
     test_offset = 0;
-    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
-                     (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+    mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+    CHK( mbedtls_ctr_drbg_seed( &ctx,
+                                ctr_drbg_self_test_entropy,
+                                (void *) entropy_source_nopr,
+                                nonce_pers_nopr, 16 ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
diff --git a/library/error.c b/library/error.c
index 7d7155b..649b3ba 100644
--- a/library/error.c
+++ b/library/error.c
@@ -467,7 +467,7 @@
     if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) )
         mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
     if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) )
-        mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+        mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid" );
     if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) )
         mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
     if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) )
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 67123df..f71c95c 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -273,16 +273,19 @@
 
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
 
-    /*
-     * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
-     * each hash function, then according to SP800-90A rev1 10.1 table 2,
-     * min_entropy_len (in bits) is security_strength.
-     *
-     * (This also matches the sizes used in the NIST test vectors.)
-     */
-    ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
-                       md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
-                       32;  /* better (256+) -> 256 bits */
+    if( ctx->entropy_len == 0 )
+    {
+        /*
+         * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+         * each hash function, then according to SP800-90A rev1 10.1 table 2,
+         * min_entropy_len (in bits) is security_strength.
+         *
+         * (This also matches the sizes used in the NIST test vectors.)
+         */
+        ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+                           md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+                           32;  /* better (256+) -> 256 bits */
+    }
 
     if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
                                        1 /* add nonce */ ) ) != 0 )
@@ -303,7 +306,7 @@
 }
 
 /*
- * Set entropy length grabbed for reseeds
+ * Set entropy length grabbed for seeding
  */
 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
 {
diff --git a/library/pkcs5.c b/library/pkcs5.c
index e7d805c..3d29fd7 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -243,13 +243,12 @@
         return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
 #endif
 
+    if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
+        return( ret );
     while( key_length )
     {
         // U1 ends up in work
         //
-        if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
-            return( ret );
-
         if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
             return( ret );
 
@@ -259,21 +258,24 @@
         if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
             return( ret );
 
+        if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+           return( ret );
+
         memcpy( md1, work, md_size );
 
         for( i = 1; i < iteration_count; i++ )
         {
             // U2 ends up in md1
             //
-            if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
-                return( ret );
-
             if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
                 return( ret );
 
             if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
                 return( ret );
 
+            if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+                return( ret );
+
             // U1 xor U2
             //
             for( j = 0; j < md_size; j++ )
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 4388160..c2c5623 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -38,7 +38,9 @@
 #include "mbedtls/rsa.h"
 #endif
 #if defined(MBEDTLS_ECP_C)
+#include "mbedtls/bignum.h"
 #include "mbedtls/ecp.h"
+#include "mbedtls/platform_util.h"
 #endif
 #if defined(MBEDTLS_ECDSA_C)
 #include "mbedtls/ecdsa.h"
@@ -154,6 +156,26 @@
 
     return( (int) len );
 }
+
+/*
+ * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
+ */
+static int pk_write_ec_private( unsigned char **p, unsigned char *start,
+                                mbedtls_ecp_keypair *ec )
+{
+    int ret;
+    size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
+    unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
+
+    ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length );
+
+exit:
+    mbedtls_platform_zeroize( tmp, byte_length );
+    return( ret );
+}
 #endif /* MBEDTLS_ECP_C */
 
 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
@@ -424,9 +446,8 @@
                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
         len += par_len;
 
-        /* privateKey: write as MPI then fix tag */
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) );
-        *c = MBEDTLS_ASN1_OCTET_STRING;
+        /* privateKey */
+        MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) );
 
         /* version */
         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index b9ea00f..e4d4924 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1013,6 +1013,9 @@
     psa_se_drv_table_entry_t *driver;
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
+    if( handle == 0 )
+        return( PSA_SUCCESS );
+
     status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
@@ -1579,7 +1582,7 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     /* For a key in a secure element, we need to do three things
-     * when creating a key (but not when registering an existing key):
+     * when creating or registering a key:
      * create the key file in internal storage, create the
      * key inside the secure element, and update the driver's
      * persistent data. Start a transaction that will encompass these
@@ -1592,7 +1595,7 @@
      * secure element driver updates its persistent state, but we do not yet
      * save the driver's persistent state, so that if the power fails,
      * we can roll back to a state where the key doesn't exist. */
-    if( *p_drv != NULL && method != PSA_KEY_CREATION_REGISTER )
+    if( *p_drv != NULL )
     {
         status = psa_find_se_slot_for_key( attributes, method, *p_drv,
                                            &slot->data.se.slot_number );
@@ -1609,6 +1612,12 @@
             return( status );
         }
     }
+
+    if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER )
+    {
+        /* Key registration only makes sense with a secure element. */
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     return( status );
@@ -1883,7 +1892,6 @@
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
-    const psa_drv_se_t *drv;
     psa_key_handle_t handle = 0;
 
     /* Leaving attributes unspecified is not currently supported.
@@ -1900,37 +1908,6 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    if( driver == NULL )
-    {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        goto exit;
-    }
-    drv = psa_get_se_driver_methods( driver );
-
-    if ( psa_get_key_slot_number( attributes,
-                                  &slot->data.se.slot_number ) != PSA_SUCCESS )
-    {
-        /* The application didn't specify a slot number. This doesn't
-         * make sense when registering a slot. */
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        goto exit;
-    }
-
-    /* If the driver has a slot number validation method, call it.
-     * If it doesn't, it means the secure element is unable to validate
-     * anything and so we have to trust the application. */
-    if( drv->key_management != NULL &&
-        drv->key_management->p_validate_slot_number != NULL )
-    {
-        status = drv->key_management->p_validate_slot_number(
-            psa_get_se_driver_context( driver ),
-            attributes,
-            PSA_KEY_CREATION_REGISTER,
-            slot->data.se.slot_number );
-        if( status != PSA_SUCCESS )
-            goto exit;
-    }
-
     status = psa_finish_key_creation( slot, driver );
 
 exit:
@@ -2029,6 +2006,7 @@
 /* Message digests */
 /****************************************************************/
 
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC)
 static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
 {
     switch( alg )
@@ -2069,6 +2047,7 @@
             return( NULL );
     }
 }
+#endif
 
 psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
 {
@@ -5713,6 +5692,12 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    status = psa_init_all_se_drivers( );
+    if( status != PSA_SUCCESS )
+        goto exit;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
     status = psa_crypto_load_transaction( );
     if( status == PSA_SUCCESS )
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index 523c621..b7fa0c5 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -222,9 +222,16 @@
         if( p_validate_slot_number == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
         status = p_validate_slot_number( &driver->context,
+                                         driver->internal.persistent_data,
                                          attributes, method,
                                          *slot_number );
     }
+    else if( method == PSA_KEY_CREATION_REGISTER )
+    {
+        /* The application didn't specify a slot number. This doesn't
+         * make sense when registering a slot. */
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    }
     else
     {
         /* The application didn't tell us which slot to use. Let the driver
@@ -265,6 +272,31 @@
     return( status == PSA_SUCCESS ? storage_status : status );
 }
 
+psa_status_t psa_init_all_se_drivers( void )
+{
+    size_t i;
+    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
+    {
+        psa_se_drv_table_entry_t *driver = &driver_table[i];
+        if( driver->lifetime == 0 )
+            continue; /* skipping unused entry */
+        const psa_drv_se_t *methods = psa_get_se_driver_methods( driver );
+        if( methods->p_init != NULL )
+        {
+            psa_status_t status = methods->p_init(
+                &driver->context,
+                driver->internal.persistent_data,
+                driver->lifetime );
+            if( status != PSA_SUCCESS )
+                return( status );
+            status = psa_save_se_persistent_data( driver );
+            if( status != PSA_SUCCESS )
+                return( status );
+        }
+    }
+    return( PSA_SUCCESS );
+}
+
 
 
 /****************************************************************/
@@ -309,6 +341,8 @@
 
     driver_table[i].lifetime = lifetime;
     driver_table[i].methods = methods;
+    driver_table[i].internal.persistent_data_size =
+        methods->persistent_data_size;
 
     if( methods->persistent_data_size != 0 )
     {
@@ -326,8 +360,6 @@
         if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST )
             goto error;
     }
-    driver_table[i].internal.persistent_data_size =
-        methods->persistent_data_size;
 
     return( PSA_SUCCESS );
 
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 900a72b..86bf7a7 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -66,6 +66,12 @@
  */
 void psa_unregister_all_se_drivers( void );
 
+/** Initialize all secure element drivers.
+ *
+ * Called from psa_crypto_init().
+ */
+psa_status_t psa_init_all_se_drivers( void );
+
 /** A structure that describes a registered secure element driver.
  *
  * A secure element driver table entry contains a pointer to the
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 59be319..6cd6a11 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -255,6 +255,9 @@
     psa_status_t status;
     psa_key_slot_t *slot;
 
+    if( handle == 0 )
+        return( PSA_SUCCESS );
+
     status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index a27442c..1389fd4 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -419,7 +419,7 @@
 {
     struct psa_storage_info_t p_info;
     psa_status_t status;
-    status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
+    status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info );
     if( status == PSA_SUCCESS )
     {
         /* This shouldn't happen: we're trying to start a transaction while
diff --git a/library/version_features.c b/library/version_features.c
index 5404d79..a91723f 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -300,6 +300,9 @@
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
     "MBEDTLS_CIPHER_PADDING_ZEROS",
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+    "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY",
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
     "MBEDTLS_ECP_DP_SECP192R1_ENABLED",
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index b005c20..8f89c70 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -686,12 +686,13 @@
         mbedtls_ctr_drbg_context ctr_drbg;
 
         mbedtls_ctr_drbg_init( &ctr_drbg );
-
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         TIME_AND_TSC( "CTR_DRBG (NOPR)",
                 mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
+        mbedtls_ctr_drbg_free( &ctr_drbg );
 
+        mbedtls_ctr_drbg_init( &ctr_drbg );
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index da3dfb0..1832b2c 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -828,6 +828,14 @@
     }
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
 
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+    if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
+
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
     if( strcmp( "MBEDTLS_ECP_DP_SECP192R1_ENABLED", config ) == 0 )
     {
@@ -1676,14 +1684,6 @@
     }
 #endif /* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT */
 
-#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-    if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 )
-    {
-        MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY );
-        return( 0 );
-    }
-#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
-
 #if defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
     if( strcmp( "MBEDTLS_HMAC_DRBG_RESEED_INTERVAL", config ) == 0 )
     {
diff --git a/scripts/config.pl b/scripts/config.pl
index ed0967d..8066bb0 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -78,6 +78,7 @@
 MBEDTLS_DEPRECATED_REMOVED
 MBEDTLS_HAVE_SSE2
 MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
 MBEDTLS_ECP_DP_M221_ENABLED
 MBEDTLS_ECP_DP_M383_ENABLED
 MBEDTLS_ECP_DP_M511_ENABLED
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7dcc98d..bcf462f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -79,6 +79,7 @@
 add_test_suite(aes aes.xts)
 add_test_suite(arc4)
 add_test_suite(aria)
+add_test_suite(asn1parse)
 add_test_suite(asn1write)
 add_test_suite(base64)
 add_test_suite(blowfish)
diff --git a/tests/data_files/ec_256_long_prv.pem b/tests/data_files/ec_256_long_prv.pem
new file mode 100644
index 0000000..5141e30
--- /dev/null
+++ b/tests/data_files/ec_256_long_prv.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIIcex4mqXsQamUKTVf8vXmTAJrQvGjh5mXG8p9+OR4xAoAoGCCqGSM49
+AwEHoUQDQgAEqJ2HQjPpc6fDwE/vSa6U35USXawkTo98y4U6NsAl+rOGuqMPEFXf
+P1Srm/Jrzwa/RuppRL5kgyAsGJTUmwZEzQ==
+-----END EC PRIVATE KEY-----
diff --git a/tests/data_files/ec_521_short_prv.pem b/tests/data_files/ec_521_short_prv.pem
new file mode 100644
index 0000000..427b7ad
--- /dev/null
+++ b/tests/data_files/ec_521_short_prv.pem
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIAOXdk7W+Hf5L7Hc9fKe44wmpaRNs5ERFTkv5CrlXv/Bu3y28M673q
+vBNo7a/UE/6NNQHu2pQODEYFpMg6R34b5SigBwYFK4EEACOhgYkDgYYABAFUMHXV
+KPA4vkMgq+pFgDoH96XoM517gF2GJFV6h2gLhykzIHL/otAyEpAStw7MBvbU0V21
+ixB+hjqzO7Snxaj9mwB8g87OKxm5eGfsqvJNPdJ0RZ/EKy06Ukg6KThlhQeyrtIk
+g5PTCrPnNszlffAy6/jCOe3Moi59g15H13sSzwfX6g==
+-----END EC PRIVATE KEY-----
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index d4cb011..282c513 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -128,6 +128,9 @@
     # Include more verbose output for failing tests run by CMake
     export CTEST_OUTPUT_ON_FAILURE=1
 
+    # CFLAGS and LDFLAGS for Asan builds that don't use CMake
+    ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
+
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
     # Parse the script with sed, because in sh there is no way to list
@@ -826,7 +829,7 @@
     msg "build: malloc(0) returns NULL (ASan+UBSan build)"
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
-    make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined'
+    make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' $ASAN_CFLAGS -O" LDFLAGS="$ASAN_CFLAGS"
 
     msg "test: malloc(0) returns NULL (ASan+UBSan build)"
     make test
@@ -868,7 +871,7 @@
 component_test_se_default () {
     msg "build: default config + MBEDTLS_PSA_CRYPTO_SE_C"
     scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
-    make CC=clang CFLAGS='-Werror -Wall -Wextra -Wno-unused-function -Os -fsanitize=address' LDFLAGS='-fsanitize=address'
+    make CC=clang CFLAGS="$ASAN_CFLAGS -Os" LDFLAGS="$ASAN_CFLAGS"
 
     msg "test: default config + MBEDTLS_PSA_CRYPTO_SE_C"
     make test
@@ -876,8 +879,10 @@
 
 component_test_se_full () {
     msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C"
+    scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -O2 -fsanitize=address' LDFLAGS='-fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
 
     msg "test: full config + MBEDTLS_PSA_CRYPTO_SE_C"
     make test
@@ -912,7 +917,7 @@
     # Build once with -O0, to compile out the i386 specific inline assembly
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32 -fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O0 (ASan build)"
     make test
@@ -931,7 +936,7 @@
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
     scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl unset MBEDTLS_MEMORY_DEBUG
-    make CC=gcc CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32 -fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O1 (ASan build)"
     make test
@@ -944,7 +949,7 @@
     msg "build: i386, Everest ECDH context (ASan build)" # ~ 6 min
     scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT
     scripts/config.pl set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
-    make CC=gcc CFLAGS='-O2 -Werror -Wall -Wextra -m32 -fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
     make test
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 1c9dc1d..d06badd 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -93,7 +93,7 @@
     $suite_cases_failed = () = $result =~ /.. FAILED/g;
     $suite_cases_skipped = () = $result =~ /.. ----/g;
 
-    if( $result =~ /PASSED/ ) {
+    if( $? == 0 ) {
         print "PASS\n";
         if( $verbose > 2 ) {
             pad_print_center( 72, '-', "Begin $suite" );
diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl
index 09baebb..1e65969 100755
--- a/tests/scripts/test-ref-configs.pl
+++ b/tests/scripts/test-ref-configs.pl
@@ -17,6 +17,8 @@
 use strict;
 
 my %configs = (
+    'config-symmetric-only.h' => {
+    },
     'config-suite-b.h' => {
     },
 );
@@ -48,6 +50,15 @@
     exit 1;
 }
 
+# Create a seedfile for configurations that enable MBEDTLS_ENTROPY_NV_SEED.
+# For test purposes, this doesn't have to be cryptographically random.
+if (!-e "tests/seedfile" || -s "tests/seedfile" < 64) {
+    local *SEEDFILE;
+    open SEEDFILE, ">tests/seedfile" or die;
+    print SEEDFILE "*" x 64 or die;
+    close SEEDFILE or die;
+}
+
 while( my ($conf, $data) = each %configs ) {
     system( "cp $config_h.bak $config_h" ) and die;
     system( "make clean" ) and die;
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 1a524a6..00320bc 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -158,6 +158,26 @@
     }                                                             \
     while( 0 )
 
+/** Allocate memory dynamically. Exit the test if this fails, but do
+ * not mark the test as failed.
+ *
+ * This macro behaves like #ASSERT_ALLOC, except that if the allocation
+ * fails, it jumps to the \c exit label without calling test_fail().
+ */
+#define ASSERT_ALLOC_WEAK( pointer, length )                      \
+    do                                                            \
+    {                                                             \
+        TEST_ASSERT( ( pointer ) == NULL );                       \
+        if( ( length ) != 0 )                                     \
+        {                                                         \
+            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
+                                          ( length ) );           \
+            if( ( pointer ) == NULL )                             \
+                goto exit;                                        \
+        }                                                         \
+    }                                                             \
+    while( 0 )
+
 /** Compare two buffers and fail the test case if they differ.
  *
  * This macro expands to an instruction, not an expression.
@@ -393,6 +413,7 @@
     const char *test;
     const char *filename;
     int line_no;
+    unsigned long step;
 }
 test_info;
 
@@ -423,6 +444,19 @@
 /*----------------------------------------------------------------------------*/
 /* Helper Functions */
 
+/** Set the test step number for failure reports.
+ *
+ * Call this function to display "step NNN" in addition to the line number
+ * and file name if a test fails. Typically the "step number" is the index
+ * of a for loop but it can be whatever you want.
+ *
+ * \param step  The step number to report.
+ */
+void test_set_step( unsigned long step )
+{
+    test_info.step = step;
+}
+
 void test_fail( const char *test, int line_no, const char* filename )
 {
     test_info.result = TEST_RESULT_FAILED;
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index 0f98d23..24d9b97 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -548,6 +548,7 @@
             {
                 test_info.result = TEST_RESULT_SUCCESS;
                 test_info.paramfail_test_state = PARAMFAIL_TESTSTATE_IDLE;
+                test_info.step = (unsigned long)( -1 );
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
                 /* Suppress all output from the library unless we're verbose
@@ -624,9 +625,15 @@
                 {
                     total_errors++;
                     mbedtls_fprintf( stdout, "FAILED\n" );
-                    mbedtls_fprintf( stdout, "  %s\n  at line %d, %s\n",
-                                     test_info.test, test_info.line_no,
-                                     test_info.filename );
+                    mbedtls_fprintf( stdout, "  %s\n  at ",
+                                     test_info.test );
+                    if( test_info.step != (unsigned long)( -1 ) )
+                    {
+                        mbedtls_fprintf( stdout, "step %lu, ",
+                                         test_info.step );
+                    }
+                    mbedtls_fprintf( stdout, "line %d, %s",
+                                     test_info.line_no, test_info.filename );
                 }
                 fflush( stdout );
             }
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
index 91f7198..3d88957 100644
--- a/tests/suites/target_test.function
+++ b/tests/suites/target_test.function
@@ -75,7 +75,7 @@
     c[1] = greentea_getc();
     c[2] = '\0';
 
-    assert( unhexify( &byte, c ) != 2 );
+    TEST_HELPER_ASSERT( unhexify( &byte, c ) != 2 );
     return( byte );
 }
 
@@ -90,18 +90,19 @@
 uint32_t receive_uint32()
 {
     uint32_t value;
-    const uint8_t c[9] = { greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           greentea_getc(),
-                           '\0'
-                         };
-    assert( unhexify( &value, c ) != 8 );
-    return( (uint32_t)value );
+    const uint8_t c_be[8] = { greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc(),
+                              greentea_getc()
+                             };
+    const uint8_t c[9] = { c_be[6], c_be[7], c_be[4], c_be[5], c_be[2],
+                           c_be[3], c_be[0], c_be[1], '\0' };
+    TEST_HELPER_ASSERT( unhexify( (uint8_t*)&value, c ) != 8 );
+    return( value );
 }
 
 /**
@@ -368,13 +369,14 @@
     void ** params = NULL;
     uint8_t * data = NULL, * p = NULL;
 
-    GREENTEA_SETUP( 180, "mbedtls_test" );
+    GREENTEA_SETUP( 800, "mbedtls_test" );
     greentea_send_kv( "GO", " " );
 
     while ( 1 )
     {
         ret = 0;
         test_info.result = TEST_RESULT_SUCCESS;
+        test_info.step = (unsigned long)( -1 );
         data_len = 0;
 
         data = receive_data( &data_len );
diff --git a/tests/suites/test_suite_asn1parse.data b/tests/suites/test_suite_asn1parse.data
new file mode 100644
index 0000000..4abae0b
--- /dev/null
+++ b/tests/suites/test_suite_asn1parse.data
@@ -0,0 +1,491 @@
+Empty length
+parse_prefixes:"04":0:MBEDTLS_ERR_ASN1_INVALID_LENGTH
+
+Prefixes of OCTET STRING, length=0
+parse_prefixes:"04007e":2:0
+
+Prefixes of OCTET STRING, length=0 (0 length bytes)
+parse_prefixes:"04807e":2:MBEDTLS_ERR_ASN1_INVALID_LENGTH
+
+Prefixes of OCTET STRING, length=1
+parse_prefixes:"0401417e":3:0
+
+Prefixes of OCTET STRING, length=2
+parse_prefixes:"040241427e":4:0
+
+Prefixes of BOOLEAN, length=0
+parse_prefixes:"01007e":2:MBEDTLS_ERR_ASN1_INVALID_LENGTH
+
+Prefixes of BOOLEAN, length=1
+parse_prefixes:"0101007e":3:0
+
+Prefixes of BOOLEAN, length=2
+parse_prefixes:"010200007e":4:MBEDTLS_ERR_ASN1_INVALID_LENGTH
+
+Prefixes of INTEGER, length=1
+parse_prefixes:"0201417e":3:0
+
+Prefixes of INTEGER, length=2
+parse_prefixes:"020241427e":4:0
+
+Prefixes of INTEGER, length=5
+parse_prefixes:"020541424344457e":7:0
+
+Prefixes of empty BIT STRING
+parse_prefixes:"03007e":2:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+Prefixes of BIT STRING, unused_bits=0, payload_length=0
+parse_prefixes:"030100":3:0
+
+Prefixes of BIT STRING, unused_bits=0, payload_length=1
+parse_prefixes:"0302002a":4:0
+
+Prefixes of BIT STRING, unused_bits=1, payload_length=1
+parse_prefixes:"0302012a":4:0
+
+Prefixes of empty SEQUENCE
+parse_prefixes:"30007e":2:0
+
+Prefixes of SEQUENCE of BOOLEAN, INTEGER, INTEGER
+parse_prefixes:"300b01010102012a02031234567e":13:0
+
+Prefixes of SEQUENCE of (SEQUENCE of INTEGER, INTEGER), INTEGER
+parse_prefixes:"300b30060201410201420201617e":13:0
+
+length=0 (short form)
+get_len:"00":0
+
+length=0 (1 length byte)
+get_len:"8100":0
+
+length=0 (2 length bytes)
+get_len:"820000":0
+
+length=1 (short form)
+get_len:"01":1
+
+length=1 (1 length byte)
+get_len:"8101":1
+
+length=1 (2 length bytes)
+get_len:"820001":1
+
+length=1 (3 length bytes)
+get_len:"83000001":1
+
+length=1 (4 length bytes)
+get_len:"8400000001":1
+
+length=2 (short form)
+get_len:"02":2
+
+length=2 (1 length byte)
+get_len:"8102":2
+
+length=2 (2 length bytes)
+get_len:"820002":2
+
+length=2 (3 length bytes)
+get_len:"83000002":2
+
+length=2 (4 length bytes)
+get_len:"8400000002":2
+
+length=127 (short form)
+get_len:"7f":127
+
+length=128 (1 length byte)
+get_len:"8180":128
+
+length=128 (2 length bytes)
+get_len:"820080":128
+
+length=255 (1 length byte)
+get_len:"81ff":255
+
+length=255 (2 length bytes)
+get_len:"8200ff":255
+
+length=256 (2 length bytes)
+get_len:"820100":256
+
+length=256 (3 length bytes)
+get_len:"83000100":256
+
+length=258 (2 length bytes)
+get_len:"820102":258
+
+length=258 (3 length bytes)
+get_len:"83000102":258
+
+length=65535 (2 length bytes)
+get_len:"82ffff":65535
+
+length=65535 (3 length bytes)
+get_len:"8300ffff":65535
+
+length=65535 (4 length bytes)
+get_len:"840000ffff":65535
+
+length=65536 (3 length bytes)
+get_len:"83010000":65536
+
+length=65536 (4 length bytes)
+get_len:"8400010000":65536
+
+length=16777215 (3 length bytes)
+get_len:"83ffffff":16777215
+
+length=16777215 (4 length bytes)
+get_len:"8400ffffff":16777215
+
+length=16777216 (4 length bytes)
+get_len:"8401000000":16777216
+
+length=16909060 (4 length bytes)
+get_len:"8401020304":16909060
+
+BOOLEAN FALSE
+get_boolean:"010100":0:0
+
+BOOLEAN TRUE (1)
+get_boolean:"010101":1:0
+
+BOOLEAN TRUE (2)
+get_boolean:"010101":1:0
+
+BOOLEAN TRUE (128)
+get_boolean:"010180":1:0
+
+BOOLEAN TRUE (255)
+get_boolean:"0101ff":1:0
+
+Not BOOLEAN
+get_boolean:"020101":0:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+Empty INTEGER
+empty_integer:"0200"
+
+INTEGER 0
+get_integer:"020100":"0":0
+
+INTEGER 0, extra leading 0
+get_integer:"02020000":"0":0
+
+INTEGER 1
+get_integer:"020101":"1":0:
+
+INTEGER 1, extra leading 0
+get_integer:"02020001":"1":0:
+
+INTEGER 0x7f
+get_integer:"02017f":"7f":0
+
+INTEGER 0x80
+get_integer:"02020080":"80":0
+
+INTEGER 0x80, extra leading 0
+get_integer:"0203000080":"80":0
+
+INTEGER 0xff
+get_integer:"020200ff":"ff":0
+
+INTEGER 0x7fff
+get_integer:"02027fff":"7fff":0
+
+INTEGER 0x12345678
+get_integer:"020412345678":"12345678":0
+
+INTEGER 0x12345678, extra leading 0
+get_integer:"02050012345678":"12345678":0
+
+INTEGER 0x7fffffff
+get_integer:"02047fffffff":"7fffffff":0
+
+INTEGER 0x7fffffff, extra leading 0
+get_integer:"0205007fffffff":"7fffffff":0
+
+INTEGER 0x80000000
+get_integer:"02050080000000":"80000000":0
+
+INTEGER 0xffffffff
+get_integer:"020500ffffffff":"ffffffff":0
+
+INTEGER 0x100000000
+get_integer:"02050100000000":"0100000000":0
+
+INTEGER 0x123456789abcdef0
+get_integer:"0208123456789abcdef0":"123456789abcdef0":0
+
+INTEGER 0xfedcab9876543210
+get_integer:"020900fedcab9876543210":"fedcab9876543210":0
+
+INTEGER 0x1fedcab9876543210
+get_integer:"020901fedcab9876543210":"1fedcab9876543210":0
+
+INTEGER with 127 value octets
+get_integer:"027f0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":0
+
+INTEGER with 127 value octets (long length encoding)
+get_integer:"02817f0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd":0
+
+INTEGER with 128 value octets
+get_integer:"0281800123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":0
+
+INTEGER with 128 value octets (leading 0 in length)
+get_integer:"028200800123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":0
+
+INTEGER -1
+get_integer:"0201ff":"-1":0
+
+INTEGER -1, extra leading ff
+get_integer:"0202ffff":"-1":0
+
+INTEGER -0x7f
+get_integer:"020181":"-7f":0
+
+INTEGER -0x80
+get_integer:"020180":"-80":0
+
+INTEGER -0x81
+get_integer:"0202ff7f":"-81":0
+
+INTEGER -0xff
+get_integer:"0202ff01":"-ff":0
+
+INTEGER -0x100
+get_integer:"0202ff00":"-100":0
+
+INTEGER -0x7fffffff
+get_integer:"020480000001":"-7fffffff":0
+
+INTEGER -0x80000000
+get_integer:"020480000000":"-80000000":0
+
+INTEGER -0x80000001
+get_integer:"0205ff7fffffff":"-80000001":0
+
+INTEGER -0xffffffff
+get_integer:"0205ff00000001":"-ffffffff":0
+
+INTEGER -0x100000000
+get_integer:"0205ff00000000":"-100000000":0
+
+INTEGER -0x123456789abcdef0
+get_integer:"0208edcba98765432110":"-123456789abcdef0":0
+
+INTEGER -0xfedcba9876543210
+get_integer:"0209ff0123456789abcdf0":"-fedcba9876543210":0
+
+INTEGER -0x1fedcab9876543210
+get_integer:"0209fe0123546789abcdf0":"-1fedcab9876543210":0
+
+Not INTEGER
+get_integer:"010101":"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+INTEGER too large for mpi
+get_mpi_too_large:
+
+BIT STRING: empty
+get_bitstring:"0300":0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=0, unused_bits=0
+get_bitstring:"030100":0:0:0:0
+
+BIT STRING: octets=0, unused_bits=7
+get_bitstring:"030107":0:7:0:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=0, unused_bits=8
+get_bitstring:"030108":0:0:MBEDTLS_ERR_ASN1_INVALID_LENGTH:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=1, unused_bits=0
+get_bitstring:"03020041":1:0:0:0
+
+BIT STRING: octets=1, unused_bits=7
+get_bitstring:"03020741":1:7:0:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=1, unused_bits=8
+get_bitstring:"03020841":1:8:MBEDTLS_ERR_ASN1_INVALID_LENGTH:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=2, unused_bits=0
+get_bitstring:"0303004142":2:0:0:0
+
+BIT STRING: octets=2, unused_bits=7
+get_bitstring:"0303074142":2:7:0:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING: octets=2, unused_bits=8
+get_bitstring:"0303084142":2:8:MBEDTLS_ERR_ASN1_INVALID_LENGTH:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING with trailing garbage, unused_bits=0
+get_bitstring:"030200417e":1:0:MBEDTLS_ERR_ASN1_LENGTH_MISMATCH:0
+
+BIT STRING with trailing garbage, unused_bits=7
+get_bitstring:"030207417e":1:7:MBEDTLS_ERR_ASN1_LENGTH_MISMATCH:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+BIT STRING with trailing garbage, unused_bits=8
+get_bitstring:"030208417e":1:8:MBEDTLS_ERR_ASN1_INVALID_LENGTH:MBEDTLS_ERR_ASN1_INVALID_DATA
+
+Not BIT STRING
+get_bitstring:"04020100":0:0:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+SEQUENCE OF 0 OCTET STRING
+get_sequence_of:"3000":0x04:"":0
+
+SEQUENCE OF 0 OCTET STRING plus trailing garbage
+get_sequence_of:"30007e":0x04:"":MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
+
+SEQUENCE of 1 OCTET STRING truncated after tag
+get_sequence_of:"300104":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING truncated in length #1
+get_sequence_of:"30020481":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING truncated in length #2
+get_sequence_of:"3003048201":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING truncated in content #1
+get_sequence_of:"30020401":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING truncated in content #2
+get_sequence_of:"3003040241":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING truncated in content #3
+get_sequence_of:"300404034142":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 1 OCTET STRING (0)
+get_sequence_of:"30020400":0x04:"4,0":0
+
+SEQUENCE of 1 OCTET STRING (1)
+get_sequence_of:"3003040141":0x04:"4,1":0
+
+SEQUENCE of 1 OCTET STRING (126)
+get_sequence_of:"308180047e414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141":0x04:"5,126":0
+
+SEQUENCE of 2 OCTET STRINGs, second truncated after tag
+get_sequence_of:"30050402414104":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs, second truncated in length #1
+get_sequence_of:"3006040241410481":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs, second truncated in length #2
+get_sequence_of:"300704024141048201":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs, second truncated in content #1
+get_sequence_of:"3006040241410401":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs, second truncated in content #2
+get_sequence_of:"300704024141040241":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs, second truncated in content #3
+get_sequence_of:"30080402414104034142":0x04:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+SEQUENCE of 2 OCTET STRINGs (2, 0)
+get_sequence_of:"3006040241410400":0x04:"4,2,8,0":0
+
+SEQUENCE of 2 OCTET STRINGs (2, 1)
+get_sequence_of:"300704024141040142":0x04:"4,2,8,1":0
+
+SEQUENCE of 2 OCTET STRINGs (0, 2)
+get_sequence_of:"3006040004024141":0x04:"4,0,6,2":0
+
+SEQUENCE of 2 OCTET STRINGs (1, 2)
+get_sequence_of:"300704014104024242":0x04:"4,1,7,2":0
+
+Not a SEQUENCE (not CONSTRUCTED)
+get_sequence_of:"1000":0x04:"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+Not a SEQUENCE (not SEQUENCE)
+get_sequence_of:"3100":0x04:"":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+AlgorithmIdentifier, no params
+get_alg:"300506034f4944":4:3:0:0:0:7:0
+
+AlgorithmIdentifier, no params, trailing garbage
+get_alg:"300506034f49447e":4:3:0:0:0:7:0
+
+AlgorithmIdentifier, null params
+get_alg:"300706034f49440500":4:3:0x05:9:0:9:0
+
+AlgorithmIdentifier, null params, trailing garbage
+get_alg:"300706034f494405007e":4:3:0x05:9:0:9:0
+
+AlgorithmIdentifier, OCTET STRING params
+get_alg:"300c06034f494404056162636465":4:3:0x04:9:5:14:0
+
+AlgorithmIdentifier, truncated before OID
+get_alg:"3000":4:3:0:0:0:2:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated in OID after tag
+get_alg:"300106":0:0:0:0:0:3:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated in OID after length
+get_alg:"30020603":4:3:0:0:0:4:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated inside OID content
+get_alg:"300406034f49":4:3:0:0:0:6:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated in params after tag
+get_alg:"300606034f494404":4:3:0x04:0:0:8:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated in params after length
+get_alg:"300706034f49440405":4:3:0x04:9:0:9:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+AlgorithmIdentifier, truncated inside params content
+get_alg:"300806034f4944040561":4:3:0x04:9:5:10:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+Not an AlgorithmIdentifier (not a SEQUENCE)
+get_alg:"310506034f4944":0:0:0:0:0:0:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+Not an AlgorithmIdentifier (empty SEQUENCE)
+get_alg:"3000":0:0:0:0:0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+Not an AlgorithmIdentifier (not an OID)
+get_alg:"3006050006034f4944":0:0:0:0:0:0:MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+Not an AlgorithmIdentifier (too many elements)
+get_alg:"300f06034f494406034f494406034f4944":0:0:0:0:0:0:MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
+
+Find named data: not found
+find_named_data:"414141":"424242":"434343":"444444":"7f7f7f":0:4
+
+Find named data: empty haystack
+find_named_data:"414141":"424242":"434343":"444444":"7f7f7f":4:4
+
+Find named data: first
+find_named_data:"414141":"424242":"434343":"444444":"414141":0:0
+
+Find named data: last
+find_named_data:"414141":"424242":"434343":"444444":"444444":0:3
+
+Find named data: skip suffix
+find_named_data:"41414141":"414141":"434343":"444444":"414141":0:1
+
+Find named data: skip prefix
+find_named_data:"4141":"414141":"434343":"444444":"414141":0:1
+
+Find named data: first match
+find_named_data:"414141":"414141":"434343":"444444":"414141":0:0
+
+Free named data: null pointer
+free_named_data_null:
+
+Free named data: all null
+free_named_data:0:0:0
+
+Free named data: with oid
+free_named_data:1:0:0
+
+Free named data: with val
+free_named_data:0:1:0
+
+Free named data: with next
+free_named_data:0:0:1
+
+Free named data list (empty)
+free_named_data_list:0
+
+Free named data list (1)
+free_named_data_list:1
+
+Free named data list (2)
+free_named_data_list:2
diff --git a/tests/suites/test_suite_asn1parse.function b/tests/suites/test_suite_asn1parse.function
new file mode 100644
index 0000000..defbd01
--- /dev/null
+++ b/tests/suites/test_suite_asn1parse.function
@@ -0,0 +1,642 @@
+/* BEGIN_HEADER */
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/asn1.h"
+#if defined(MBEDTLS_ASN1_WRITE_C)
+#include "mbedtls/asn1write.h"
+#endif
+
+#define ERR_PARSE_INCONSISTENCY INT_MAX
+
+static int nested_parse( unsigned char **const p,
+                         const unsigned char *const end )
+{
+    int ret;
+    size_t len = 0;
+    size_t len2 = 0;
+    unsigned char *const start = *p;
+    unsigned char *content_start;
+    unsigned char tag;
+
+    /* First get the length, skipping over the tag. */
+    content_start = start + 1;
+    ret = mbedtls_asn1_get_len( &content_start, end, &len );
+    TEST_ASSERT( content_start <= end );
+    if( ret != 0 )
+        return( ret );
+
+    /* Since we have a valid element start (tag and length), retrieve and
+     * check the tag. */
+    tag = start[0];
+    TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len2, tag ^ 1 ),
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+    *p = start;
+    TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len2, tag ), 0 );
+    TEST_EQUAL( len, len2 );
+    TEST_ASSERT( *p == content_start );
+    *p = content_start;
+
+    switch( tag & 0x1f )
+    {
+        case MBEDTLS_ASN1_BOOLEAN:
+        {
+            int val = -257;
+            *p = start;
+            ret = mbedtls_asn1_get_bool( p, end, &val );
+            if( ret == 0 )
+                TEST_ASSERT( val == 0 || val == 1 );
+            break;
+        }
+
+        case MBEDTLS_ASN1_INTEGER:
+        {
+#if defined(MBEDTLS_BIGNUM_C)
+            mbedtls_mpi mpi;
+            mbedtls_mpi_init( &mpi );
+            *p = start;
+            ret = mbedtls_asn1_get_mpi( p, end, &mpi );
+            mbedtls_mpi_free( &mpi );
+#else
+            *p = start + 1;
+            ret = mbedtls_asn1_get_len( p, end, &len );
+            *p += len;
+#endif
+            /* If we're sure that the number fits in an int, also
+             * call mbedtls_asn1_get_int(). */
+            if( ret == 0 && len < sizeof( int ) )
+            {
+                int val = -257;
+                unsigned char *q = start;
+                ret = mbedtls_asn1_get_int( &q, end, &val );
+                TEST_ASSERT( *p == q );
+            }
+            break;
+        }
+
+        case MBEDTLS_ASN1_BIT_STRING:
+        {
+            mbedtls_asn1_bitstring bs;
+            *p = start;
+            ret = mbedtls_asn1_get_bitstring( p, end, &bs );
+            break;
+        }
+
+        case MBEDTLS_ASN1_SEQUENCE:
+        {
+            while( *p <= end && *p < content_start + len && ret == 0 )
+                ret = nested_parse( p, content_start + len );
+            break;
+        }
+
+        case MBEDTLS_ASN1_OCTET_STRING:
+        case MBEDTLS_ASN1_NULL:
+        case MBEDTLS_ASN1_OID:
+        case MBEDTLS_ASN1_UTF8_STRING:
+        case MBEDTLS_ASN1_SET:
+        case MBEDTLS_ASN1_PRINTABLE_STRING:
+        case MBEDTLS_ASN1_T61_STRING:
+        case MBEDTLS_ASN1_IA5_STRING:
+        case MBEDTLS_ASN1_UTC_TIME:
+        case MBEDTLS_ASN1_GENERALIZED_TIME:
+        case MBEDTLS_ASN1_UNIVERSAL_STRING:
+        case MBEDTLS_ASN1_BMP_STRING:
+        default:
+            /* No further testing implemented for this tag. */
+            *p += len;
+            return( 0 );
+    }
+
+    TEST_ASSERT( *p <= end );
+    return( ret );
+
+exit:
+    return( ERR_PARSE_INCONSISTENCY );
+}
+
+int get_len_step( const data_t *input, size_t buffer_size,
+                  size_t actual_length )
+{
+    unsigned char *buf = NULL;
+    unsigned char *p = NULL;
+    size_t parsed_length;
+    int ret;
+
+    test_set_step( buffer_size );
+    /* Allocate a new buffer of exactly the length to parse each time.
+     * This gives memory sanitizers a chance to catch buffer overreads. */
+    if( buffer_size == 0 )
+    {
+        ASSERT_ALLOC( buf, 1 );
+        p = buf + 1;
+    }
+    else
+    {
+        ASSERT_ALLOC_WEAK( buf, buffer_size );
+        if( buffer_size > input->len )
+        {
+            memcpy( buf, input->x, input->len );
+            memset( buf + input->len, 'A', buffer_size - input->len );
+        }
+        else
+        {
+            memcpy( buf, input->x, buffer_size );
+        }
+        p = buf;
+    }
+
+    ret = mbedtls_asn1_get_len( &p, buf + buffer_size, &parsed_length );
+
+    if( buffer_size >= input->len + actual_length )
+    {
+        TEST_EQUAL( ret, 0 );
+        TEST_ASSERT( p == buf + input->len );
+        TEST_EQUAL( parsed_length, actual_length );
+    }
+    else
+    {
+        TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    }
+    mbedtls_free( buf );
+    return( 1 );
+
+exit:
+    mbedtls_free( buf );
+    return( 0 );
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_ASN1_PARSE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void parse_prefixes( const data_t *input,
+                     int actual_length_arg,
+                     int last_result )
+{
+    size_t actual_length = actual_length_arg;
+    unsigned char *buf = NULL;
+    unsigned char *p = NULL;
+    size_t buffer_size;
+    int ret;
+
+    for( buffer_size = 1; buffer_size <= input->len; buffer_size++ )
+    {
+        test_set_step( buffer_size );
+        /* Allocate a new buffer of exactly the length to parse each time.
+         * This gives memory sanitizers a chance to catch buffer overreads. */
+        ASSERT_ALLOC( buf, buffer_size );
+        memcpy( buf, input->x, buffer_size );
+        p = buf;
+        ret = nested_parse( &p, buf + buffer_size );
+        if( ret == ERR_PARSE_INCONSISTENCY )
+            goto exit;
+        if( actual_length > 0 && buffer_size >= actual_length )
+        {
+            TEST_EQUAL( ret, last_result );
+            if( ret == 0 )
+                TEST_ASSERT( p == buf + actual_length );
+        }
+        else
+        {
+            TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        }
+        mbedtls_free( buf );
+        buf = NULL;
+    }
+
+exit:
+    mbedtls_free( buf );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_len( const data_t *input, int actual_length_arg )
+{
+    size_t actual_length = actual_length_arg;
+    size_t buffer_size;
+
+    for( buffer_size = 1; buffer_size <= input->len + 1; buffer_size++ )
+    {
+        if( ! get_len_step( input, buffer_size, actual_length ) )
+            goto exit;
+    }
+    if( ! get_len_step( input, input->len + actual_length - 1, actual_length ) )
+        goto exit;
+    if( ! get_len_step( input, input->len + actual_length, actual_length ) )
+        goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_boolean( const data_t *input,
+                  int expected_value, int expected_result )
+{
+    unsigned char *p = input->x;
+    int val;
+    int ret;
+    ret = mbedtls_asn1_get_bool( &p, input->x + input->len, &val );
+    TEST_EQUAL( ret, expected_result );
+    if( expected_result == 0 )
+    {
+        TEST_EQUAL( val, expected_value );
+        TEST_ASSERT( p == input->x + input->len );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void empty_integer( const data_t *input )
+{
+    unsigned char *p;
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi actual_mpi;
+#endif
+    int val;
+
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_init( & actual_mpi );
+#endif
+
+    /* An INTEGER with no content is not valid. */
+    p = input->x;
+    TEST_EQUAL( mbedtls_asn1_get_int( &p, input->x + input->len, &val ),
+                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+#if defined(MBEDTLS_BIGNUM_C)
+    /* INTEGERs are sometimes abused as bitstrings, so the library accepts
+     * an INTEGER with empty content and gives it the value 0. */
+    p = input->x;
+    TEST_EQUAL( mbedtls_asn1_get_mpi( &p, input->x + input->len, &actual_mpi ),
+                0 );
+    TEST_EQUAL( mbedtls_mpi_cmp_int( &actual_mpi, 0 ), 0 );
+#endif
+
+exit:
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_free( &actual_mpi );
+#endif
+    /*empty cleanup in some configurations*/ ;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_integer( const data_t *input,
+                  const char *expected_hex, int expected_result )
+{
+    unsigned char *p;
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi expected_mpi;
+    mbedtls_mpi actual_mpi;
+    mbedtls_mpi complement;
+    int expected_result_for_mpi = expected_result;
+#endif
+    long expected_value;
+    int expected_result_for_int = expected_result;
+    int val;
+    int ret;
+
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_init( &expected_mpi );
+    mbedtls_mpi_init( &actual_mpi );
+    mbedtls_mpi_init( &complement );
+#endif
+
+    errno = 0;
+    expected_value = strtol( expected_hex, NULL, 16 );
+    if( expected_result == 0 &&
+        ( errno == ERANGE
+#if LONG_MAX > INT_MAX
+          || expected_value > INT_MAX || expected_value < INT_MIN
+#endif
+            ) )
+    {
+        /* The library returns the dubious error code INVALID_LENGTH
+         * for integers that are out of range. */
+        expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+    if( expected_result == 0 && expected_value < 0 )
+    {
+        /* The library does not support negative INTEGERs and
+         * returns the dubious error code INVALID_LENGTH.
+         * Test that we preserve the historical behavior. If we
+         * decide to change the behavior, we'll also change this test. */
+        expected_result_for_int = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+
+    p = input->x;
+    ret = mbedtls_asn1_get_int( &p, input->x + input->len, &val );
+    TEST_EQUAL( ret, expected_result_for_int );
+    if( ret == 0 )
+    {
+        TEST_EQUAL( val, expected_value );
+        TEST_ASSERT( p == input->x + input->len );
+    }
+
+#if defined(MBEDTLS_BIGNUM_C)
+    ret = mbedtls_mpi_read_string( &expected_mpi, 16, expected_hex );
+    TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if( ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
+    {
+        /* The data overflows the maximum MPI size. */
+        expected_result_for_mpi = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+    p = input->x;
+    ret = mbedtls_asn1_get_mpi( &p, input->x + input->len, &actual_mpi );
+    TEST_EQUAL( ret, expected_result_for_mpi );
+    if( ret == 0 )
+    {
+        if( expected_value >= 0 )
+        {
+            TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual_mpi,
+                                              &expected_mpi ) == 0 );
+        }
+        else
+        {
+            /* The library ignores the sign bit in ASN.1 INTEGERs
+             * (which makes sense insofar as INTEGERs are sometimes
+             * abused as bit strings), so the result of parsing them
+             * is a positive integer such that expected_mpi +
+             * actual_mpi = 2^n where n is the length of the content
+             * of the INTEGER. (Leading ff octets don't matter for the
+             * expected value, but they matter for the actual value.)
+             * Test that we don't change from this behavior. If we
+             * decide to fix the library to change the behavior on
+             * negative INTEGERs, we'll fix this test code. */
+            unsigned char *q = input->x + 1;
+            size_t len;
+            TEST_ASSERT( mbedtls_asn1_get_len( &q, input->x + input->len,
+                                               &len ) == 0 );
+            TEST_ASSERT( mbedtls_mpi_lset( &complement, 1 ) == 0 );
+            TEST_ASSERT( mbedtls_mpi_shift_l( &complement, len * 8 ) == 0 );
+            TEST_ASSERT( mbedtls_mpi_add_mpi( &complement, &complement,
+                                              &expected_mpi ) == 0 );
+            TEST_ASSERT( mbedtls_mpi_cmp_mpi( &complement,
+                                              &actual_mpi ) == 0 );
+        }
+        TEST_ASSERT( p == input->x + input->len );
+    }
+#endif
+
+exit:
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_free( &expected_mpi );
+    mbedtls_mpi_free( &actual_mpi );
+    mbedtls_mpi_free( &complement );
+#endif
+    /*empty cleanup in some configurations*/ ;
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
+void get_mpi_too_large( )
+{
+    unsigned char *buf = NULL;
+    unsigned char *p;
+    mbedtls_mpi actual_mpi;
+    size_t too_many_octets =
+        MBEDTLS_MPI_MAX_LIMBS * sizeof(mbedtls_mpi_uint) + 1;
+    size_t size = too_many_octets + 6;
+
+    mbedtls_mpi_init( &actual_mpi );
+
+    ASSERT_ALLOC( buf, size );
+    buf[0] = 0x02; /* tag: INTEGER */
+    buf[1] = 0x84; /* 4-octet length */
+    buf[2] = ( too_many_octets >> 24 ) & 0xff;
+    buf[3] = ( too_many_octets >> 16 ) & 0xff;
+    buf[4] = ( too_many_octets >> 8 ) & 0xff;
+    buf[5] = too_many_octets & 0xff;
+    buf[6] = 0x01; /* most significant octet */
+
+    p = buf;
+    TEST_EQUAL( mbedtls_asn1_get_mpi( &p, buf + size, &actual_mpi ),
+                MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+exit:
+    mbedtls_mpi_free( &actual_mpi );
+    mbedtls_free( buf );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_bitstring( const data_t *input,
+                    int expected_length, int expected_unused_bits,
+                    int expected_result, int expected_result_null )
+{
+    mbedtls_asn1_bitstring bs = { 0xdead, 0x21, NULL };
+    unsigned char *p = input->x;
+
+    TEST_EQUAL( mbedtls_asn1_get_bitstring( &p, input->x + input->len, &bs ),
+                expected_result );
+    if( expected_result == 0 )
+    {
+        TEST_EQUAL( bs.len, (size_t) expected_length );
+        TEST_EQUAL( bs.unused_bits, expected_unused_bits );
+        TEST_ASSERT( bs.p != NULL );
+        TEST_EQUAL( bs.p - input->x + bs.len, input->len );
+        TEST_ASSERT( p == input->x + input->len );
+    }
+
+    p = input->x;
+    TEST_EQUAL( mbedtls_asn1_get_bitstring_null( &p, input->x + input->len,
+                                                 &bs.len ),
+                expected_result_null );
+    if( expected_result_null == 0 )
+    {
+        TEST_EQUAL( bs.len, (size_t) expected_length );
+        if( expected_result == 0 )
+            TEST_ASSERT( p == input->x + input->len - bs.len );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_sequence_of( const data_t *input, int tag,
+                      const char *description,
+                      int expected_result )
+{
+    mbedtls_asn1_sequence head = { { 0, 0, NULL }, NULL };
+    mbedtls_asn1_sequence *cur, *next;
+    unsigned char *p = input->x;
+    const char *rest = description;
+    unsigned long n;
+
+    TEST_EQUAL( mbedtls_asn1_get_sequence_of( &p, input->x + input->len,
+                                              &head, tag ),
+                expected_result );
+    if( expected_result == 0 )
+    {
+        TEST_ASSERT( p == input->x + input->len );
+
+        if( ! *rest )
+        {
+            TEST_EQUAL( head.buf.tag, 0 );
+            TEST_ASSERT( head.buf.p == NULL );
+            TEST_EQUAL( head.buf.len, 0 );
+            TEST_ASSERT( head.next == NULL );
+        }
+        else
+        {
+            cur = &head;
+            while( *rest )
+            {
+                ++test_info.step;
+                TEST_ASSERT( cur != NULL );
+                TEST_EQUAL( cur->buf.tag, tag );
+                n = strtoul( rest, (char **) &rest, 0 );
+                TEST_EQUAL( n, (size_t)( cur->buf.p - input->x ) );
+                ++rest;
+                n = strtoul( rest, (char **) &rest, 0 );
+                TEST_EQUAL( n, cur->buf.len );
+                if( *rest )
+                    ++rest;
+                cur = cur->next;
+            }
+            TEST_ASSERT( cur == NULL );
+        }
+    }
+
+exit:
+    cur = head.next;
+    while( cur != NULL )
+    {
+        next = cur->next;
+        mbedtls_free( cur );
+        cur = next;
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void get_alg( const data_t *input,
+              int oid_offset, int oid_length,
+              int params_tag, int params_offset, int params_length,
+              int total_length,
+              int expected_result )
+{
+    mbedtls_asn1_buf oid = { -1, 0, NULL };
+    mbedtls_asn1_buf params = { -1, 0, NULL };
+    unsigned char *p = input->x;
+    int ret;
+
+    TEST_EQUAL( mbedtls_asn1_get_alg( &p, input->x + input->len,
+                                      &oid, &params ),
+                expected_result );
+    if( expected_result == 0 )
+    {
+        TEST_EQUAL( oid.tag, MBEDTLS_ASN1_OID );
+        TEST_EQUAL( oid.p - input->x, oid_offset );
+        TEST_EQUAL( oid.len, (size_t) oid_length );
+        TEST_EQUAL( params.tag, params_tag );
+        if( params_offset != 0 )
+            TEST_EQUAL( params.p - input->x, params_offset );
+        else
+            TEST_ASSERT( params.p == NULL );
+        TEST_EQUAL( params.len, (size_t) params_length );
+        TEST_EQUAL( p - input->x, total_length );
+    }
+
+    ret = mbedtls_asn1_get_alg_null( &p, input->x + input->len, &oid );
+    if( expected_result == 0 && params_offset == 0 )
+    {
+        TEST_EQUAL( oid.tag, MBEDTLS_ASN1_OID );
+        TEST_EQUAL( oid.p - input->x, oid_offset );
+        TEST_EQUAL( oid.len, (size_t) oid_length );
+        TEST_EQUAL( p - input->x, total_length );
+    }
+    else
+        TEST_ASSERT( ret != 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void find_named_data( data_t *oid0, data_t *oid1, data_t *oid2, data_t *oid3,
+                      data_t *needle, int from, int position )
+{
+    mbedtls_asn1_named_data nd[] ={
+        { {0x06, oid0->len, oid0->x}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, oid1->len, oid1->x}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, oid2->len, oid2->x}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, oid3->len, oid3->x}, {0, 0, NULL}, NULL, 0 },
+    };
+    mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1];
+    size_t i;
+    mbedtls_asn1_named_data *found;
+
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+        pointers[i] = &nd[i];
+    pointers[ARRAY_LENGTH( nd )] = NULL;
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+        nd[i].next = pointers[i+1];
+
+    found = mbedtls_asn1_find_named_data( pointers[from],
+                                          (const char *) needle->x,
+                                          needle->len );
+    TEST_ASSERT( found == pointers[position] );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void free_named_data_null( )
+{
+    mbedtls_asn1_free_named_data( NULL );
+    goto exit; /* Silence unused label warning */
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void free_named_data( int with_oid, int with_val, int with_next )
+{
+    mbedtls_asn1_named_data next =
+        { {0x06, 0, NULL}, {0, 0xcafe, NULL}, NULL, 0 };
+    mbedtls_asn1_named_data head =
+        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 };
+
+    if( with_oid )
+        ASSERT_ALLOC( head.oid.p, 1 );
+    if( with_val )
+        ASSERT_ALLOC( head.val.p, 1 );
+    if( with_next )
+        head.next = &next;
+
+    mbedtls_asn1_free_named_data( &head );
+    TEST_ASSERT( head.oid.p == NULL );
+    TEST_ASSERT( head.val.p == NULL );
+    TEST_ASSERT( head.next == NULL );
+    TEST_ASSERT( next.val.len == 0xcafe );
+
+exit:
+    mbedtls_free( head.oid.p );
+    mbedtls_free( head.val.p );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void free_named_data_list( int length )
+{
+    mbedtls_asn1_named_data *head = NULL;
+    int i;
+
+    for( i = 0; i < length; i++ )
+    {
+        mbedtls_asn1_named_data *new = NULL;
+        ASSERT_ALLOC( new, sizeof( mbedtls_asn1_named_data ) );
+        new->next = head;
+        head = new;
+    }
+
+    mbedtls_asn1_free_named_data_list( &head );
+    TEST_ASSERT( head == NULL );
+    /* Most of the point of the test is that it doesn't leak memory.
+     * So this test is only really useful under a memory leak detection
+     * framework. */
+exit:
+    mbedtls_asn1_free_named_data_list( &head );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_asn1write.data b/tests/suites/test_suite_asn1write.data
index 9982d03..fd589fb 100644
--- a/tests/suites/test_suite_asn1write.data
+++ b/tests/suites/test_suite_asn1write.data
@@ -1,53 +1,182 @@
-ASN.1 Write Octet String #0 (Empty string)
-mbedtls_asn1_write_octet_string:"":"0400":2:2
+ASN.1 Write NULL
+mbedtls_asn1_write_null:"0500"
 
-ASN.1 Write Octet String #1 (Large buffer)
-mbedtls_asn1_write_octet_string:"AABBCC":"0403AABBCC":10:5
+ASN.1 Write BOOLEAN FALSE
+mbedtls_asn1_write_bool:0:"010100"
 
-ASN.1 Write Octet String #2 (Buffer just fits)
-mbedtls_asn1_write_octet_string:"AABBCC":"0403AABBCC":5:5
+ASN.1 Write BOOLEAN TRUE
+mbedtls_asn1_write_bool:1:"0101ff"
 
-ASN.1 Write Octet String #3 (Buffer too small for tag)
-mbedtls_asn1_write_octet_string:"AABBCC":"0403AABBCC":4:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 0
+mbedtls_asn1_write_int:0:"020100"
 
-ASN.1 Write Octet String #4 (Buffer too small for len)
-mbedtls_asn1_write_octet_string:"AABBCC":"0403AABBCC":3:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 1
+mbedtls_asn1_write_int:1:"020101"
 
-ASN.1 Write Octet String #5 (Buffer too small for string)
-mbedtls_asn1_write_octet_string:"AABBCC":"0403AABBCC":2:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 127
+mbedtls_asn1_write_int:0x7f:"02017f"
 
-ASN.1 Write Octet String #6 (l = 128, large buffer)
-mbedtls_asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"048180000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":140:131
+ASN.1 Write int 128
+mbedtls_asn1_write_int:0x80:"02020080"
 
-ASN.1 Write Octet String #7 (l = 128, buffer just fits)
-mbedtls_asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"048180000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":131:131
+ASN.1 Write int 255
+mbedtls_asn1_write_int:0xff:"020200ff"
 
-ASN.1 Write Octet String #8 (l = 128, buffer too small for tag)
-mbedtls_asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":130:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 256
+mbedtls_asn1_write_int:0x100:"02020100"
 
-ASN.1 Write Octet String #9 (l = 128, buffer too small for len)
-mbedtls_asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":129:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 32767
+mbedtls_asn1_write_int:0x7fff:"02027fff"
 
-ASN.1 Write Octet String #9 (l = 128, buffer too small for string)
-mbedtls_asn1_write_octet_string:"000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F":"":127:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 32768
+mbedtls_asn1_write_int:0x8000:"0203008000"
 
-ASN.1 Write IA5 String #0 (Empty string)
-mbedtls_asn1_write_ia5_string:"":"1600":2:2
+ASN.1 Write int 65535
+mbedtls_asn1_write_int:0xffff:"020300ffff"
 
-ASN.1 Write IA5 String #1 (Large buffer)
-mbedtls_asn1_write_ia5_string:"ABC":"1603414243":10:5
+ASN.1 Write int 65536
+mbedtls_asn1_write_int:0x10000:"0203010000"
 
-ASN.1 Write IA5 String #2 (Buffer just fits)
-mbedtls_asn1_write_ia5_string:"ABC":"1603414243":5:5
+ASN.1 Write int 8388607
+mbedtls_asn1_write_int:0x7fffff:"02037fffff"
 
-ASN.1 Write IA5 String #3 (Buffer too small for tag)
-mbedtls_asn1_write_ia5_string:"ABC":"":4:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 8388608
+mbedtls_asn1_write_int:0x800000:"020400800000"
 
-ASN.1 Write IA5 String #4 (Buffer too small for len)
-mbedtls_asn1_write_ia5_string:"ABC":"":3:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 0x12345678
+mbedtls_asn1_write_int:0x12345678:"020412345678"
 
-ASN.1 Write IA5 String #5 (Buffer too small for string)
-mbedtls_asn1_write_ia5_string:"ABC":"":2:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
+ASN.1 Write int 2147483647
+mbedtls_asn1_write_int:0x7fffffff:"02047fffffff"
+
+#ASN.1 Write mpi 0
+#mbedtls_asn1_write_mpi:"00":"020100"
+
+ASN.1 Write mpi 1
+mbedtls_asn1_write_mpi:"01":"020101"
+
+ASN.1 Write mpi 0x7f
+mbedtls_asn1_write_mpi:"7f":"02017f"
+
+#ASN.1 Write mpi 0x80
+#mbedtls_asn1_write_mpi:"7f":"02020080"
+
+#ASN.1 Write mpi 0xff
+#mbedtls_asn1_write_mpi:"7f":"020200ff"
+
+ASN.1 Write mpi 0x100
+mbedtls_asn1_write_mpi:"0100":"02020100"
+
+ASN.1 Write mpi, 127*8-1 bits
+mbedtls_asn1_write_mpi:"7f7b16e05c1537de7c41cef1a0985d6a3ced98aec28e091874cbad6b5e40a5c956258f18861c28bed8ba808259339ee34b2e509c4080149474d5d5b86093f90c475a6443fc87e1a293d4151be625d652f1c32a00a018bba10c8a2ae5b2b0ee4be64e053dce9d07ec7919526c9dfcf2ec9fc3db485caa8e5a68a2cd0a427de8":"027f7f7b16e05c1537de7c41cef1a0985d6a3ced98aec28e091874cbad6b5e40a5c956258f18861c28bed8ba808259339ee34b2e509c4080149474d5d5b86093f90c475a6443fc87e1a293d4151be625d652f1c32a00a018bba10c8a2ae5b2b0ee4be64e053dce9d07ec7919526c9dfcf2ec9fc3db485caa8e5a68a2cd0a427de8"
+
+#ASN.1 Write mpi, 127*8 bits
+#mbedtls_asn1_write_mpi:"e77b16e05c1537de7c41cef1a0985d6a3ced98aec28e091874cbad6b5e40a5c956258f18861c28bed8ba808259339ee34b2e509c4080149474d5d5b86093f90c475a6443fc87e1a293d4151be625d652f1c32a00a018bba10c8a2ae5b2b0ee4be64e053dce9d07ec7919526c9dfcf2ec9fc3db485caa8e5a68a2cd0a427de8":"028180e77b16e05c1537de7c41cef1a0985d6a3ced98aec28e091874cbad6b5e40a5c956258f18861c28bed8ba808259339ee34b2e509c4080149474d5d5b86093f90c475a6443fc87e1a293d4151be625d652f1c32a00a018bba10c8a2ae5b2b0ee4be64e053dce9d07ec7919526c9dfcf2ec9fc3db485caa8e5a68a2cd0a427de8"
+
+ASN.1 Write mpi, 127*8+1 bits
+mbedtls_asn1_write_mpi:"108446d68934cc1af23c4cd909884d4bd737a1890e12f5ef8bf3d807d72feffa63c0bf2633345f8b8418d144617c871a7a0277ac0150eed4b3db7f9dff21114cd0d7f282400f03c931cb00c367550e374a1ed3762a1801ca714cfc8d5aac69707ca81e0661400ed0014d97cba48f94d835dd681fc3053c51958afbf7583cf49c":"028180108446d68934cc1af23c4cd909884d4bd737a1890e12f5ef8bf3d807d72feffa63c0bf2633345f8b8418d144617c871a7a0277ac0150eed4b3db7f9dff21114cd0d7f282400f03c931cb00c367550e374a1ed3762a1801ca714cfc8d5aac69707ca81e0661400ed0014d97cba48f94d835dd681fc3053c51958afbf7583cf49c"
+
+ASN.1 Write mpi, 255*8-1 bits
+mbedtls_asn1_write_mpi:"7bd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c":"0281ff7bd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c"
+
+#ASN.1 Write mpi, 255*8 bits
+#mbedtls_asn1_write_mpi:"fbd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c":"0282010000fbd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c"
+
+ASN.1 Write mpi, 256*8-1 bits
+mbedtls_asn1_write_mpi:"7bd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c89":"028201007bd1913fcfb652896209ad3e62f5d04a8dfc71eb1698543c52200bd7bbf3c11dd9ff57c299a2f4da172b3d5bd7e29affddf8859be7d50a45537a0df15b17af603d18803fd17134847cba78d83e64bf9fee58364d6124add0541da7bad331cd35fb48186a74bc502ddb967602401c0db02b19e5d38f09e8618fa7f6a1a3f738629baffdc63d9d70d396007d943fd64ae696e5b7e88f2c6d6ec322b461dbddd36efa91d990343b66419cf4832a22dc9ad13021185a1bf007989a50ba3bfd1152b8db899482d3ed498d1b9fae243a3cdae9530d8b29fdb684f70cdc0c9b8527265312603b405e67d59d4b1d654ddc3b7fd5515acb32440dc80903c8474a2c136c89"
+
+ASN.1 Write OCTET STRING: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"":"0400"
+
+ASN.1 Write OCTET STRING: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"41":"040141"
+
+ASN.1 Write OCTET STRING: length=2
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"4142":"04024142"
+
+ASN.1 Write OCTET STRING: length=127
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"99a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"047f99a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write OCTET STRING: length=128
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"0199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"0481800199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write OCTET STRING: length=255
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"633ed2cb0a2915dc4438a4c063017eb336cd9571d2a0585522c5073ca22a30ca7b8c9bd167d89ba1827bc6fb5d6ef6dcc52ee6eecc47e84ee0dd18fa3ebbdb6edfc679f037160d48d46a0d7e571335b24a28c8fd29b7f4a93d013b74e522bc1f5f605096bb99d438814b77b54d6dde608417b0a0ce9a8cb507fbeb95e9926b4bb6eec725599493d4b156ef3a5fd701426456029111c20f1d03c5d8999d2c042277ef91c5114a6c06218c1ba28d41ef08e4870d0cef260cba9de16d7d11ed5889b88fb93073746ebb158a4246cdb8a4ce403a5d1d598a0d11548f22070f833c1344d15e7a1445c133d19b8295b7c071bf2227178938031249d22d21c6f8e53d":"0481ff633ed2cb0a2915dc4438a4c063017eb336cd9571d2a0585522c5073ca22a30ca7b8c9bd167d89ba1827bc6fb5d6ef6dcc52ee6eecc47e84ee0dd18fa3ebbdb6edfc679f037160d48d46a0d7e571335b24a28c8fd29b7f4a93d013b74e522bc1f5f605096bb99d438814b77b54d6dde608417b0a0ce9a8cb507fbeb95e9926b4bb6eec725599493d4b156ef3a5fd701426456029111c20f1d03c5d8999d2c042277ef91c5114a6c06218c1ba28d41ef08e4870d0cef260cba9de16d7d11ed5889b88fb93073746ebb158a4246cdb8a4ce403a5d1d598a0d11548f22070f833c1344d15e7a1445c133d19b8295b7c071bf2227178938031249d22d21c6f8e53d"
+
+ASN.1 Write OCTET STRING: length=256
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OCTET_STRING:"5a633ed2cb0a2915dc4438a4c063017eb336cd9571d2a0585522c5073ca22a30ca7b8c9bd167d89ba1827bc6fb5d6ef6dcc52ee6eecc47e84ee0dd18fa3ebbdb6edfc679f037160d48d46a0d7e571335b24a28c8fd29b7f4a93d013b74e522bc1f5f605096bb99d438814b77b54d6dde608417b0a0ce9a8cb507fbeb95e9926b4bb6eec725599493d4b156ef3a5fd701426456029111c20f1d03c5d8999d2c042277ef91c5114a6c06218c1ba28d41ef08e4870d0cef260cba9de16d7d11ed5889b88fb93073746ebb158a4246cdb8a4ce403a5d1d598a0d11548f22070f833c1344d15e7a1445c133d19b8295b7c071bf2227178938031249d22d21c6f8e53d":"048201005a633ed2cb0a2915dc4438a4c063017eb336cd9571d2a0585522c5073ca22a30ca7b8c9bd167d89ba1827bc6fb5d6ef6dcc52ee6eecc47e84ee0dd18fa3ebbdb6edfc679f037160d48d46a0d7e571335b24a28c8fd29b7f4a93d013b74e522bc1f5f605096bb99d438814b77b54d6dde608417b0a0ce9a8cb507fbeb95e9926b4bb6eec725599493d4b156ef3a5fd701426456029111c20f1d03c5d8999d2c042277ef91c5114a6c06218c1ba28d41ef08e4870d0cef260cba9de16d7d11ed5889b88fb93073746ebb158a4246cdb8a4ce403a5d1d598a0d11548f22070f833c1344d15e7a1445c133d19b8295b7c071bf2227178938031249d22d21c6f8e53d"
+
+ASN.1 Write UTF8 STRING: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_UTF8_STRING:"":"0c00"
+
+ASN.1 Write UTF8 STRING: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_UTF8_STRING:"41":"0c0141"
+
+ASN.1 Write UTF8 STRING: length=128
+mbedtls_asn1_write_string:MBEDTLS_ASN1_UTF8_STRING:"0199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"0c81800199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write PRINTABLE STRING: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_PRINTABLE_STRING:"":"1300"
+
+ASN.1 Write PRINTABLE STRING: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_PRINTABLE_STRING:"41":"130141"
+
+ASN.1 Write PRINTABLE STRING: length=128
+mbedtls_asn1_write_string:MBEDTLS_ASN1_PRINTABLE_STRING:"0199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"1381800199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write IA5 STRING: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING:"":"1600"
+
+ASN.1 Write IA5 STRING: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING:"41":"160141"
+
+ASN.1 Write IA5 STRING: length=128
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING:"0199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"1681800199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write tagged string: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING | MBEDTLS_ASN1_CONTEXT_SPECIFIC:"":"9600"
+
+ASN.1 Write tagged string: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING | MBEDTLS_ASN1_CONTEXT_SPECIFIC:"41":"960141"
+
+ASN.1 Write tagged string: length=128
+mbedtls_asn1_write_string:MBEDTLS_ASN1_IA5_STRING | MBEDTLS_ASN1_CONTEXT_SPECIFIC:"0199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38":"9681800199a66790856f7199641f55cadabb660aaed6aa0d9ef8cef4417118c6e8c6e15becbaa21c63faf48726e92357a38b3079a0b9d60be7457ec6552f900dd032577167c91e829927343c3a769b362db4de0ad2ffb8f13cc2eeca9e52dc557118baa88b857477595622bc301a1ae2150030d652c4a482cf88d0ded85d6731ff2d38"
+
+ASN.1 Write OID: length=0
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OID:"":"0600"
+
+ASN.1 Write OID: length=1
+mbedtls_asn1_write_string:MBEDTLS_ASN1_OID:"41":"060141"
+
+ASN.1 Write AlgorithmIdentifier, null parameters
+mbedtls_asn1_write_algorithm_identifier:"4f4944":8:"300d06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, parameters (8 bytes)
+mbedtls_asn1_write_algorithm_identifier:"4f4944":8:"300d06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0x7f
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0x7a:"307f06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0x80
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0x7b:"30818006034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0xff
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfa:"3081ff06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0x100
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfb:"3082010006034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0xffff
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfffa:"3082ffff06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0x10000
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfffb:"308301000006034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0xffffff
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfffffa:"3083ffffff06034f4944"
+
+ASN.1 Write AlgorithmIdentifier, total length=0x1000000
+mbedtls_asn1_write_algorithm_identifier:"4f4944":0xfffffb:"30840100000006034f4944"
 
 ASN.1 Write / Read Length #0 (Len = 0, short form)
 mbedtls_asn1_write_len:0:"00":1:1
@@ -92,73 +221,121 @@
 mbedtls_asn1_write_len:16909060:"8401020304":4:MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
 
 ASN.1 Write Named Bitstring / Unused bits #0
-test_asn1_write_bitstrings:"FF":8:"030200FF":4:1
+test_asn1_write_bitstrings:"FF":8:"030200FF":1
 
 ASN.1 Write Named Bitstring / Unused bits #1
-test_asn1_write_bitstrings:"FE":8:"030201FE":4:1
+test_asn1_write_bitstrings:"FE":8:"030201FE":1
 
 ASN.1 Write Named Bitstring / Unused bits #2
-test_asn1_write_bitstrings:"FC":7:"030202FC":4:1
+test_asn1_write_bitstrings:"FC":7:"030202FC":1
 
 ASN.1 Write Named Bitstring / Unused bits #3
-test_asn1_write_bitstrings:"F8":8:"030203F8":4:1
+test_asn1_write_bitstrings:"F8":8:"030203F8":1
 
 ASN.1 Write Named Bitstring / Unused bits #4
-test_asn1_write_bitstrings:"F0":6:"030204F0":4:1
+test_asn1_write_bitstrings:"F0":6:"030204F0":1
 
 ASN.1 Write Named Bitstring / Unused bits #5
-test_asn1_write_bitstrings:"E0":6:"030205E0":4:1
+test_asn1_write_bitstrings:"E0":6:"030205E0":1
 
 ASN.1 Write Named Bitstring / Unused bits #6
-test_asn1_write_bitstrings:"C0":8:"030206C0":4:1
+test_asn1_write_bitstrings:"C0":8:"030206C0":1
 
 ASN.1 Write Named Bitstring / Unused bits #7
-test_asn1_write_bitstrings:"80":8:"03020780":4:1
+test_asn1_write_bitstrings:"80":8:"03020780":1
 
 ASN.1 Write Named Bitstring / Empty bitstring
-test_asn1_write_bitstrings:"00":7:"030100":3:1
+test_asn1_write_bitstrings:"00":7:"030100":1
 
 ASN.1 Write Named Bitstring / Empty bitstring (bits = 16)
-test_asn1_write_bitstrings:"0000":16:"030100":3:1
+test_asn1_write_bitstrings:"0000":16:"030100":1
 
 ASN.1 Write Named Bitstring / Empty bitstring (bits = 24)
-test_asn1_write_bitstrings:"FFFFFF":0:"030100":3:1
+test_asn1_write_bitstrings:"FFFFFF":0:"030100":1
 
 ASN.1 Write Named Bitstring / 15 trailing bits all unset
-test_asn1_write_bitstrings:"F88000":24:"030307F880":5:1
+test_asn1_write_bitstrings:"F88000":24:"030307F880":1
 
 ASN.1 Write Named Bitstring / 15 trailing bits all set
-test_asn1_write_bitstrings:"F8FFFF":9:"030307F880":5:1
+test_asn1_write_bitstrings:"F8FFFF":9:"030307F880":1
 
 ASN.1 Write Bitstring / Unused bits #0
-test_asn1_write_bitstrings:"FF":8:"030200FF":4:0
+test_asn1_write_bitstrings:"FF":8:"030200FF":0
 
 ASN.1 Write Bitstring / Unused bits #1
-test_asn1_write_bitstrings:"FF":7:"030201FE":4:0
+test_asn1_write_bitstrings:"FF":7:"030201FE":0
 
 ASN.1 Write Bitstring / Unused bits #2
-test_asn1_write_bitstrings:"FF":6:"030202FC":4:0
+test_asn1_write_bitstrings:"FF":6:"030202FC":0
 
 ASN.1 Write Bitstring / Unused bits #3
-test_asn1_write_bitstrings:"FF":5:"030203F8":4:0
+test_asn1_write_bitstrings:"FF":5:"030203F8":0
 
 ASN.1 Write Bitstring / Unused bits #4
-test_asn1_write_bitstrings:"FF":4:"030204F0":4:0
+test_asn1_write_bitstrings:"FF":4:"030204F0":0
 
 ASN.1 Write Bitstring / Unused bits #5
-test_asn1_write_bitstrings:"FF":3:"030205E0":4:0
+test_asn1_write_bitstrings:"FF":3:"030205E0":0
 
 ASN.1 Write Bitstring / Unused bits #6
-test_asn1_write_bitstrings:"FF":2:"030206C0":4:0
+test_asn1_write_bitstrings:"FF":2:"030206C0":0
 
 ASN.1 Write Bitstring / Unused bits #7
-test_asn1_write_bitstrings:"FF":1:"03020780":4:0
+test_asn1_write_bitstrings:"FF":1:"03020780":0
 
 ASN.1 Write Bitstring / 1 trailing bit (bits 15)
-test_asn1_write_bitstrings:"0003":15:"0303010002":5:0
+test_asn1_write_bitstrings:"0003":15:"0303010002":0
 
 ASN.1 Write Bitstring / 0 bits
-test_asn1_write_bitstrings:"":0:"030100":3:0
+test_asn1_write_bitstrings:"":0:"030100":0
 
 ASN.1 Write Bitstring / long string all bits unset except trailing bits
-test_asn1_write_bitstrings:"000000000007":45:"030703000000000000":9:0
+test_asn1_write_bitstrings:"000000000007":45:"030703000000000000":0
+
+Store named data: not found
+store_named_data_find:"414141":"424242":"434343":"444444":"7f7f7f":0:-1
+
+Store named data: empty haystack
+store_named_data_find:"414141":"424242":"434343":"444444":"7f7f7f":4:-1
+
+Store named data: first
+store_named_data_find:"414141":"424242":"434343":"444444":"414141":0:0
+
+Store named data: last
+store_named_data_find:"414141":"424242":"434343":"444444":"444444":0:3
+
+Store named data: skip suffix
+store_named_data_find:"41414141":"414141":"434343":"444444":"414141":0:1
+
+Store named data: skip prefix
+store_named_data_find:"4141":"414141":"434343":"444444":"414141":0:1
+
+Store named data: first match
+store_named_data_find:"414141":"414141":"434343":"444444":"414141":0:0
+
+Store named data: found, null to zero
+store_named_data_val_found:0:0
+
+Store named data: found, null to data
+store_named_data_val_found:0:9
+
+Store named data: found, data to zero
+store_named_data_val_found:9:0
+
+Store named data: found, smaller data
+store_named_data_val_found:9:2
+
+Store named data: found, same-size data
+store_named_data_val_found:9:9
+
+Store named data: found, larger data
+store_named_data_val_found:4:9
+
+Store named data: new, val_len=0
+store_named_data_val_new:0
+
+Store named data: new, val_len=4
+store_named_data_val_new:4
+
+Store named data: new, val_len=4, val=NULL
+store_named_data_val_new:-4
diff --git a/tests/suites/test_suite_asn1write.function b/tests/suites/test_suite_asn1write.function
index e45583c..b69f6b5 100644
--- a/tests/suites/test_suite_asn1write.function
+++ b/tests/suites/test_suite_asn1write.function
@@ -3,6 +3,53 @@
 
 #define GUARD_LEN 4
 #define GUARD_VAL 0x2a
+
+typedef struct
+{
+    unsigned char *output;
+    unsigned char *start;
+    unsigned char *end;
+    unsigned char *p;
+    size_t size;
+} generic_write_data_t;
+
+int generic_write_start_step( generic_write_data_t *data )
+{
+    test_set_step( data->size );
+    ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size );
+    data->end = data->output + data->size;
+    data->p = data->end;
+    data->start = data->end - data->size;
+    return( 1 );
+exit:
+    return( 0 );
+}
+
+int generic_write_finish_step( generic_write_data_t *data,
+                               const data_t *expected, int ret )
+{
+    int ok = 0;
+
+    if( data->size < expected->len )
+    {
+        TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    }
+    else
+    {
+        TEST_EQUAL( ret, data->end - data->p );
+        TEST_ASSERT( data->p >= data->start );
+        TEST_ASSERT( data->p <= data->end );
+        ASSERT_COMPARE( data->p, (size_t)( data->end - data->p ),
+                        expected->x, expected->len );
+    }
+    ok = 1;
+
+exit:
+    mbedtls_free( data->output );
+    data->output = NULL;
+    return( ok );
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -11,74 +58,175 @@
  */
 
 /* BEGIN_CASE */
-void mbedtls_asn1_write_octet_string( data_t * str, data_t * asn1,
-                                      int buf_len, int result )
+void mbedtls_asn1_write_null( data_t *expected )
 {
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
     int ret;
-    unsigned char buf[150];
-    size_t i;
-    unsigned char *p;
 
-    memset( buf, GUARD_VAL, sizeof( buf ) );
-
-
-    p = buf + GUARD_LEN + buf_len;
-
-    ret = mbedtls_asn1_write_octet_string( &p, buf + GUARD_LEN, str->x, str->len );
-
-    /* Check for buffer overwrite on both sides */
-    for( i = 0; i < GUARD_LEN; i++ )
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
     {
-        TEST_ASSERT( buf[i] == GUARD_VAL );
-        TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = mbedtls_asn1_write_null( &data.p, data.start );
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
     }
 
-    if( result >= 0 )
-    {
-        TEST_ASSERT( (size_t) ret == asn1->len );
-        TEST_ASSERT( p + asn1->len == buf + GUARD_LEN + buf_len );
-
-        TEST_ASSERT( memcmp( p, asn1->x, asn1->len ) == 0 );
-    }
+exit:
+    mbedtls_free( data.output );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_asn1_write_ia5_string( char * str, data_t * asn1,
-                                    int buf_len, int result )
+void mbedtls_asn1_write_bool( int val, data_t *expected )
 {
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
     int ret;
-    unsigned char buf[150];
-    size_t str_len;
-    size_t i;
-    unsigned char *p;
 
-    memset( buf, GUARD_VAL, sizeof( buf ) );
-
-    str_len = strlen( str );
-
-    p = buf + GUARD_LEN + buf_len;
-
-    ret = mbedtls_asn1_write_ia5_string( &p, buf + GUARD_LEN, str, str_len );
-
-    /* Check for buffer overwrite on both sides */
-    for( i = 0; i < GUARD_LEN; i++ )
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
     {
-        TEST_ASSERT( buf[i] == GUARD_VAL );
-        TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL );
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = mbedtls_asn1_write_bool( &data.p, data.start, val );
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
     }
 
-    if( result >= 0 )
-    {
-        TEST_ASSERT( (size_t) ret == asn1->len );
-        TEST_ASSERT( p + asn1->len == buf + GUARD_LEN + buf_len );
-
-        TEST_ASSERT( memcmp( p, asn1->x, asn1->len ) == 0 );
-    }
+exit:
+    mbedtls_free( data.output );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ASN1PARSE_C */
+/* BEGIN_CASE */
+void mbedtls_asn1_write_int( int val, data_t *expected )
+{
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
+    int ret;
+
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
+    {
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = mbedtls_asn1_write_int( &data.p, data.start, val );
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
+    }
+
+exit:
+    mbedtls_free( data.output );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
+void mbedtls_asn1_write_mpi( data_t *val, data_t *expected )
+{
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
+    mbedtls_mpi mpi;
+    int ret;
+
+    mbedtls_mpi_init( &mpi );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &mpi, val->x, val->len ) == 0 );
+
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
+    {
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = mbedtls_asn1_write_mpi( &data.p, data.start, &mpi );
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
+        if( expected->len > 10 && data.size == 8 )
+            data.size = expected->len - 2;
+    }
+
+exit:
+    mbedtls_mpi_free( &mpi );
+    mbedtls_free( data.output );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_asn1_write_string( int tag, data_t *content, data_t *expected )
+{
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
+    int ret;
+
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
+    {
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        switch( tag )
+        {
+            case MBEDTLS_ASN1_OCTET_STRING:
+                ret = mbedtls_asn1_write_octet_string(
+                    &data.p, data.start, content->x, content->len );
+                break;
+            case MBEDTLS_ASN1_OID:
+                ret = mbedtls_asn1_write_oid(
+                    &data.p, data.start,
+                    (const char *) content->x, content->len );
+                break;
+            case MBEDTLS_ASN1_UTF8_STRING:
+                ret = mbedtls_asn1_write_utf8_string(
+                    &data.p, data.start,
+                    (const char *) content->x, content->len );
+                break;
+            case MBEDTLS_ASN1_PRINTABLE_STRING:
+                ret = mbedtls_asn1_write_printable_string(
+                    &data.p, data.start,
+                    (const char *) content->x, content->len );
+                break;
+            case MBEDTLS_ASN1_IA5_STRING:
+                ret = mbedtls_asn1_write_ia5_string(
+                    &data.p, data.start,
+                    (const char *) content->x, content->len );
+                break;
+            default:
+                ret = mbedtls_asn1_write_tagged_string(
+                    &data.p, data.start, tag,
+                    (const char *) content->x, content->len );
+        }
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
+        if( expected->len > 10 && data.size == 8 )
+            data.size = expected->len - 2;
+    }
+
+exit:
+    mbedtls_free( data.output );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_asn1_write_algorithm_identifier( data_t *oid,
+                                              int par_len,
+                                              data_t *expected )
+{
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
+    int ret;
+
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
+    {
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = mbedtls_asn1_write_algorithm_identifier(
+            &data.p, data.start,
+            (const char *) oid->x, oid->len, par_len );
+        /* If params_len != 0, mbedtls_asn1_write_algorithm_identifier()
+         * assumes that the parameters are already present in the buffer
+         * and returns a length that accounts for this, but our test
+         * data omits the parameters. */
+        if( ret >= 0 )
+            ret -= par_len;
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
+    }
+
+exit:
+    mbedtls_free( data.output );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
 void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len,
                              int result )
 {
@@ -131,44 +279,174 @@
 
 /* BEGIN_CASE */
 void test_asn1_write_bitstrings( data_t *bitstring, int bits,
-                                 data_t *expected_asn1, int result,
-                                 int is_named )
+                                 data_t *expected, int is_named )
 {
+    generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 };
     int ret;
-    size_t i;
-    unsigned char buf[150];
-    unsigned char *p;
+    int ( *func )( unsigned char **p, unsigned char *start,
+                   const unsigned char *buf, size_t bits ) =
+        ( is_named ? mbedtls_asn1_write_named_bitstring :
+          mbedtls_asn1_write_bitstring );
 
-    memset( buf, GUARD_VAL, sizeof( buf ) );
-
-    p = buf + GUARD_LEN + expected_asn1->len;
-
-    if ( is_named == 0 )
+    for( data.size = 0; data.size < expected->len + 1; data.size++ )
     {
-        ret = mbedtls_asn1_write_bitstring( &p,
-                                            buf,
-                                            (unsigned char *)bitstring->x,
-                                            (size_t) bits );
+        if( ! generic_write_start_step( &data ) )
+            goto exit;
+        ret = ( *func )( &data.p, data.start, bitstring->x, bits );
+        if( ! generic_write_finish_step( &data, expected, ret ) )
+            goto exit;
+    }
+
+exit:
+    mbedtls_free( data.output );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void store_named_data_find( data_t *oid0, data_t *oid1,
+                            data_t *oid2, data_t *oid3,
+                            data_t *needle, int from, int position )
+{
+    data_t *oid[4] = {oid0, oid1, oid2, oid3};
+    mbedtls_asn1_named_data nd[] ={
+        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
+        { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 },
+    };
+    mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1];
+    size_t i;
+    mbedtls_asn1_named_data *head = NULL;
+    mbedtls_asn1_named_data *found = NULL;
+
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+        pointers[i] = &nd[i];
+    pointers[ARRAY_LENGTH( nd )] = NULL;
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+    {
+        ASSERT_ALLOC( nd[i].oid.p, oid[i]->len );
+        memcpy( nd[i].oid.p, oid[i]->x, oid[i]->len );
+        nd[i].oid.len = oid[i]->len;
+        nd[i].next = pointers[i+1];
+    }
+
+    head = pointers[from];
+    found = mbedtls_asn1_store_named_data( &head,
+                                           (const char *) needle->x,
+                                           needle->len,
+                                           NULL, 0 );
+
+    /* In any case, the existing list structure must be unchanged. */
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+        TEST_ASSERT( nd[i].next == pointers[i+1] );
+
+    if( position >= 0 )
+    {
+        /* position should have been found and modified. */
+        TEST_ASSERT( head == pointers[from] );
+        TEST_ASSERT( found == pointers[position] );
     }
     else
     {
-        ret = mbedtls_asn1_write_named_bitstring( &p,
-                                                  buf,
-                                                  (unsigned char *)bitstring->x,
-                                                  (size_t) bits );
-    }
-    TEST_ASSERT( ret == result );
-
-    /* Check for buffer overwrite on both sides */
-    for( i = 0; i < GUARD_LEN; i++ )
-    {
-        TEST_ASSERT( buf[i] == GUARD_VAL );
-        TEST_ASSERT( buf[GUARD_LEN + expected_asn1->len + i] == GUARD_VAL );
+        /* A new entry should have been created. */
+        TEST_ASSERT( found == head );
+        TEST_ASSERT( head->next == pointers[from] );
+        for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+            TEST_ASSERT( found != &nd[i] );
     }
 
-    if ( result >= 0 )
+exit:
+    if( found != NULL && found == head && found != pointers[from] )
     {
-        TEST_ASSERT( memcmp( p, expected_asn1->x, expected_asn1->len ) == 0 );
+        mbedtls_free( found->oid.p );
+        mbedtls_free( found );
     }
+    for( i = 0; i < ARRAY_LENGTH( nd ); i++ )
+        mbedtls_free( nd[i].oid.p );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void store_named_data_val_found( int old_len, int new_len )
+{
+    mbedtls_asn1_named_data nd =
+        { {0x06, 3, (unsigned char *) "OID"}, {0, 0, NULL}, NULL, 0 };
+    mbedtls_asn1_named_data *head = &nd;
+    mbedtls_asn1_named_data *found = NULL;
+    unsigned char *old_val = NULL;
+    unsigned char *new_val = (unsigned char *) "new value";
+
+    if( old_len != 0 )
+    {
+        ASSERT_ALLOC( nd.val.p, (size_t) old_len );
+        old_val = nd.val.p;
+        nd.val.len = old_len;
+        memset( old_val, 'x', old_len );
+    }
+    if( new_len <= 0 )
+    {
+        new_len = - new_len;
+        new_val = NULL;
+    }
+
+    found = mbedtls_asn1_store_named_data( &head, "OID", 3,
+                                           new_val, new_len );
+    TEST_ASSERT( head == &nd );
+    TEST_ASSERT( found == head );
+
+    if( new_val != NULL)
+        ASSERT_COMPARE( found->val.p, found->val.len,
+                        new_val, (size_t) new_len );
+    if( new_len == 0)
+        TEST_ASSERT( found->val.p == NULL );
+    else if( new_len == old_len )
+        TEST_ASSERT( found->val.p == old_val );
+    else
+        TEST_ASSERT( found->val.p != old_val );
+
+exit:
+    mbedtls_free( nd.val.p );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void store_named_data_val_new( int new_len )
+{
+    mbedtls_asn1_named_data *head = NULL;
+    mbedtls_asn1_named_data *found = NULL;
+    const unsigned char *oid = (unsigned char *) "OID";
+    size_t oid_len = strlen( (const char *) oid );
+    const unsigned char *new_val = (unsigned char *) "new value";
+
+    if( new_len <= 0 )
+        new_val = NULL;
+    if( new_len < 0 )
+        new_len = - new_len;
+
+    found = mbedtls_asn1_store_named_data( &head,
+                                           (const char *) oid, oid_len,
+                                           new_val, (size_t) new_len );
+    TEST_ASSERT( found != NULL );
+    TEST_ASSERT( found == head );
+    TEST_ASSERT( found->oid.p != oid );
+    ASSERT_COMPARE( found->oid.p, found->oid.len, oid, oid_len );
+    if( new_len == 0 )
+        TEST_ASSERT( found->val.p == NULL );
+    else if( new_val == NULL )
+        TEST_ASSERT( found->val.p != NULL );
+    else
+    {
+        TEST_ASSERT( found->val.p != new_val );
+        ASSERT_COMPARE( found->val.p, found->val.len,
+                        new_val, (size_t) new_len );
+    }
+
+exit:
+    if( found != NULL )
+    {
+        mbedtls_free( found->oid.p );
+        mbedtls_free( found->val.p );
+    }
+    mbedtls_free( found );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_ctr_drbg.data b/tests/suites/test_suite_ctr_drbg.data
index 312910e..b50df2b 100644
--- a/tests/suites/test_suite_ctr_drbg.data
+++ b/tests/suites/test_suite_ctr_drbg.data
@@ -1070,8 +1070,22 @@
 depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
 ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602"
 
-CTR_DRBG entropy usage
-ctr_drbg_entropy_usage:
+CTR_DRBG entropy usage (default entropy_nonce_len)
+ctr_drbg_entropy_usage:-1
+
+CTR_DRBG entropy usage (entropy_nonce_len=0)
+ctr_drbg_entropy_usage:0
+
+CTR_DRBG entropy usage (entropy_nonce_len=7)
+ctr_drbg_entropy_usage:7
+
+CTR_DRBG entropy strength: 128 bits
+depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ctr_drbg_entropy_strength:128
+
+CTR_DRBG entropy strength: 256 bits
+depends_on:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ctr_drbg_entropy_strength:256
 
 CTR_DRBG write/update seed file [#1]
 ctr_drbg_seed_file:"data_files/ctr_drbg_seed":0
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 4a97826..8317c08 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -44,11 +44,12 @@
 
     /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
      * where nonce||perso = nonce[nonce->len] */
-    TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len(
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len );
+    mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+    TEST_ASSERT( mbedtls_ctr_drbg_seed(
                      &ctx,
                      mbedtls_test_entropy_func, entropy->x,
-                     nonce->x, nonce->len,
-                     entropy_chunk_len ) == 0 );
+                     nonce->x, nonce->len ) == 0 );
     if( reseed_mode == RESEED_ALWAYS )
         mbedtls_ctr_drbg_set_prediction_resistance(
             &ctx,
@@ -187,17 +188,47 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void ctr_drbg_entropy_strength( int expected_bit_strength )
+{
+    unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
+                          /*nonce*/     MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
+                          /*reseed*/          MBEDTLS_CTR_DRBG_ENTROPY_LEN];
+    mbedtls_ctr_drbg_context ctx;
+    size_t last_idx;
+    size_t byte_strength = expected_bit_strength / 8;
 
+    mbedtls_ctr_drbg_init( &ctx );
+    test_offset_idx = 0;
+    test_max_idx = sizeof( entropy );
+    memset( entropy, 0, sizeof( entropy ) );
+
+    /* The initial seeding must grab at least byte_strength bytes of entropy
+     * for the entropy input and byte_strength/2 bytes for a nonce. */
+    TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx,
+                                        mbedtls_test_entropy_func, entropy,
+                                        NULL, 0 ) == 0 );
+    TEST_ASSERT( test_offset_idx >= ( byte_strength * 3 + 1 ) / 2 );
+    last_idx = test_offset_idx;
+
+    /* A reseed must grab at least byte_strength bytes of entropy. */
+    TEST_ASSERT( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) == 0 );
+    TEST_ASSERT( test_offset_idx - last_idx >= byte_strength );
+
+exit:
+    mbedtls_ctr_drbg_free( &ctx );
+}
+/* END_CASE */
 
 /* BEGIN_CASE */
-void ctr_drbg_entropy_usage(  )
+void ctr_drbg_entropy_usage( int entropy_nonce_len )
 {
     unsigned char out[16];
     unsigned char add[16];
     unsigned char entropy[1024];
     mbedtls_ctr_drbg_context ctx;
     size_t i, reps = 10;
-    size_t last_idx;
+    size_t expected_idx = 0;
 
     mbedtls_ctr_drbg_init( &ctx );
     test_offset_idx = 0;
@@ -206,21 +237,27 @@
     memset( out, 0, sizeof( out ) );
     memset( add, 0, sizeof( add ) );
 
+    if( entropy_nonce_len >= 0 )
+        TEST_ASSERT( mbedtls_ctr_drbg_set_nonce_len( &ctx, entropy_nonce_len ) == 0 );
+
     /* Init must use entropy */
-    last_idx = test_offset_idx;
     TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 );
-    TEST_ASSERT( last_idx < test_offset_idx );
+    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    if( entropy_nonce_len >= 0 )
+        expected_idx += entropy_nonce_len;
+    else
+        expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     /* By default, PR is off and reseed_interval is large,
      * so the next few calls should not use entropy */
-    last_idx = test_offset_idx;
     for( i = 0; i < reps; i++ )
     {
         TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
         TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
                                                 add, sizeof( add ) ) == 0 );
     }
-    TEST_ASSERT( last_idx == test_offset_idx );
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     /* While at it, make sure we didn't write past the requested length */
     TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
@@ -232,17 +269,17 @@
      * so the next call should reseed */
     mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
     TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( last_idx < test_offset_idx );
+    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     /* The new few calls should not reseed */
-    last_idx = test_offset_idx;
     for( i = 0; i < reps / 2; i++ )
     {
         TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
         TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
                                                 add, sizeof( add ) ) == 0 );
     }
-    TEST_ASSERT( last_idx == test_offset_idx );
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
      * Make sure it's detected as an error and doesn't cause memory
@@ -253,18 +290,19 @@
     /* Now enable PR, so the next few calls should all reseed */
     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
     TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( last_idx < test_offset_idx );
+    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     /* Finally, check setting entropy_len */
     mbedtls_ctr_drbg_set_entropy_len( &ctx, 42 );
-    last_idx = test_offset_idx;
     TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( test_offset_idx - last_idx == 42 );
+    expected_idx += 42;
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
     mbedtls_ctr_drbg_set_entropy_len( &ctx, 13 );
-    last_idx = test_offset_idx;
     TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( test_offset_idx - last_idx == 13 );
+    expected_idx += 13;
+    TEST_EQUAL( test_offset_idx, expected_idx );
 
 exit:
     mbedtls_ctr_drbg_free( &ctx );
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index 13bc400..b526f43 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -37,7 +37,9 @@
     const mbedtls_md_info_t *md_info;
     mbedtls_hmac_drbg_context ctx;
     entropy_ctx entropy;
-    size_t last_len, i, reps = 10;
+    size_t i, reps = 10;
+    size_t default_entropy_len;
+    size_t expected_consumed_entropy = 0;
 
     mbedtls_hmac_drbg_init( &ctx );
     memset( buf, 0, sizeof( buf ) );
@@ -48,23 +50,29 @@
 
     md_info = mbedtls_md_info_from_type( md_alg );
     TEST_ASSERT( md_info != NULL );
+    if( mbedtls_md_get_size( md_info ) <= 20 )
+        default_entropy_len = 16;
+    else if( mbedtls_md_get_size( md_info ) <= 28 )
+        default_entropy_len = 24;
+    else
+        default_entropy_len = 32;
 
     /* Init must use entropy */
-    last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy,
                                  NULL, 0 ) == 0 );
-    TEST_ASSERT( entropy.len < last_len );
+    /* default_entropy_len of entropy, plus half as much for the nonce */
+    expected_consumed_entropy += default_entropy_len * 3 / 2;
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     /* By default, PR is off and reseed_interval is large,
      * so the next few calls should not use entropy */
-    last_len = entropy.len;
     for( i = 0; i < reps; i++ )
     {
         TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
         TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
                                                 buf, 16 ) == 0 );
     }
-    TEST_ASSERT( entropy.len == last_len );
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     /* While at it, make sure we didn't write past the requested length */
     TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
@@ -76,33 +84,34 @@
      * so the next call should reseed */
     mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( entropy.len < last_len );
+    expected_consumed_entropy += default_entropy_len;
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     /* The new few calls should not reseed */
-    last_len = entropy.len;
     for( i = 0; i < reps / 2; i++ )
     {
         TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
         TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) ,
                                                 buf, 16 ) == 0 );
     }
-    TEST_ASSERT( entropy.len == last_len );
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     /* Now enable PR, so the next few calls should all reseed */
     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( entropy.len < last_len );
+    expected_consumed_entropy += default_entropy_len;
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     /* Finally, check setting entropy_len */
     mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 );
-    last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( (int) last_len - entropy.len == 42 );
+    expected_consumed_entropy += 42;
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
     mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 );
-    last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
-    TEST_ASSERT( (int) last_len - entropy.len == 13 );
+    expected_consumed_entropy += 13;
+    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
 
 exit:
     mbedtls_hmac_drbg_free( &ctx );
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 162cb56..b349075 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -664,7 +664,7 @@
                              char * input_E, data_t * result_str,
                              int result )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context *rsa;
     mbedtls_pk_context pk;
     mbedtls_pk_restart_ctx *rs_ctx = NULL;
@@ -679,7 +679,7 @@
 
     mbedtls_pk_init( &pk );
 
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, MBEDTLS_MD_MAX_SIZE );
 
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == 0 );
     rsa = mbedtls_pk_rsa( pk );
@@ -713,7 +713,7 @@
                                  data_t * result_str, int pk_type,
                                  int mgf1_hash_id, int salt_len, int result )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context *rsa;
     mbedtls_pk_context pk;
     mbedtls_pk_rsassa_pss_options pss_opts;
@@ -722,7 +722,7 @@
 
     mbedtls_pk_init( &pk );
 
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
 
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == 0 );
     rsa = mbedtls_pk_rsa( pk );
@@ -976,7 +976,7 @@
                               char * input_N, int radix_E, char * input_E,
                               data_t * result, int ret )
 {
-    unsigned char output[1000];
+    unsigned char output[300];
     rnd_pseudo_info rnd_info;
     mbedtls_rsa_context *rsa;
     mbedtls_pk_context pk;
@@ -1011,7 +1011,7 @@
                               int radix_N, char * input_N, int radix_E,
                               char * input_E, data_t * clear, int ret )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     rnd_pseudo_info rnd_info;
     mbedtls_mpi N, P, Q, E;
     mbedtls_rsa_context *rsa;
@@ -1136,8 +1136,8 @@
     mbedtls_rsa_context raw;
     mbedtls_pk_context rsa, alt;
     mbedtls_pk_debug_item dbg_items[10];
-    unsigned char hash[50], sig[1000];
-    unsigned char msg[50], ciph[1000], test[1000];
+    unsigned char hash[50], sig[64];
+    unsigned char msg[50], ciph[64], test[50];
     size_t sig_len, ciph_len, test_len;
     int ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
 
diff --git a/tests/suites/test_suite_pkcs1_v15.function b/tests/suites/test_suite_pkcs1_v15.function
index 3ef4e2c..13fdf58 100644
--- a/tests/suites/test_suite_pkcs1_v15.function
+++ b/tests/suites/test_suite_pkcs1_v15.function
@@ -14,7 +14,7 @@
                               data_t * message_str, data_t * rnd_buf,
                               data_t * result_hex_str, int result )
 {
-    unsigned char output[1000];
+    unsigned char output[128];
     mbedtls_rsa_context ctx;
     rnd_buf_info info;
     mbedtls_mpi N, E;
@@ -24,7 +24,7 @@
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -54,7 +54,7 @@
                               char * seed, data_t * message_str,
                               int result )
 {
-    unsigned char output[1000];
+    unsigned char output[128];
     mbedtls_rsa_context ctx;
     size_t output_len;
     rnd_pseudo_info rnd_info;
@@ -65,7 +65,7 @@
     mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
@@ -253,8 +253,8 @@
                             data_t * message_str, data_t * rnd_buf,
                             data_t * result_hex_str, int result )
 {
-    unsigned char hash_result[1000];
-    unsigned char output[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
+    unsigned char output[128];
     mbedtls_rsa_context ctx;
     mbedtls_mpi N, P, Q, E;
     rnd_buf_info info;
@@ -266,8 +266,8 @@
     mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
 
-    memset( hash_result, 0x00, 1000 );
-    memset( output, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
@@ -303,14 +303,14 @@
                               int hash, data_t * message_str, char * salt,
                               data_t * result_str, int result )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context ctx;
     mbedtls_mpi N, E;
     ((void) salt);
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
diff --git a/tests/suites/test_suite_pkcs1_v21.function b/tests/suites/test_suite_pkcs1_v21.function
index 180bc4a..7b8087b 100644
--- a/tests/suites/test_suite_pkcs1_v21.function
+++ b/tests/suites/test_suite_pkcs1_v21.function
@@ -14,7 +14,7 @@
                                data_t * message_str, data_t * rnd_buf,
                                data_t * result_hex_str, int result )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
     rnd_buf_info info;
     mbedtls_mpi N, E;
@@ -24,7 +24,7 @@
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -54,7 +54,7 @@
                                char * seed, data_t * message_str,
                                int result )
 {
-    unsigned char output[1000];
+    unsigned char output[64];
     mbedtls_rsa_context ctx;
     size_t output_len;
     rnd_pseudo_info rnd_info;
@@ -66,7 +66,7 @@
 
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
@@ -81,11 +81,16 @@
 
     if( result_hex_str->len == 0 )
     {
-        TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE, &output_len, message_str->x, NULL, 0 ) == result );
+        TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, &rnd_pseudo_rand, &rnd_info,
+                                                MBEDTLS_RSA_PRIVATE, &output_len,
+                                                message_str->x, NULL, 0 ) == result );
     }
     else
     {
-        TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE, &output_len, message_str->x, output, 1000 ) == result );
+        TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, &rnd_pseudo_rand, &rnd_info,
+                                                MBEDTLS_RSA_PRIVATE, &output_len,
+                                                message_str->x, output,
+                                                sizeof( output ) ) == result );
         if( result == 0 )
         {
             TEST_ASSERT( hexcmp( output, result_hex_str->x, output_len, result_hex_str->len ) == 0 );
@@ -106,8 +111,8 @@
                             data_t * message_str, data_t * rnd_buf,
                             data_t * result_hex_str, int result )
 {
-    unsigned char hash_result[1000];
-    unsigned char output[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
     rnd_buf_info info;
     mbedtls_mpi N, P, Q, E;
@@ -119,8 +124,8 @@
     mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
 
-    memset( hash_result, 0x00, 1000 );
-    memset( output, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
@@ -157,14 +162,14 @@
                               int hash, data_t * message_str, char * salt,
                               data_t * result_str, int result )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context ctx;
     mbedtls_mpi N, E;
     ((void) salt);
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -194,14 +199,14 @@
                                   data_t * result_str, int result_simple,
                                   int result_full )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context ctx;
     size_t hash_len;
     mbedtls_mpi N, E;
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, ctx_hash );
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data
index c8ff177..e0101cc 100644
--- a/tests/suites/test_suite_pkwrite.data
+++ b/tests/suites/test_suite_pkwrite.data
@@ -30,10 +30,18 @@
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_write_key_check:"data_files/ec_prv.sec1.pem"
 
+Private key write check EC 256 bits (top bit set)
+depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+pk_write_key_check:"data_files/ec_256_long_prv.pem"
+
 Private key write check EC 521 bits
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 pk_write_key_check:"data_files/ec_521_prv.pem"
 
+Private key write check EC 521 bits (top byte is 0)
+depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+pk_write_key_check:"data_files/ec_521_short_prv.pem"
+
 Private key write check EC Brainpool 512 bits
 depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_BP512R1_ENABLED
 pk_write_key_check:"data_files/ec_bp512_prv.pem"
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 6efdc01..3bd3738 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -43,15 +43,6 @@
 depends_on:MBEDTLS_AES_C
 import_export:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:256:0:PSA_SUCCESS:1
 
-PSA invalid handle (0)
-invalid_handle:0
-
-PSA invalid handle (smallest plausible handle)
-invalid_handle:1
-
-PSA invalid handle (largest plausible handle)
-invalid_handle:-1
-
 PSA import: bad usage flag
 import_with_policy:PSA_KEY_TYPE_RAW_DATA:0x40000000:0:PSA_ERROR_INVALID_ARGUMENT
 
@@ -1547,6 +1538,14 @@
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
 sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
 
+PSA sign: deterministic ECDSA SECP256R1 SHA-384
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA512_C:MBEDTLS_ECDSA_C
+sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca"
+
+PSA sign: deterministic ECDSA SECP384R1 SHA-256
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
+sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP384R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f"
+
 PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
 sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT
@@ -1621,6 +1620,22 @@
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
 sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
+PSA sign/verify: randomized ECDSA SECP256R1 SHA-384
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_SHA512_C
+sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
+
+PSA sign/verify: deterministic ECDSA SECP256R1 SHA-384
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA512_C:MBEDTLS_ECDSA_C
+sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
+
+PSA sign/verify: randomized ECDSA SECP384R1 SHA-256
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C
+sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP384R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
+PSA sign/verify: deterministic ECDSA SECP384R1 SHA-256
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
+sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP384R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
 PSA verify: RSA PKCS#1 v1.5 SHA-256, good signature
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
 asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 87529ac..f3f79ab 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -736,6 +736,11 @@
     TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
                                       MBEDTLS_ASN1_INTEGER ),
                 0 );
+
+    /* Check if the retrieved length doesn't extend the actual buffer's size.
+     * It is assumed here, that end >= p, which validates casting to size_t. */
+    TEST_ASSERT( len <= (size_t)( end - *p) );
+
     /* Tolerate a slight departure from DER encoding:
      * - 0 may be represented by an empty string or a 1-byte string.
      * - The sign bit may be used as a value bit. */
@@ -894,6 +899,8 @@
                               "No sanity check for public key type=0x%08lx",
                               (unsigned long) type );
             test_fail( message, __LINE__, __FILE__ );
+            (void) p;
+            (void) end;
             return( 0 );
         }
     }
@@ -1103,9 +1110,6 @@
                                        buffer, sizeof( buffer ), &length ),
                 PSA_ERROR_INVALID_HANDLE );
 
-    TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_destroy_key( handle ), PSA_ERROR_INVALID_HANDLE );
-
     ok = 1;
 
 exit:
@@ -1536,17 +1540,6 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void invalid_handle( int handle )
-{
-    PSA_ASSERT( psa_crypto_init( ) );
-    test_operations_on_invalid_handle( handle );
-
-exit:
-    PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void import_export_public_key( data_t *data,
                                int type_arg,
                                int alg_arg,
diff --git a/tests/suites/test_suite_psa_crypto_init.data b/tests/suites/test_suite_psa_crypto_init.data
index c57a764..9620a64 100644
--- a/tests/suites/test_suite_psa_crypto_init.data
+++ b/tests/suites/test_suite_psa_crypto_init.data
@@ -34,15 +34,25 @@
 Fake entropy: less than the block size
 fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:-1:PSA_ERROR_INSUFFICIENT_ENTROPY
 
+Fake entropy: not enough for a nonce
+depends_on:ENTROPY_NONCE_LEN != 0
+fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:ENTROPY_NONCE_LEN - 1:-1:-1:-1:PSA_ERROR_INSUFFICIENT_ENTROPY
+
 Fake entropy: one block eventually
+depends_on:ENTROPY_NONCE_LEN == 0
 fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:0:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS
 
 Fake entropy: one block in two steps
+depends_on:ENTROPY_NONCE_LEN == 0
 fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:1:-1:-1:PSA_SUCCESS
 
 Fake entropy: more than one block in two steps
+depends_on:ENTROPY_NONCE_LEN == 0
 fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:PSA_SUCCESS
 
+Fake entropy: two blocks eventually
+fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:MBEDTLS_ENTROPY_BLOCK_SIZE:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS
+
 NV seed only: less than minimum
 entropy_from_nv_seed:MBEDTLS_ENTROPY_MIN_PLATFORM - 1:PSA_ERROR_INSUFFICIENT_ENTROPY
 
diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function
index 3c4b42e..3283ac9 100644
--- a/tests/suites/test_suite_psa_crypto_init.function
+++ b/tests/suites/test_suite_psa_crypto_init.function
@@ -11,6 +11,12 @@
 #define ENTROPY_MIN_NV_SEED_SIZE                                        \
     MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
 
+/* PSA crypto uses the CTR_DRBG module. In some configurations, it needs
+ * to read from the entropy source twice: once for the initial entropy
+ * and once for a nonce. */
+#include "mbedtls/ctr_drbg.h"
+#define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN
+
 typedef struct
 {
     size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index 53e3fc5..1b0ef04 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -121,23 +121,23 @@
 generate_key_smoke:PSA_KEY_TYPE_HMAC:256:PSA_ALG_HMAC( PSA_ALG_SHA_256 )
 
 Key registration: smoke test
-register_key_smoke_test:MIN_DRIVER_LIFETIME:-1:PSA_SUCCESS
-
-Key registration: invalid lifetime (volatile)
-register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:-1:PSA_ERROR_INVALID_ARGUMENT
-
-Key registration: invalid lifetime (internal storage)
-register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:-1:PSA_ERROR_INVALID_ARGUMENT
-
-Key registration: invalid lifetime (no registered driver)
-register_key_smoke_test:MIN_DRIVER_LIFETIME + 1:-1:PSA_ERROR_INVALID_ARGUMENT
-
-Key registration: with driver validation (accepted)
 register_key_smoke_test:MIN_DRIVER_LIFETIME:1:PSA_SUCCESS
 
-Key registration: with driver validation (rejected)
+Key registration: invalid lifetime (volatile)
+register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: invalid lifetime (internal storage)
+register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: invalid lifetime (no registered driver)
+register_key_smoke_test:MIN_DRIVER_LIFETIME + 1:1:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: rejected
 register_key_smoke_test:MIN_DRIVER_LIFETIME:0:PSA_ERROR_NOT_PERMITTED
 
+Key registration: not supported
+register_key_smoke_test:MIN_DRIVER_LIFETIME:-1:PSA_ERROR_NOT_SUPPORTED
+
 Import-sign-verify: sign in driver, ECDSA
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 sign_verify:SIGN_IN_DRIVER_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index fc6f668..e06ef17 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -5,6 +5,13 @@
 #include "psa_crypto_se.h"
 #include "psa_crypto_storage.h"
 
+/* Invasive peeking: check the persistent data */
+#if defined(MBEDTLS_PSA_ITS_FILE_C)
+#include "psa_crypto_its.h"
+#else /* Native ITS implementation */
+#include "psa/error.h"
+#include "psa/internal_trusted_storage.h"
+#endif
 
 
 /****************************************************************/
@@ -90,11 +97,13 @@
 /* Validate a choice of slot number as directed. */
 static psa_status_t validate_slot_number_as_directed(
     psa_drv_se_context_t *context,
+    void *persistent_data,
     const psa_key_attributes_t *attributes,
     psa_key_creation_method_t method,
     psa_key_slot_number_t slot_number )
 {
     (void) context;
+    (void) persistent_data;
     (void) attributes;
     DRIVER_ASSERT_RETURN( slot_number ==
                           validate_slot_number_directions.slot_number );
@@ -104,6 +113,11 @@
 }
 
 /* Allocate slot numbers with a monotonic counter. */
+static psa_key_slot_number_t shadow_counter;
+static void counter_reset( void )
+{
+    shadow_counter = 0;
+}
 static psa_status_t counter_allocate( psa_drv_se_context_t *context,
                                       void *persistent_data,
                                       const psa_key_attributes_t *attributes,
@@ -118,6 +132,7 @@
     ++*p_counter;
     if( *p_counter == 0 )
         return( PSA_ERROR_INSUFFICIENT_STORAGE );
+    shadow_counter = *p_counter;
     *slot_number = *p_counter;
     return( PSA_SUCCESS );
 }
@@ -193,12 +208,15 @@
  * bit vector indicating which slots are in use. */
 typedef uint16_t ram_slot_usage_t;
 
+static ram_slot_usage_t ram_shadow_slot_usage;
+
 static uint8_t ram_min_slot = 0;
 
 static void ram_slots_reset( void )
 {
     memset( ram_slots, 0, sizeof( ram_slots ) );
     ram_min_slot = 0;
+    ram_shadow_slot_usage = 0;
 }
 
 /* Common parts of key creation.
@@ -342,6 +360,7 @@
     DRIVER_ASSERT_RETURN( slot_number < ARRAY_LENGTH( ram_slots ) );
     memset( &ram_slots[slot_number], 0, sizeof( ram_slots[slot_number] ) );
     *slot_usage &= ~(ram_slot_usage_t)( 1 << slot_number );
+    ram_shadow_slot_usage = *slot_usage;
     return( PSA_SUCCESS );
 }
 
@@ -360,18 +379,23 @@
          ++( *slot_number ) )
     {
         if( ! ( *slot_usage & 1 << *slot_number ) )
+        {
+            ram_shadow_slot_usage = *slot_usage;
             return( PSA_SUCCESS );
+        }
     }
     return( PSA_ERROR_INSUFFICIENT_STORAGE );
 }
 
 static psa_status_t ram_validate_slot_number(
     psa_drv_se_context_t *context,
+    void *persistent_data,
     const psa_key_attributes_t *attributes,
     psa_key_creation_method_t method,
     psa_key_slot_number_t slot_number )
 {
     (void) context;
+    (void) persistent_data;
     (void) attributes;
     (void) method;
     if( slot_number >= ARRAY_LENGTH( ram_slots ) )
@@ -522,6 +546,38 @@
     return( ok );
 }
 
+/* Get the file UID corresponding to the specified lifetime.
+ * If this changes, the storage format version must change.
+ * See psa_get_se_driver_its_file_uid() in psa_crypto_se.c.
+ */
+psa_storage_uid_t file_uid_for_lifetime( psa_key_lifetime_t lifetime )
+{
+    if( lifetime > PSA_MAX_SE_LIFETIME )
+        return( 0 );
+    return( 0xfffffe00 + lifetime );
+}
+
+/* Check that the persistent data of a driver has its expected content. */
+static int check_persistent_data( psa_key_lifetime_t lifetime,
+                                  const void *expected_data,
+                                  size_t size )
+{
+    psa_storage_uid_t uid = file_uid_for_lifetime( lifetime );
+    struct psa_storage_info_t info;
+    uint8_t *loaded = NULL;
+    int ok = 0;
+
+    PSA_ASSERT( psa_its_get_info( uid, &info ) );
+    ASSERT_ALLOC( loaded, info.size );
+    PSA_ASSERT( psa_its_get( uid, 0, info.size, loaded, NULL ) );
+    ASSERT_COMPARE( expected_data, size, loaded, info.size );
+    ok = 1;
+
+exit:
+    mbedtls_free( loaded );
+    return( ok );
+}
+
 /* Check that a function's return status is "smoke-free", i.e. that
  * it's an acceptable error code when calling an API function that operates
  * on a key with potentially bogus parameters. */
@@ -776,6 +832,10 @@
     PSA_ASSERT( psa_import_key( &attributes,
                                 key_material, sizeof( key_material ),
                                 &handle ) );
+    if( ! check_persistent_data( lifetime,
+                                 &ram_shadow_slot_usage,
+                                 sizeof( ram_shadow_slot_usage ) ) )
+        goto exit;
 
     /* Maybe restart, to check that the information is saved correctly. */
     if( restart )
@@ -783,6 +843,10 @@
         mbedtls_psa_crypto_free( );
         PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
         PSA_ASSERT( psa_crypto_init( ) );
+        if( ! check_persistent_data( lifetime,
+                                     &ram_shadow_slot_usage,
+                                     sizeof( ram_shadow_slot_usage ) ) )
+            goto exit;
         PSA_ASSERT( psa_open_key( id, &handle ) );
     }
 
@@ -805,6 +869,10 @@
 
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
+    if( ! check_persistent_data( lifetime,
+                                 &ram_shadow_slot_usage,
+                                 sizeof( ram_shadow_slot_usage ) ) )
+        goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
                 PSA_ERROR_DOES_NOT_EXIST );
 
@@ -860,6 +928,10 @@
 
     if( status != PSA_SUCCESS )
         goto exit;
+    if( ! check_persistent_data( lifetime,
+                                 &ram_shadow_slot_usage,
+                                 sizeof( ram_shadow_slot_usage ) ) )
+        goto exit;
 
     /* Maybe restart, to check that the information is saved correctly. */
     if( restart )
@@ -867,6 +939,10 @@
         mbedtls_psa_crypto_free( );
         PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
         PSA_ASSERT( psa_crypto_init( ) );
+        if( ! check_persistent_data( lifetime,
+                                     &ram_shadow_slot_usage,
+                                     sizeof( ram_shadow_slot_usage ) ) )
+            goto exit;
         PSA_ASSERT( psa_open_key( id, &handle ) );
     }
 
@@ -879,6 +955,10 @@
 
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
+    if( ! check_persistent_data( lifetime,
+                                 &ram_shadow_slot_usage,
+                                 sizeof( ram_shadow_slot_usage ) ) )
+        goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
                 PSA_ERROR_DOES_NOT_EXIST );
 
@@ -926,6 +1006,9 @@
     PSA_ASSERT( psa_import_key( &attributes,
                                 key_material->x, key_material->len,
                                 &handle ) );
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
 
     /* Do stuff with the key. */
     if( ! smoke_test_key( handle ) )
@@ -935,6 +1018,9 @@
     mbedtls_psa_crypto_free( );
     PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
     PSA_ASSERT( psa_open_key( id, &handle ) );
     if( ! smoke_test_key( handle ) )
         goto exit;
@@ -942,11 +1028,15 @@
     /* We're done. */
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
                 PSA_ERROR_DOES_NOT_EXIST );
 
 exit:
     PSA_DONE( );
+    counter_reset( );
     psa_purge_storage( );
 }
 /* END_CASE */
@@ -983,6 +1073,7 @@
 
 exit:
     PSA_DONE( );
+    counter_reset( );
     psa_purge_storage( );
 }
 /* END_CASE */
@@ -1023,6 +1114,9 @@
     psa_set_key_type( &attributes, type );
     psa_set_key_bits( &attributes, bits );
     PSA_ASSERT( psa_generate_key( &attributes, &handle ) );
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
 
     /* Do stuff with the key. */
     if( ! smoke_test_key( handle ) )
@@ -1032,6 +1126,9 @@
     mbedtls_psa_crypto_free( );
     PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
     PSA_ASSERT( psa_open_key( id, &handle ) );
     if( ! smoke_test_key( handle ) )
         goto exit;
@@ -1039,11 +1136,15 @@
     /* We're done. */
     PSA_ASSERT( psa_destroy_key( handle ) );
     handle = 0;
+    if( ! check_persistent_data( lifetime,
+                                 &shadow_counter, sizeof( shadow_counter ) ) )
+        goto exit;
     TEST_EQUAL( psa_open_key( id, &handle ),
                 PSA_ERROR_DOES_NOT_EXIST );
 
 exit:
     PSA_DONE( );
+    counter_reset( );
     psa_purge_storage( );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
index dba6875..f60bd76 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
@@ -1,3 +1,12 @@
+SE init mock test: success
+mock_init:2:PSA_SUCCESS:PSA_SUCCESS:PSA_SUCCESS:1
+
+SE init mock test: failure
+mock_init:2:PSA_SUCCESS:PSA_ERROR_HARDWARE_FAILURE:PSA_ERROR_HARDWARE_FAILURE:1
+
+SE init mock test: invalid lifetime
+mock_init:1:PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_BAD_STATE:PSA_SUCCESS:0
+
 SE key importing mock test
 mock_import:PSA_SUCCESS:PSA_SUCCESS:0:PSA_SUCCESS
 
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index e6b3f7b..7088a52 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -8,6 +8,13 @@
 static struct
 {
     uint16_t called;
+    psa_key_lifetime_t lifetime;
+    psa_status_t return_value;
+} mock_init_data;
+
+static struct
+{
+    uint16_t called;
     psa_key_slot_number_t key_slot;
     psa_key_attributes_t attributes;
     size_t pubkey_size;
@@ -92,6 +99,7 @@
 
 static void mock_teardown( void )
 {
+    memset( &mock_init_data, 0, sizeof( mock_init_data ) );
     memset( &mock_import_data, 0, sizeof( mock_import_data ) );
     memset( &mock_export_data, 0, sizeof( mock_export_data ) );
     memset( &mock_export_public_data, 0, sizeof( mock_export_public_data ) );
@@ -103,6 +111,18 @@
     psa_purge_storage( );
 }
 
+static psa_status_t mock_init( psa_drv_se_context_t *drv_context,
+                               void *persistent_data,
+                               psa_key_lifetime_t lifetime )
+{
+    (void) drv_context;
+    (void) persistent_data;
+
+    mock_init_data.called++;
+    mock_init_data.lifetime = lifetime;
+    return( mock_init_data.return_value );
+}
+
 static psa_status_t mock_generate( psa_drv_se_context_t *drv_context,
                                    psa_key_slot_number_t key_slot,
                                    const psa_key_attributes_t *attributes,
@@ -259,6 +279,42 @@
  */
 
 /* BEGIN_CASE */
+void mock_init( int lifetime_arg,
+                int expected_register_status_arg,
+                int driver_status_arg,
+                int expected_psa_status_arg,
+                int expected_called )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_status_t expected_register_status = expected_register_status_arg;
+    psa_status_t driver_status = driver_status_arg;
+    psa_status_t expected_psa_status = expected_psa_status_arg;
+    psa_drv_se_t driver = {
+        .hal_version = PSA_DRV_SE_HAL_VERSION,
+        .p_init = mock_init,
+    };
+    int psa_crypto_init_called = 0;
+
+    mock_init_data.return_value = driver_status;
+
+    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+                expected_register_status );
+
+    psa_crypto_init_called = 1;
+    TEST_EQUAL( psa_crypto_init( ), expected_psa_status );
+
+    TEST_EQUAL( mock_init_data.called, expected_called );
+    if( expected_called )
+        TEST_EQUAL( mock_init_data.lifetime, lifetime );
+
+exit:
+    if( psa_crypto_init_called )
+        PSA_DONE( );
+    mock_teardown( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mock_import( int mock_alloc_return_value,
                   int mock_import_return_value,
                   int bits,
@@ -335,6 +391,7 @@
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
     driver.key_management = &key_management;
+    driver.p_init = mock_init;
     key_management.p_import = mock_import;
     key_management.p_export = mock_export;
     key_management.p_destroy = mock_destroy;
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data
index 6fa8723..803917d 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.data
+++ b/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -148,8 +148,17 @@
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f"
 
-Close/destroy invalid handle
-invalid_handle:
+invalid handle: 0
+invalid_handle:INVALID_HANDLE_0:PSA_SUCCESS:PSA_ERROR_INVALID_HANDLE
+
+invalid handle: never opened
+invalid_handle:INVALID_HANDLE_UNOPENED:PSA_ERROR_INVALID_HANDLE:PSA_ERROR_INVALID_HANDLE
+
+invalid handle: already closed
+invalid_handle:INVALID_HANDLE_CLOSED:PSA_ERROR_INVALID_HANDLE:PSA_ERROR_INVALID_HANDLE
+
+invalid handle: huge
+invalid_handle:INVALID_HANDLE_HUGE:PSA_ERROR_INVALID_HANDLE:PSA_ERROR_INVALID_HANDLE
 
 Open many transient handles
 many_transient_handles:42
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index 3b9eada..4c824f7 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -20,6 +20,14 @@
     CLOSE_AFTER,
 } reopen_policy_t;
 
+typedef enum
+{
+    INVALID_HANDLE_0,
+    INVALID_HANDLE_UNOPENED,
+    INVALID_HANDLE_CLOSED,
+    INVALID_HANDLE_HUGE,
+} invalid_handle_construction_t;
+
 /* All test functions that create persistent keys must call
  * `TEST_USES_KEY_ID( key_id )` before creating a persistent key with this
  * identifier, and must call psa_purge_key_storage() in their cleanup
@@ -625,9 +633,13 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void invalid_handle( )
+void invalid_handle( int handle_construction,
+                     int close_status_arg, int usage_status_arg )
 {
-    psa_key_handle_t handle1 = 0;
+    psa_key_handle_t valid_handle = 0;
+    psa_key_handle_t invalid_handle = 0;
+    psa_status_t close_status = close_status_arg;
+    psa_status_t usage_status = usage_status_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t material[1] = "a";
 
@@ -639,23 +651,50 @@
     psa_set_key_algorithm( &attributes, 0 );
     PSA_ASSERT( psa_import_key( &attributes,
                                 material, sizeof( material ),
-                                &handle1 ) );
-    TEST_ASSERT( handle1 != 0 );
+                                &valid_handle ) );
+    TEST_ASSERT( valid_handle != 0 );
 
-    /* Attempt to close and destroy some invalid handles. */
-    TEST_EQUAL( psa_close_key( 0 ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_close_key( handle1 - 1 ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_close_key( handle1 + 1 ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_destroy_key( 0 ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_destroy_key( handle1 - 1 ), PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_destroy_key( handle1 + 1 ), PSA_ERROR_INVALID_HANDLE );
+    /* Construct an invalid handle as specified in the test case data. */
+    switch( handle_construction )
+    {
+        case INVALID_HANDLE_0:
+            invalid_handle = 0;
+            break;
+        case INVALID_HANDLE_UNOPENED:
+            /* We can't easily construct a handle that's never been opened
+             * without knowing how the implementation constructs handle
+             * values. The current test code assumes that valid handles
+             * are in a range between 1 and some maximum. */
+            if( valid_handle == 1 )
+                invalid_handle = 2;
+            else
+                invalid_handle = valid_handle - 1;
+            break;
+        case INVALID_HANDLE_CLOSED:
+            PSA_ASSERT( psa_import_key( &attributes,
+                                        material, sizeof( material ),
+                                        &invalid_handle ) );
+            PSA_ASSERT( psa_destroy_key( invalid_handle ) );
+            break;
+        case INVALID_HANDLE_HUGE:
+            invalid_handle = (psa_key_handle_t) ( -1 );
+            break;
+        default:
+            TEST_ASSERT( ! "unknown handle construction" );
+    }
+
+    /* Attempt to use the invalid handle. */
+    TEST_EQUAL( psa_get_key_attributes( invalid_handle, &attributes ),
+                usage_status );
+    TEST_EQUAL( psa_close_key( invalid_handle ), close_status );
+    TEST_EQUAL( psa_destroy_key( invalid_handle ), close_status );
 
     /* After all this, check that the original handle is intact. */
-    PSA_ASSERT( psa_get_key_attributes( handle1, &attributes ) );
+    PSA_ASSERT( psa_get_key_attributes( valid_handle, &attributes ) );
     TEST_EQUAL( psa_get_key_type( &attributes ), PSA_KEY_TYPE_RAW_DATA );
     TEST_EQUAL( psa_get_key_bits( &attributes ),
                 PSA_BYTES_TO_BITS( sizeof( material ) ) );
-    PSA_ASSERT( psa_close_key( handle1 ) );
+    PSA_ASSERT( psa_close_key( valid_handle ) );
 
 exit:
     PSA_DONE( );
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index 20789e6..3307849 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -272,7 +272,7 @@
 
 RSA PKCS1 Decrypt #1 (Verify)
 depends_on:MBEDTLS_PKCS1_V15
-mbedtls_rsa_pkcs1_decrypt:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404fea284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":MBEDTLS_RSA_PKCS_V15:2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":1000:"4E636AF98E40F3ADCFCCB698F4E80B9F":0
+mbedtls_rsa_pkcs1_decrypt:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404fea284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":MBEDTLS_RSA_PKCS_V15:2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":32:"4E636AF98E40F3ADCFCCB698F4E80B9F":0
 
 RSA PKCS1 Encrypt #2 (Data too large)
 depends_on:MBEDTLS_PKCS1_V15
@@ -280,7 +280,7 @@
 
 RSA PKCS1 Decrypt #2 (Data too small)
 depends_on:MBEDTLS_PKCS1_V15
-mbedtls_rsa_pkcs1_decrypt:"deadbeafcafedeadbeeffedcba9876":MBEDTLS_RSA_PKCS_V15:2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":1000:"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_ERR_RSA_PRIVATE_FAILED + MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_rsa_pkcs1_decrypt:"deadbeafcafedeadbeeffedcba9876":MBEDTLS_RSA_PKCS_V15:2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":32:"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_ERR_RSA_PRIVATE_FAILED + MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 RSA PKCS1 Decrypt #4 (Output buffer too small)
 depends_on:MBEDTLS_PKCS1_V15
diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function
index 89c84e8..d4acc2d 100644
--- a/tests/suites/test_suite_rsa.function
+++ b/tests/suites/test_suite_rsa.function
@@ -472,8 +472,8 @@
                              char * input_N, int radix_E, char * input_E,
                              data_t * result_hex_str, int result )
 {
-    unsigned char hash_result[1000];
-    unsigned char output[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
     mbedtls_mpi N, P, Q, E;
     rnd_pseudo_info rnd_info;
@@ -482,8 +482,8 @@
     mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
 
-    memset( hash_result, 0x00, 1000 );
-    memset( output, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
+    memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
@@ -522,14 +522,14 @@
                                char * input_N, int radix_E, char * input_E,
                                data_t * result_str, int result )
 {
-    unsigned char hash_result[1000];
+    unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context ctx;
 
     mbedtls_mpi N, E;
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
-    memset( hash_result, 0x00, 1000 );
+    memset( hash_result, 0x00, sizeof( hash_result ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -557,7 +557,7 @@
                          int radix_N, char * input_N, int radix_E,
                          char * input_E, data_t * result_hex_str )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
     mbedtls_mpi N, P, Q, E;
     rnd_pseudo_info rnd_info;
@@ -566,7 +566,7 @@
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P );
     mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
@@ -593,7 +593,7 @@
     if( padding_mode == MBEDTLS_RSA_PKCS_V15 )
     {
         int res;
-        memset( output, 0x00, 1000 );
+        memset( output, 0x00, sizeof( output) );
 
         res = mbedtls_rsa_rsaes_pkcs1_v15_encrypt( &ctx,
                     &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE,
@@ -627,7 +627,7 @@
                            char * input_N, int radix_E, char * input_E,
                            data_t * result_str, int correct )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
 
     mbedtls_mpi N, E;
@@ -688,7 +688,7 @@
                                 int radix_E, char * input_E,
                                 data_t * result_hex_str, int result )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
     rnd_pseudo_info rnd_info;
 
@@ -698,7 +698,7 @@
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -729,14 +729,14 @@
                                 int radix_E, char * input_E,
                                 data_t * result_hex_str, int result )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx;
 
     mbedtls_mpi N, E;
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -769,7 +769,7 @@
                                 int max_output, data_t * result_hex_str,
                                 int result )
 {
-    unsigned char output[1000];
+    unsigned char output[32];
     mbedtls_rsa_context ctx;
     size_t output_len;
     rnd_pseudo_info rnd_info;
@@ -780,7 +780,7 @@
 
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
 
 
@@ -815,7 +815,7 @@
                          char * input_N, int radix_E, char * input_E,
                          data_t * result_hex_str, int result )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx, ctx2; /* Also test mbedtls_rsa_copy() while at it */
 
     mbedtls_mpi N, E;
@@ -823,7 +823,7 @@
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
     mbedtls_rsa_init( &ctx2, MBEDTLS_RSA_PKCS_V15, 0 );
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
 
     TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
     TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
@@ -847,7 +847,7 @@
 
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx2 ) == 0 );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     TEST_ASSERT( mbedtls_rsa_public( &ctx2, message_str->x, output ) == result );
     if( result == 0 )
     {
@@ -869,7 +869,7 @@
                           char * input_E, data_t * result_hex_str,
                           int result )
 {
-    unsigned char output[1000];
+    unsigned char output[256];
     mbedtls_rsa_context ctx, ctx2; /* Also test mbedtls_rsa_copy() while at it */
     mbedtls_mpi N, P, Q, E;
     rnd_pseudo_info rnd_info;
@@ -896,7 +896,7 @@
     /* repeat three times to test updating of blinding values */
     for( i = 0; i < 3; i++ )
     {
-        memset( output, 0x00, 1000 );
+        memset( output, 0x00, sizeof( output ) );
         TEST_ASSERT( mbedtls_rsa_private( &ctx, rnd_pseudo_rand, &rnd_info,
                                   message_str->x, output ) == result );
         if( result == 0 )
@@ -913,7 +913,7 @@
 
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx2 ) == 0 );
 
-    memset( output, 0x00, 1000 );
+    memset( output, 0x00, sizeof( output ) );
     TEST_ASSERT( mbedtls_rsa_private( &ctx2, rnd_pseudo_rand, &rnd_info,
                               message_str->x, output ) == result );
     if( result == 0 )
@@ -1577,11 +1577,11 @@
                              int successive )
 {
     /* Exported buffers */
-    unsigned char bufNe[1000];
-    unsigned char bufPe[1000];
-    unsigned char bufQe[1000];
-    unsigned char bufDe[1000];
-    unsigned char bufEe[1000];
+    unsigned char bufNe[256];
+    unsigned char bufPe[128];
+    unsigned char bufQe[128];
+    unsigned char bufDe[256];
+    unsigned char bufEe[1];
 
     mbedtls_rsa_context ctx;