Merge pull request #287 from gilles-peskine-arm/ctr_drbg-doc-nist-crypto

DRBG documentation improvements
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/psa/crypto.h b/include/psa/crypto.h
index 68a4f65..d3b7522 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -57,7 +57,7 @@
  * algorithms, key types, policies, etc. */
 #include "crypto_types.h"
 
-/** \defgroup API version
+/** \defgroup version API version
  * @{
  */
 
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..4764ca4 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -149,11 +149,18 @@
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
         return( ret );
 
-    if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+    if( len == 0 || ( **p & 0x80 ) != 0 )
+        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+    while( len > 0 && **p == 0 )
+    {
+        ++( *p );
+        --len;
+    }
+    if( len > sizeof( int ) )
         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
 
     *val = 0;
-
     while( len-- > 0 )
     {
         *val = ( *val << 8 ) | **p;
@@ -223,8 +230,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/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/psa_crypto.c b/library/psa_crypto.c
index b9ea00f..e26a7ec 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1579,7 +1579,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 +1592,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 +1609,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 +1889,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 +1905,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:
@@ -5713,6 +5687,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/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/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..c5d9136
--- /dev/null
+++ b/tests/suites/test_suite_asn1parse.data
@@ -0,0 +1,438 @@
+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
+depends_on:SUPPORT_NEGATIVE_INTEGERS
+get_integer:"0200":"":MBEDTLS_ERR_ASN1_INVALID_LENGTH
+
+INTEGER 0
+get_integer:"020100":"0":0
+
+INTEGER 0, extra leading 0
+get_integer:"02020000":"0":0
+
+INTEGER -0
+depends_on:SUPPORT_NEGATIVE_INTEGERS
+get_integer:"020180":"0":0
+
+INTEGER 1
+get_integer:"020101":"1":0:
+
+INTEGER 1, extra leading 0
+get_integer:"02020001":"1":0:
+
+INTEGER -1
+depends_on:SUPPORT_NEGATIVE_INTEGERS
+get_integer:"020181":"-1":0
+
+INTEGER 0x7f
+get_integer:"02017f":"7f":0
+
+INTEGER -0x7f
+depends_on:SUPPORT_NEGATIVE_INTEGERS
+get_integer:"0201ff":"-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 0x123456789abcdef0
+get_integer:"0208123456789abcdef0":"123456789abcdef0":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
+
+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..3bfb1c7
--- /dev/null
+++ b/tests/suites/test_suite_asn1parse.function
@@ -0,0 +1,562 @@
+/* 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 );
+#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 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;
+#endif
+    long expected_value;
+    int expected_result_for_int = expected_result;
+    int expected_result_for_mpi = expected_result;
+    int val;
+    int ret;
+
+#if defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_init( &expected_mpi );
+    mbedtls_mpi_init( &actual_mpi );
+#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
+            ) )
+    {
+        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 )
+    {
+        TEST_ASSERT( mbedtls_mpi_cmp_mpi( &actual_mpi , &expected_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 );
+#endif
+}
+/* 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_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_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..61fb918 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,37 @@
     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;
+
+    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 );
+    return( 1 );
+
+exit:
+    mbedtls_free( loaded );
+    return( 0 );
+}
+
 /* 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 +831,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 +842,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 +868,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 +927,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 +938,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 +954,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 +1005,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 +1017,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 +1027,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 +1072,7 @@
 
 exit:
     PSA_DONE( );
+    counter_reset( );
     psa_purge_storage( );
 }
 /* END_CASE */
@@ -1023,6 +1113,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 +1125,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 +1135,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_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;