Merge branch 'development' into dev/yanesca/iotcrypt-942
diff --git a/README.md b/README.md
index 9d34c55..a954a16 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
 
 ## PSA cryptography API
 
-Arm's Platform Security Architecture (PSA) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
+Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
 
-The PSA cryptography API provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.
+The [PSA cryptography API](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.
 
 The design goals of the PSA cryptography API include:
 
@@ -24,17 +24,17 @@
 
 ## Documentation
 
-The Mbed Crypto library is a reference implementation of the PSA cryptography API. Please refer to the PSA Cryptography API documents for an overview of the library's interfaces and a detailed description of the types, macros and functions that it provides.
+The Mbed Crypto library implements both the legacy Mbed TLS interfaces to cryptographic primitives (`mbedtls_xxx`) and the new PSA Cryptography interfaces (`psa_xxx`).
+
+Documentation for the Mbed TLS interfaces in the default library configuration is available as part of the [Mbed TLS documentation](https://tls.mbed.org/api/).
+
+For the PSA interfaces, please refer to the PSA Cryptography API documents linked from the [PSA cryptography interfaces documentation portal](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) for an overview of the library's interfaces and a detailed description of the types, macros and functions that it provides. The API reference is available in [PDF](https://armmbed.github.io/mbed-crypto/PSA_Cryptography_API_Specification.pdf) and [HTML](https://armmbed.github.io/mbed-crypto/html/index.html) formats.
 
 There are currently a few deviations where the library does not yet implement the latest version of the specification. Please refer to the [compliance issues on Github](https://github.com/ARMmbed/mbed-crypto/labels/compliance) for an up-to-date list.
 
-### PSA Cryptography API
-
-You can read the [complete PSA cryptography API specification as a PDF document](https://github.com/ARMmbed/mbed-crypto/raw/psa-crypto-api/docs/PSA_Cryptography_API_Specification.pdf). The API reference is also available in [HTML format](https://armmbed.github.io/mbed-crypto/html/index.html).
-
 ### Browsable library documentation
 
-To generate a local copy of the library documentation in HTML format:
+To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:
 
 1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. We use version 1.8.11 but slightly older or more recent versions should work.
 1. Run `make apidoc`.
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index 1a76111..1c6683f 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -75,6 +75,7 @@
 #define MBEDTLS_ASN1_OCTET_STRING            0x04
 #define MBEDTLS_ASN1_NULL                    0x05
 #define MBEDTLS_ASN1_OID                     0x06
+#define MBEDTLS_ASN1_ENUMERATED              0x0A
 #define MBEDTLS_ASN1_UTF8_STRING             0x0C
 #define MBEDTLS_ASN1_SEQUENCE                0x10
 #define MBEDTLS_ASN1_SET                     0x11
@@ -254,14 +255,33 @@
  *              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 );
 
 /**
+ * \brief       Retrieve an enumerated ASN.1 tag and its value.
+ *              Updates the pointer to immediately behind the full 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
+ *              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.
+ * \return      An ASN.1 error code if the input does not start with
+ *              a valid ASN.1 ENUMERATED.
+ * \return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ *              not fit in an \c int.
+ */
+int mbedtls_asn1_get_enum( unsigned char **p,
+                           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.
  *
@@ -367,8 +387,6 @@
  * \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,
diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h
index 9824146..0bce28e 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -193,6 +193,21 @@
 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
 
 /**
+ * \brief           Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
+ *                  in ASN.1 format.
+ *
+ * \note            This function works backwards in data buffer.
+ *
+ * \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.
+ *
+ * \return          The number of bytes written to \p p on success.
+ * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
+
+/**
  * \brief           Write a string in ASN.1 format using a specific
  *                  string encoding tag.
 
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 5075dfd..e7e4d13 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -140,17 +140,20 @@
     return( 0 );
 }
 
-int mbedtls_asn1_get_int( unsigned char **p,
-                  const unsigned char *end,
-                  int *val )
+static int asn1_get_tagged_int( unsigned char **p,
+                                const unsigned char *end,
+                                int tag, int *val )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
         return( ret );
 
-    /* len==0 is malformed (0 must be represented as 020100). */
+    /*
+     * len==0 is malformed (0 must be represented as 020100 for INTEGER,
+     * or 0A0100 for ENUMERATED tags
+     */
     if( len == 0 )
         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
     /* This is a cryptography library. Reject negative integers. */
@@ -181,6 +184,20 @@
     return( 0 );
 }
 
+int mbedtls_asn1_get_int( unsigned char **p,
+                          const unsigned char *end,
+                          int *val )
+{
+    return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
+}
+
+int mbedtls_asn1_get_enum( unsigned char **p,
+                           const unsigned char *end,
+                           int *val )
+{
+    return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
+}
+
 #if defined(MBEDTLS_BIGNUM_C)
 int mbedtls_asn1_get_mpi( unsigned char **p,
                   const unsigned char *end,
diff --git a/library/asn1write.c b/library/asn1write.c
index 262d0bf..503db93 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -232,7 +232,7 @@
     return( (int) len );
 }
 
-int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
@@ -256,11 +256,21 @@
     }
 
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
 
     return( (int) len );
 }
 
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+    return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
+}
+
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
+{
+    return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
+}
+
 int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
     const char *text, size_t text_len )
 {
diff --git a/library/entropy.c b/library/entropy.c
index ad6de23..102f9f1 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -328,7 +328,8 @@
 
 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
 {
-    int ret, count = 0, i, done;
+    int ret, count = 0, i, thresholds_reached;
+    size_t strong_size;
     mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
@@ -366,12 +367,17 @@
         if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
             goto exit;
 
-        done = 1;
+        thresholds_reached = 1;
+        strong_size = 0;
         for( i = 0; i < ctx->source_count; i++ )
+        {
             if( ctx->source[i].size < ctx->source[i].threshold )
-                done = 0;
+                thresholds_reached = 0;
+            if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+                strong_size += ctx->source[i].size;
+        }
     }
-    while( ! done );
+    while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE );
 
     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
 
diff --git a/tests/scripts/test_psa_constant_names.py b/tests/scripts/test_psa_constant_names.py
index 724f8d9..8931987 100755
--- a/tests/scripts/test_psa_constant_names.py
+++ b/tests/scripts/test_psa_constant_names.py
@@ -8,6 +8,7 @@
 """
 
 import argparse
+from collections import namedtuple
 import itertools
 import os
 import platform
@@ -60,12 +61,15 @@
                 from exc_value
 
 class Inputs:
+    # pylint: disable=too-many-instance-attributes
     """Accumulate information about macros to test.
+
     This includes macro names as well as information about their arguments
     when applicable.
     """
 
     def __init__(self):
+        self.all_declared = set()
         # Sets of names per type
         self.statuses = set(['PSA_SUCCESS'])
         self.algorithms = set(['0xffffffff'])
@@ -86,11 +90,30 @@
         self.table_by_prefix = {
             'ERROR': self.statuses,
             'ALG': self.algorithms,
-            'CURVE': self.ecc_curves,
-            'GROUP': self.dh_groups,
+            'ECC_CURVE': self.ecc_curves,
+            'DH_GROUP': self.dh_groups,
             'KEY_TYPE': self.key_types,
             'KEY_USAGE': self.key_usage_flags,
         }
+        # Test functions
+        self.table_by_test_function = {
+            # Any function ending in _algorithm also gets added to
+            # self.algorithms.
+            'key_type': [self.key_types],
+            'ecc_key_types': [self.ecc_curves],
+            'dh_key_types': [self.dh_groups],
+            'hash_algorithm': [self.hash_algorithms],
+            'mac_algorithm': [self.mac_algorithms],
+            'cipher_algorithm': [],
+            'hmac_algorithm': [self.mac_algorithms],
+            'aead_algorithm': [self.aead_algorithms],
+            'key_derivation_algorithm': [self.kdf_algorithms],
+            'key_agreement_algorithm': [self.ka_algorithms],
+            'asymmetric_signature_algorithm': [],
+            'asymmetric_signature_wildcard': [self.algorithms],
+            'asymmetric_encryption_algorithm': [],
+            'other_algorithm': [],
+        }
         # macro name -> list of argument names
         self.argspecs = {}
         # argument name -> list of values
@@ -99,8 +122,20 @@
             'tag_length': ['1', '63'],
         }
 
+    def get_names(self, type_word):
+        """Return the set of known names of values of the given type."""
+        return {
+            'status': self.statuses,
+            'algorithm': self.algorithms,
+            'ecc_curve': self.ecc_curves,
+            'dh_group': self.dh_groups,
+            'key_type': self.key_types,
+            'key_usage': self.key_usage_flags,
+        }[type_word]
+
     def gather_arguments(self):
         """Populate the list of values for macro arguments.
+
         Call this after parsing all the inputs.
         """
         self.arguments_for['hash_alg'] = sorted(self.hash_algorithms)
@@ -118,6 +153,7 @@
 
     def distribute_arguments(self, name):
         """Generate macro calls with each tested argument set.
+
         If name is a macro without arguments, just yield "name".
         If name is a macro with arguments, yield a series of
         "name(arg1,...,argN)" where each argument takes each possible
@@ -145,6 +181,9 @@
         except BaseException as e:
             raise Exception('distribute_arguments({})'.format(name)) from e
 
+    def generate_expressions(self, names):
+        return itertools.chain(*map(self.distribute_arguments, names))
+
     _argument_split_re = re.compile(r' *, *')
     @classmethod
     def _argument_split(cls, arguments):
@@ -154,7 +193,7 @@
     # Groups: 1=macro name, 2=type, 3=argument list (optional).
     _header_line_re = \
         re.compile(r'#define +' +
-                   r'(PSA_((?:KEY_)?[A-Z]+)_\w+)' +
+                   r'(PSA_((?:(?:DH|ECC|KEY)_)?[A-Z]+)_\w+)' +
                    r'(?:\(([^\n()]*)\))?')
     # Regex of macro names to exclude.
     _excluded_name_re = re.compile(r'_(?:GET|IS|OF)_|_(?:BASE|FLAG|MASK)\Z')
@@ -167,10 +206,6 @@
         # Auxiliary macro whose name doesn't fit the usual patterns for
         # auxiliary macros.
         'PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE',
-        # PSA_ALG_ECDH and PSA_ALG_FFDH are excluded for now as the script
-        # currently doesn't support them.
-        'PSA_ALG_ECDH',
-        'PSA_ALG_FFDH',
         # Deprecated aliases.
         'PSA_ERROR_UNKNOWN_ERROR',
         'PSA_ERROR_OCCUPIED_SLOT',
@@ -184,6 +219,7 @@
         if not m:
             return
         name = m.group(1)
+        self.all_declared.add(name)
         if re.search(self._excluded_name_re, name) or \
            name in self._excluded_names:
             return
@@ -200,26 +236,34 @@
             for line in lines:
                 self.parse_header_line(line)
 
+    _macro_identifier_re = r'[A-Z]\w+'
+    def generate_undeclared_names(self, expr):
+        for name in re.findall(self._macro_identifier_re, expr):
+            if name not in self.all_declared:
+                yield name
+
+    def accept_test_case_line(self, function, argument):
+        #pylint: disable=unused-argument
+        undeclared = list(self.generate_undeclared_names(argument))
+        if undeclared:
+            raise Exception('Undeclared names in test case', undeclared)
+        return True
+
     def add_test_case_line(self, function, argument):
         """Parse a test case data line, looking for algorithm metadata tests."""
+        sets = []
         if function.endswith('_algorithm'):
-            # As above, ECDH and FFDH algorithms are excluded for now.
-            # Support for them will be added in the future.
-            if 'ECDH' in argument or 'FFDH' in argument:
-                return
-            self.algorithms.add(argument)
-            if function == 'hash_algorithm':
-                self.hash_algorithms.add(argument)
-            elif function in ['mac_algorithm', 'hmac_algorithm']:
-                self.mac_algorithms.add(argument)
-            elif function == 'aead_algorithm':
-                self.aead_algorithms.add(argument)
-        elif function == 'key_type':
-            self.key_types.add(argument)
-        elif function == 'ecc_key_types':
-            self.ecc_curves.add(argument)
-        elif function == 'dh_key_types':
-            self.dh_groups.add(argument)
+            sets.append(self.algorithms)
+            if function == 'key_agreement_algorithm' and \
+               argument.startswith('PSA_ALG_KEY_AGREEMENT('):
+                # We only want *raw* key agreement algorithms as such, so
+                # exclude ones that are already chained with a KDF.
+                # Keep the expression as one to test as an algorithm.
+                function = 'other_algorithm'
+        sets += self.table_by_test_function[function]
+        if self.accept_test_case_line(function, argument):
+            for s in sets:
+                s.add(argument)
 
     # Regex matching a *.data line containing a test function call and
     # its arguments. The actual definition is partly positional, but this
@@ -233,9 +277,9 @@
                 if m:
                     self.add_test_case_line(m.group(1), m.group(2))
 
-def gather_inputs(headers, test_suites):
+def gather_inputs(headers, test_suites, inputs_class=Inputs):
     """Read the list of inputs to test psa_constant_names with."""
-    inputs = Inputs()
+    inputs = inputs_class()
     for header in headers:
         inputs.parse_header(header)
     for test_cases in test_suites:
@@ -252,8 +296,10 @@
     except OSError:
         pass
 
-def run_c(options, type_word, names):
-    """Generate and run a program to print out numerical values for names."""
+def run_c(type_word, expressions, include_path=None, keep_c=False):
+    """Generate and run a program to print out numerical values for expressions."""
+    if include_path is None:
+        include_path = []
     if type_word == 'status':
         cast_to = 'long'
         printf_format = '%ld'
@@ -278,18 +324,18 @@
 int main(void)
 {
 ''')
-        for name in names:
+        for expr in expressions:
             c_file.write('    printf("{}\\n", ({}) {});\n'
-                         .format(printf_format, cast_to, name))
+                         .format(printf_format, cast_to, expr))
         c_file.write('''    return 0;
 }
 ''')
         c_file.close()
         cc = os.getenv('CC', 'cc')
         subprocess.check_call([cc] +
-                              ['-I' + dir for dir in options.include] +
+                              ['-I' + dir for dir in include_path] +
                               ['-o', exe_name, c_name])
-        if options.keep_c:
+        if keep_c:
             sys.stderr.write('List of {} tests kept at {}\n'
                              .format(type_word, c_name))
         else:
@@ -302,76 +348,101 @@
 NORMALIZE_STRIP_RE = re.compile(r'\s+')
 def normalize(expr):
     """Normalize the C expression so as not to care about trivial differences.
+
     Currently "trivial differences" means whitespace.
     """
-    expr = re.sub(NORMALIZE_STRIP_RE, '', expr, len(expr))
-    return expr.strip().split('\n')
+    return re.sub(NORMALIZE_STRIP_RE, '', expr)
 
-def do_test(options, inputs, type_word, names):
-    """Test psa_constant_names for the specified type.
-    Run program on names.
-    Use inputs to figure out what arguments to pass to macros that
-    take arguments.
+def collect_values(inputs, type_word, include_path=None, keep_c=False):
+    """Generate expressions using known macro names and calculate their values.
+
+    Return a list of pairs of (expr, value) where expr is an expression and
+    value is a string representation of its integer value.
     """
-    names = sorted(itertools.chain(*map(inputs.distribute_arguments, names)))
-    values = run_c(options, type_word, names)
-    output = subprocess.check_output([options.program, type_word] + values)
-    outputs = output.decode('ascii').strip().split('\n')
-    errors = [(type_word, name, value, output)
-              for (name, value, output) in zip(names, values, outputs)
-              if normalize(name) != normalize(output)]
-    return len(names), errors
+    names = inputs.get_names(type_word)
+    expressions = sorted(inputs.generate_expressions(names))
+    values = run_c(type_word, expressions,
+                   include_path=include_path, keep_c=keep_c)
+    return expressions, values
 
-def report_errors(errors):
-    """Describe each case where the output is not as expected."""
-    for type_word, name, value, output in errors:
-        print('For {} "{}", got "{}" (value: {})'
-              .format(type_word, name, output, value))
+class Tests:
+    """An object representing tests and their results."""
 
-def run_tests(options, inputs):
-    """Run psa_constant_names on all the gathered inputs.
-    Return a tuple (count, errors) where count is the total number of inputs
-    that were tested and errors is the list of cases where the output was
-    not as expected.
-    """
-    count = 0
-    errors = []
-    for type_word, names in [('status', inputs.statuses),
-                             ('algorithm', inputs.algorithms),
-                             ('ecc_curve', inputs.ecc_curves),
-                             ('dh_group', inputs.dh_groups),
-                             ('key_type', inputs.key_types),
-                             ('key_usage', inputs.key_usage_flags)]:
-        c, e = do_test(options, inputs, type_word, names)
-        count += c
-        errors += e
-    return count, errors
+    Error = namedtuple('Error',
+                       ['type', 'expression', 'value', 'output'])
+
+    def __init__(self, options):
+        self.options = options
+        self.count = 0
+        self.errors = []
+
+    def run_one(self, inputs, type_word):
+        """Test psa_constant_names for the specified type.
+
+        Run the program on the names for this type.
+        Use the inputs to figure out what arguments to pass to macros that
+        take arguments.
+        """
+        expressions, values = collect_values(inputs, type_word,
+                                             include_path=self.options.include,
+                                             keep_c=self.options.keep_c)
+        output = subprocess.check_output([self.options.program, type_word] +
+                                         values)
+        outputs = output.decode('ascii').strip().split('\n')
+        self.count += len(expressions)
+        for expr, value, output in zip(expressions, values, outputs):
+            if normalize(expr) != normalize(output):
+                self.errors.append(self.Error(type=type_word,
+                                              expression=expr,
+                                              value=value,
+                                              output=output))
+
+    def run_all(self, inputs):
+        """Run psa_constant_names on all the gathered inputs."""
+        for type_word in ['status', 'algorithm', 'ecc_curve', 'dh_group',
+                          'key_type', 'key_usage']:
+            self.run_one(inputs, type_word)
+
+    def report(self, out):
+        """Describe each case where the output is not as expected.
+
+        Write the errors to ``out``.
+        Also write a total.
+        """
+        for error in self.errors:
+            out.write('For {} "{}", got "{}" (value: {})\n'
+                      .format(error.type, error.expression,
+                              error.output, error.value))
+        out.write('{} test cases'.format(self.count))
+        if self.errors:
+            out.write(', {} FAIL\n'.format(len(self.errors)))
+        else:
+            out.write(' PASS\n')
+
+HEADERS = ['psa/crypto.h', 'psa/crypto_extra.h', 'psa/crypto_values.h']
+TEST_SUITES = ['tests/suites/test_suite_psa_crypto_metadata.data']
 
 def main():
     parser = argparse.ArgumentParser(description=globals()['__doc__'])
     parser.add_argument('--include', '-I',
                         action='append', default=['include'],
                         help='Directory for header files')
-    parser.add_argument('--program',
-                        default='programs/psa/psa_constant_names',
-                        help='Program to test')
     parser.add_argument('--keep-c',
                         action='store_true', dest='keep_c', default=False,
                         help='Keep the intermediate C file')
     parser.add_argument('--no-keep-c',
                         action='store_false', dest='keep_c',
                         help='Don\'t keep the intermediate C file (default)')
+    parser.add_argument('--program',
+                        default='programs/psa/psa_constant_names',
+                        help='Program to test')
     options = parser.parse_args()
-    headers = [os.path.join(options.include[0], 'psa', h)
-               for h in ['crypto.h', 'crypto_extra.h', 'crypto_values.h']]
-    test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
-    inputs = gather_inputs(headers, test_suites)
-    count, errors = run_tests(options, inputs)
-    report_errors(errors)
-    if errors == []:
-        print('{} test cases PASS'.format(count))
-    else:
-        print('{} test cases, {} FAIL'.format(count, len(errors)))
+    headers = [os.path.join(options.include[0], h) for h in HEADERS]
+    inputs = gather_inputs(headers, TEST_SUITES)
+    tests = Tests(options)
+    tests.run_all(inputs)
+    tests.report(sys.stdout)
+    if tests.errors:
         exit(1)
 
 if __name__ == '__main__':
diff --git a/tests/suites/test_suite_asn1parse.data b/tests/suites/test_suite_asn1parse.data
index 4abae0b..e26f93a 100644
--- a/tests/suites/test_suite_asn1parse.data
+++ b/tests/suites/test_suite_asn1parse.data
@@ -286,6 +286,90 @@
 INTEGER too large for mpi
 get_mpi_too_large:
 
+ENUMERATED 0
+get_enum:"0A0100":"0":0
+
+ENUMERATED 0, extra leading 0
+get_enum:"0A020000":"0":0
+
+ENUMERATED 1
+get_enum:"0A0101":"1":0
+
+ENUMERATED 1, extra leading 0
+get_enum:"0A020001":"1":0
+
+ENUMERATED 0x7f
+get_enum:"0A017f":"7f":0
+
+ENUMERATED 0x80
+get_enum:"0A020080":"80":0
+
+ENUMERATED 0x80, extra leading 0
+get_enum:"0A03000080":"80":0
+
+ENUMERATED 0xff
+get_enum:"0A0200ff":"ff":0
+
+ENUMERATED 0x7fff
+get_enum:"0A027fff":"7fff":0
+
+ENUMERATED 0x12345678
+get_enum:"0A0412345678":"12345678":0
+
+ENUMERATED 0x12345678, extra leading 0
+get_enum:"0A050012345678":"12345678":0
+
+ENUMERATED 0x7fffffff
+get_enum:"0A047fffffff":"7fffffff":0
+
+ENUMERATED 0x7fffffff, extra leading 0
+get_enum:"0A05007fffffff":"7fffffff":0
+
+ENUMERATED 0x80000000
+get_enum:"0A050080000000":"80000000":0
+
+ENUMERATED 0xffffffff
+get_enum:"0A0500ffffffff":"ffffffff":0
+
+ENUMERATED 0x100000000
+get_enum:"0A050100000000":"0100000000":0
+
+ENUMERATED -1
+get_enum:"0A01ff":"-1":0
+
+ENUMERATED -1, extra leading ff
+get_enum:"0A02ffff":"-1":0
+
+ENUMERATED -0x7f
+get_enum:"0A0181":"-7f":0
+
+ENUMERATED -0x80
+get_enum:"0A0180":"-80":0
+
+ENUMERATED -0x81
+get_enum:"0A02ff7f":"-81":0
+
+ENUMERATED -0xff
+get_enum:"0A02ff01":"-ff":0
+
+ENUMERATED -0x100
+get_enum:"0A02ff00":"-100":0
+
+ENUMERATED -0x7fffffff
+get_enum:"0A0480000001":"-7fffffff":0
+
+ENUMERATED -0x80000000
+get_enum:"0A0480000000":"-80000000":0
+
+ENUMERATED -0x80000001
+get_enum:"0A05ff7fffffff":"-80000001":0
+
+ENUMERATED -0xffffffff
+get_enum:"0A05ff00000001":"-ffffffff":0
+
+ENUMERATED -0x100000000
+get_enum:"0A05ff00000000":"-100000000":0
+
 BIT STRING: empty
 get_bitstring:"0300":0:0:MBEDTLS_ERR_ASN1_OUT_OF_DATA:MBEDTLS_ERR_ASN1_INVALID_DATA
 
diff --git a/tests/suites/test_suite_asn1parse.function b/tests/suites/test_suite_asn1parse.function
index defbd01..d747cc2 100644
--- a/tests/suites/test_suite_asn1parse.function
+++ b/tests/suites/test_suite_asn1parse.function
@@ -393,6 +393,49 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void get_enum( const data_t *input,
+               const char *expected_hex, int expected_result )
+{
+    unsigned char *p;
+    long expected_value;
+    int expected_result_for_enum = expected_result;
+    int val;
+    int ret;
+
+    errno = 0;
+    expected_value = strtol( expected_hex, NULL, 16 );
+    if( expected_result == 0 &&
+        ( errno == ERANGE
+#if LONG_MAX > INT_MAX
+          || expected_value > INT_MAX || expected_value < INT_MIN
+#endif
+            ) )
+    {
+        /* The library returns the dubious error code INVALID_LENGTH
+         * for integers that are out of range. */
+        expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+    if( expected_result == 0 && expected_value < 0 )
+    {
+        /* The library does not support negative INTEGERs and
+         * returns the dubious error code INVALID_LENGTH.
+         * Test that we preserve the historical behavior. If we
+         * decide to change the behavior, we'll also change this test. */
+        expected_result_for_enum = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+
+    p = input->x;
+    ret = mbedtls_asn1_get_enum( &p, input->x + input->len, &val );
+    TEST_EQUAL( ret, expected_result_for_enum );
+    if( ret == 0 )
+    {
+        TEST_EQUAL( val, expected_value );
+        TEST_ASSERT( p == input->x + input->len );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */
 void get_mpi_too_large( )
 {
diff --git a/tests/suites/test_suite_asn1write.data b/tests/suites/test_suite_asn1write.data
index fd589fb..7f5f536 100644
--- a/tests/suites/test_suite_asn1write.data
+++ b/tests/suites/test_suite_asn1write.data
@@ -49,6 +49,48 @@
 ASN.1 Write int 2147483647
 mbedtls_asn1_write_int:0x7fffffff:"02047fffffff"
 
+ASN.1 Write enum 0
+mbedtls_asn1_write_enum:0:"0A0100"
+
+ASN.1 Write enum 1
+mbedtls_asn1_write_enum:1:"0A0101"
+
+ASN.1 Write enum 127
+mbedtls_asn1_write_enum:0x7f:"0A017f"
+
+ASN.1 Write enum 128
+mbedtls_asn1_write_enum:0x80:"0A020080"
+
+ASN.1 Write enum 255
+mbedtls_asn1_write_enum:0xff:"0A0200ff"
+
+ASN.1 Write enum 256
+mbedtls_asn1_write_enum:0x100:"0A020100"
+
+ASN.1 Write enum 32767
+mbedtls_asn1_write_enum:0x7fff:"0A027fff"
+
+ASN.1 Write enum 32768
+mbedtls_asn1_write_enum:0x8000:"0A03008000"
+
+ASN.1 Write enum 65535
+mbedtls_asn1_write_enum:0xffff:"0A0300ffff"
+
+ASN.1 Write enum 65536
+mbedtls_asn1_write_enum:0x10000:"0A03010000"
+
+ASN.1 Write enum 8388607
+mbedtls_asn1_write_enum:0x7fffff:"0A037fffff"
+
+ASN.1 Write enum 8388608
+mbedtls_asn1_write_enum:0x800000:"0A0400800000"
+
+ASN.1 Write enum 0x12345678
+mbedtls_asn1_write_enum:0x12345678:"0A0412345678"
+
+ASN.1 Write enum 2147483647
+mbedtls_asn1_write_enum:0x7fffffff:"0A047fffffff"
+
 #ASN.1 Write mpi 0
 #mbedtls_asn1_write_mpi:"00":"020100"
 
diff --git a/tests/suites/test_suite_asn1write.function b/tests/suites/test_suite_asn1write.function
index b69f6b5..21465c7 100644
--- a/tests/suites/test_suite_asn1write.function
+++ b/tests/suites/test_suite_asn1write.function
@@ -117,6 +117,27 @@
 }
 /* END_CASE */
 
+
+/* BEGIN_CASE */
+void mbedtls_asn1_write_enum( 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_enum( &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 )
 {
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
index 11ced64..b2d20b4 100644
--- a/tests/suites/test_suite_entropy.data
+++ b/tests/suites/test_suite_entropy.data
@@ -1,45 +1,66 @@
 Create NV seed_file
 nv_seed_file_create:
 
-Entropy write/update seed file [#1]
+Entropy write/update seed file: good
 entropy_seed_file:"data_files/entropy_seed":0
 
-Entropy write/update seed file [#2]
+Entropy write/update seed file: nonexistent
 entropy_seed_file:"no_such_dir/file":MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
 
+Entropy no sources
+entropy_no_sources:
+
 Entropy too many sources
 entropy_too_many_sources:
 
-Entropy output length #1
+Entropy output length: 0
 entropy_func_len:0:0
 
-Entropy output length #2
+Entropy output length: 1
 entropy_func_len:1:0
 
-Entropy output length #3
+Entropy output length: 2
 entropy_func_len:2:0
 
-Entropy output length #4
+Entropy output length: 31
 entropy_func_len:31:0
 
-Entropy output length #5
+Entropy output length: 65 > BLOCK_SIZE
 entropy_func_len:65:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Entropy failing source
 entropy_source_fail:"data_files/entropy_seed"
 
-Entropy threshold #1
+Entropy threshold: 16=2*8
 entropy_threshold:16:2:8
 
-Entropy threshold #2
+Entropy threshold: 32=1*32
 entropy_threshold:32:1:32
 
-Entropy threshold #3
+Entropy threshold: 0* never reaches the threshold
 entropy_threshold:16:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
-Entropy threshold #4
+Entropy threshold: 1024 never reached
 entropy_threshold:1024:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
+Entropy calls: no strong
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_WEAK:MBEDTLS_ENTROPY_SOURCE_WEAK:1:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE
+
+Entropy calls: 1 strong, 1*BLOCK_SIZE
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:MBEDTLS_ENTROPY_BLOCK_SIZE:1
+
+Entropy calls: 1 strong, 2*(BLOCK_SIZE/2)
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:2
+
+Entropy calls: 1 strong, BLOCK_SIZE*1
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:1:1:MBEDTLS_ENTROPY_BLOCK_SIZE
+
+Entropy calls: 1 strong, 2*BLOCK_SIZE to reach threshold
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:MBEDTLS_ENTROPY_BLOCK_SIZE+1:MBEDTLS_ENTROPY_BLOCK_SIZE:2
+
+Entropy calls: 2 strong, BLOCK_SIZE/2 each
+entropy_calls:MBEDTLS_ENTROPY_SOURCE_STRONG:MBEDTLS_ENTROPY_SOURCE_WEAK:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:(MBEDTLS_ENTROPY_BLOCK_SIZE+1)/2:2
+
 Check NV seed standard IO
 entropy_nv_seed_std_io:
 
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 0d86ead..9f10a90 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -3,10 +3,19 @@
 #include "mbedtls/entropy_poll.h"
 #include "string.h"
 
-/*
- * Number of calls made to entropy_dummy_source()
- */
-static size_t entropy_dummy_calls;
+typedef enum
+{
+    DUMMY_CONSTANT_LENGTH, /* Output context->length bytes */
+    DUMMY_REQUESTED_LENGTH, /* Output whatever length was requested */
+    DUMMY_FAIL, /* Return an error code */
+} entropy_dummy_instruction;
+
+typedef struct
+{
+    entropy_dummy_instruction instruction;
+    size_t length; /* Length to return for DUMMY_CONSTANT_LENGTH */
+    size_t calls; /* Incremented at each call */
+} entropy_dummy_context;
 
 /*
  * Dummy entropy source
@@ -14,29 +23,28 @@
  * If data is NULL, write exactly the requested length.
  * Otherwise, write the length indicated by data or error if negative
  */
-static int entropy_dummy_source( void *data, unsigned char *output,
+static int entropy_dummy_source( void *arg, unsigned char *output,
                                  size_t len, size_t *olen )
 {
-    entropy_dummy_calls++;
+    entropy_dummy_context *context = arg;
+    ++context->calls;
 
-    if( data == NULL )
-        *olen = len;
-    else
+    switch( context->instruction )
     {
-        int *d = (int *) data;
-
-        if( *d < 0 )
+        case DUMMY_CONSTANT_LENGTH:
+            *olen = context->length;
+            break;
+        case DUMMY_REQUESTED_LENGTH:
+            *olen = len;
+            break;
+        case DUMMY_FAIL:
             return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-        else
-            *olen = *d;
     }
 
     memset( output, 0x2a, *olen );
-
     return( 0 );
 }
 
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
 /*
  * Ability to clear entropy sources to allow testing with just predefined
  * entropy sources. This function or tests depending on it might break if there
@@ -48,11 +56,12 @@
  * This might break memory checks in the future if sources need 'free-ing' then
  * as well.
  */
-void entropy_clear_sources( mbedtls_entropy_context *ctx )
+static void entropy_clear_sources( mbedtls_entropy_context *ctx )
 {
     ctx->source_count = 0;
 }
 
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
 /*
  * NV seed read/write functions that use a buffer instead of a file
  */
@@ -140,10 +149,27 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void entropy_no_sources( )
+{
+    mbedtls_entropy_context ctx;
+    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+    mbedtls_entropy_init( &ctx );
+    entropy_clear_sources( &ctx );
+    TEST_EQUAL( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ),
+                MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+exit:
+    mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void entropy_too_many_sources(  )
 {
     mbedtls_entropy_context ctx;
     size_t i;
+    entropy_dummy_context dummy = {DUMMY_REQUESTED_LENGTH, 0, 0};
 
     mbedtls_entropy_init( &ctx );
 
@@ -152,10 +178,10 @@
      * since we don't know how many sources were automatically added.
      */
     for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ )
-        (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
+        (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, &dummy,
                                            16, MBEDTLS_ENTROPY_SOURCE_WEAK );
 
-    TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
+    TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, &dummy,
                                              16, MBEDTLS_ENTROPY_SOURCE_WEAK )
                  == MBEDTLS_ERR_ENTROPY_MAX_SOURCES );
 
@@ -197,13 +223,13 @@
 void entropy_source_fail( char * path )
 {
     mbedtls_entropy_context ctx;
-    int fail = -1;
     unsigned char buf[16];
+    entropy_dummy_context dummy = {DUMMY_FAIL, 0, 0};
 
     mbedtls_entropy_init( &ctx );
 
     TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
-                                             &fail, 16,
+                                             &dummy, 16,
                                              MBEDTLS_ENTROPY_SOURCE_WEAK )
                  == 0 );
 
@@ -225,30 +251,87 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
+/* BEGIN_CASE */
 void entropy_threshold( int threshold, int chunk_size, int result )
 {
     mbedtls_entropy_context ctx;
+    entropy_dummy_context strong =
+        {DUMMY_CONSTANT_LENGTH, MBEDTLS_ENTROPY_BLOCK_SIZE, 0};
+    entropy_dummy_context weak = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
     int ret;
 
     mbedtls_entropy_init( &ctx );
+    entropy_clear_sources( &ctx );
 
+    /* Set strong source that reaches its threshold immediately and
+     * a weak source whose threshold is a test parameter. */
     TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
-                                     &chunk_size, threshold,
+                                     &strong, 1,
+                                     MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
+    TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+                                     &weak, threshold,
                                      MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 );
 
-    entropy_dummy_calls = 0;
     ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
 
     if( result >= 0 )
     {
         TEST_ASSERT( ret == 0 );
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
-        // Two times as much calls due to the NV seed update
+        /* If the NV seed functionality is enabled, there are two entropy
+         * updates: before and after updating the NV seed. */
         result *= 2;
 #endif
-        TEST_ASSERT( entropy_dummy_calls == (size_t) result );
+        TEST_ASSERT( weak.calls == (size_t) result );
+    }
+    else
+    {
+        TEST_ASSERT( ret == result );
+    }
+
+exit:
+    mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void entropy_calls( int strength1, int strength2,
+                    int threshold, int chunk_size,
+                    int result )
+{
+    /*
+     * if result >= 0: result = expected number of calls to source 1
+     * if result < 0: result = expected return code from mbedtls_entropy_func()
+     */
+
+    mbedtls_entropy_context ctx;
+    entropy_dummy_context dummy1 = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
+    entropy_dummy_context dummy2 = {DUMMY_CONSTANT_LENGTH, chunk_size, 0};
+    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
+    int ret;
+
+    mbedtls_entropy_init( &ctx );
+    entropy_clear_sources( &ctx );
+
+    TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+                                             &dummy1, threshold,
+                                             strength1 ) == 0 );
+    TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
+                                             &dummy2, threshold,
+                                             strength2 ) == 0 );
+
+    ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
+
+    if( result >= 0 )
+    {
+        TEST_ASSERT( ret == 0 );
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+        /* If the NV seed functionality is enabled, there are two entropy
+         * updates: before and after updating the NV seed. */
+        result *= 2;
+#endif
+        TEST_ASSERT( dummy1.calls == (size_t) result );
     }
     else
     {
diff --git a/tests/suites/test_suite_memory_buffer_alloc.data b/tests/suites/test_suite_memory_buffer_alloc.data
index d59f113..d780fd4 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.data
+++ b/tests/suites/test_suite_memory_buffer_alloc.data
@@ -16,8 +16,8 @@
 Memory buffer alloc - Out of Memory test
 memory_buffer_alloc_oom_test:
 
-Memory buffer small buffer
-memory_buffer_small_buffer:
+Memory buffer: heap too small (header verification should fail)
+memory_buffer_heap_too_small:
 
-Memory buffer underalloc
+Memory buffer: attempt to allocate SIZE_MAX
 memory_buffer_underalloc:
diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function
index bc03436..cc884c2 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.function
+++ b/tests/suites/test_suite_memory_buffer_alloc.function
@@ -29,7 +29,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes,
                                      int d_bytes, int free_a, int free_b,
                                      int free_c, int free_d, int e_bytes,
@@ -39,8 +39,11 @@
     unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_d = NULL,
                     *ptr_e = NULL, *ptr_f = NULL;
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     size_t reported_blocks;
-    size_t allocated_bytes = 0, reported_bytes;
+    size_t reported_bytes;
+#endif
+    size_t allocated_bytes = 0;
 
     mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
 
@@ -78,8 +81,10 @@
         allocated_bytes += d_bytes * sizeof(char);
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
 
     if( free_a )
     {
@@ -117,8 +122,10 @@
         allocated_bytes -= d_bytes * sizeof(char);
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
 
     if( e_bytes > 0 )
     {
@@ -178,8 +185,10 @@
         ptr_f = NULL;
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == 0 );
+#endif
 
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
@@ -188,12 +197,14 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 void memory_buffer_alloc_oom_test(  )
 {
     unsigned char buf[1024];
     unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL;
+#if defined(MBEDTLS_MEMORY_DEBUG)
     size_t reported_blocks, reported_bytes;
+#endif
 
     (void)ptr_c;
 
@@ -210,8 +221,10 @@
     ptr_c = mbedtls_calloc( 431, sizeof(char) );
     TEST_ASSERT( ptr_c == NULL );
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes >= 864 && reported_bytes <= sizeof(buf) );
+#endif
 
     mbedtls_free( ptr_a );
     ptr_a = NULL;
@@ -221,8 +234,10 @@
     ptr_b = NULL;
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == 0 );
+#endif
 
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
@@ -231,17 +246,20 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
-void memory_buffer_small_buffer( )
+/* BEGIN_CASE */
+void memory_buffer_heap_too_small( )
 {
     unsigned char buf[1];
 
     mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+    /* With MBEDTLS_MEMORY_DEBUG enabled, this prints a message
+     * "FATAL: verification of first header failed".
+     */
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() != 0 );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 void memory_buffer_underalloc( )
 {
     unsigned char buf[100];
diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data
index e989895..9cdee03 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.data
+++ b/tests/suites/test_suite_psa_crypto_metadata.data
@@ -262,6 +262,26 @@
 depends_on:MBEDTLS_SHA256_C
 key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):ALG_IS_HKDF
 
+Key derivation: HKDF using SHA-384
+depends_on:MBEDTLS_SHA512_C
+key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_384 ):ALG_IS_HKDF
+
+Key derivation: TLS 1.2 PRF using SHA-256
+depends_on:MBEDTLS_SHA256_C
+key_derivation_algorithm:PSA_ALG_TLS12_PRF( PSA_ALG_SHA_256 ):ALG_IS_TLS12_PRF
+
+Key derivation: TLS 1.2 PRF using SHA-384
+depends_on:MBEDTLS_SHA512_C
+key_derivation_algorithm:PSA_ALG_TLS12_PRF( PSA_ALG_SHA_384 ):ALG_IS_TLS12_PRF
+
+Key derivation: TLS 1.2 PSK-to-MS using SHA-256
+depends_on:MBEDTLS_SHA256_C
+key_derivation_algorithm:PSA_ALG_TLS12_PSK_TO_MS( PSA_ALG_SHA_256 ):ALG_IS_TLS12_PSK_TO_MS
+
+Key derivation: TLS 1.2 PSK-to-MS using SHA-384
+depends_on:MBEDTLS_SHA512_C
+key_derivation_algorithm:PSA_ALG_TLS12_PSK_TO_MS( PSA_ALG_SHA_384 ):ALG_IS_TLS12_PSK_TO_MS
+
 Key agreement: FFDH, raw output
 depends_on:MBEDTLS_DHM_C
 key_agreement_algorithm:PSA_ALG_FFDH:ALG_IS_FFDH | ALG_IS_RAW_KEY_AGREEMENT:PSA_ALG_FFDH:PSA_ALG_CATEGORY_KEY_DERIVATION
@@ -270,6 +290,10 @@
 depends_on:MBEDTLS_DHM_C
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_FFDH, PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_FFDH:PSA_ALG_FFDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 )
 
+Key agreement: FFDH, HKDF using SHA-384
+depends_on:MBEDTLS_DHM_C
+key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_FFDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_FFDH:PSA_ALG_FFDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 )
+
 Key agreement: ECDH, raw output
 depends_on:MBEDTLS_ECDH_C
 key_agreement_algorithm:PSA_ALG_ECDH:ALG_IS_ECDH | ALG_IS_RAW_KEY_AGREEMENT:PSA_ALG_ECDH:PSA_ALG_CATEGORY_KEY_DERIVATION
@@ -278,6 +302,10 @@
 depends_on:MBEDTLS_ECDH_C
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 )
 
+Key agreement: ECDH, HKDF using SHA-384
+depends_on:MBEDTLS_ECDH_C
+key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 )
+
 Key type: raw data
 key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED
 
diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function
index a9f1b39..3a9347e 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.function
+++ b/tests/suites/test_suite_psa_crypto_metadata.function
@@ -37,6 +37,8 @@
 #define ALG_IS_WILDCARD                 ( 1u << 19 )
 #define ALG_IS_RAW_KEY_AGREEMENT        ( 1u << 20 )
 #define ALG_IS_AEAD_ON_BLOCK_CIPHER     ( 1u << 21 )
+#define ALG_IS_TLS12_PRF                ( 1u << 22 )
+#define ALG_IS_TLS12_PSK_TO_MS          ( 1u << 23 )
 
 /* Flags for key type classification macros. There is a flag for every
  * key type classification macro PSA_KEY_TYPE_IS_xxx except for some that