Merge pull request #3044 from sbutcher-arm/merge-2.16-sprint27

[baremetal] Update `baremetal` branch with updates from `mbedtls-2.16` branch
diff --git a/ChangeLog b/ChangeLog
index 6ba9a5a..2e9bf11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -63,16 +63,64 @@
    * Reduce RAM consumption during session renegotiation by not storing
      the peer CRT chain and session ticket twice.
 
-= mbed TLS 2.16.x branch released xxxx-xx-xx
+= mbed TLS 2.16.X branch released XXXX-XX-XX
+
+Security
+   * Fix potential memory overread when performing an ECDSA signature
+     operation. The overread only happens with cryptographically low
+     probability (of the order of 2^-n where n is the bitsize of the curve)
+     unless the RNG is broken, and could result in information disclosure or
+     denial of service (application crash or extra resource consumption).
+     Found by Auke Zeilstra and Peter Schwabe, using static analysis.
+   * To avoid a side channel vulnerability when parsing an RSA private key,
+     read all the CRT parameters from the DER structure rather than
+     reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob
+     Brumley. Reported and fix contributed by Jack Lloyd.
+     ARMmbed/mbed-crypto#352
+
+Bugfix
+   * Fix an unchecked call to mbedtls_md() in the x509write module.
+
+= mbed TLS 2.16.4 branch released 2020-01-15
+
+Security
+   * Fix side channel vulnerability in ECDSA. Our bignum implementation is not
+     constant time/constant trace, so side channel attacks can retrieve the
+     blinded value, factor it (as it is smaller than RSA keys and not guaranteed
+     to have only large prime factors), and then, by brute force, recover the
+     key. Reported by Alejandro Cabrera Aldaya and Billy Brumley.
+   * Zeroize local variables in mbedtls_internal_aes_encrypt() and
+     mbedtls_internal_aes_decrypt() before exiting the function. The value of
+     these variables can be used to recover the last round key. To follow best
+     practice and to limit the impact of buffer overread vulnerabilities (like
+     Heartbleed) we need to zeroize them before exiting the function.
+     Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai,
+     Grant Hernandez, and Kevin Butler (University of Florida) and
+     Dave Tian (Purdue University).
+   * Fix side channel vulnerability in ECDSA key generation. Obtaining precise
+     timings on the comparison in the key generation enabled the attacker to
+     learn leading bits of the ephemeral key used during ECDSA signatures and to
+     recover the private key. Reported by Jeremy Dubeuf.
+   * Catch failure of AES functions in mbedtls_ctr_drbg_random(). Uncaught
+     failures could happen with alternative implementations of AES. Bug
+     reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri,
+     Sectra.
 
 Bugfix
    * Remove redundant line for getting the bitlen of a bignum, since the variable
      holding the returned value is overwritten a line after.
      Found by irwir in #2377.
+   * Support mbedtls_hmac_drbg_set_entropy_len() and
+     mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before,
+     the initial seeding always reset the entropy length to the compile-time
+     default.
 
 Changes
    * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()
      from the cipher abstraction layer. Fixes #2198.
+   * Clarify how the interface of the CTR_DRBG and HMAC modules relates to
+     NIST SP 800-90A. In particular CTR_DRBG requires an explicit nonce
+     to achieve a 256-bit strength if MBEDTLS_ENTROPY_FORCE_SHA256 is set.
 
 = mbed TLS 2.16.3 branch released 2019-09-06
 
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index a6126f3..de43cdf 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.16.3 source code documentation
+ * @mainpage mbed TLS v2.16.4 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 3fcc034..5745520 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.16.3"
+PROJECT_NAME           = "mbed TLS v2.16.4"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 1c86072..22b3731 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -184,7 +184,7 @@
  */
 typedef struct mbedtls_mpi
 {
-    int s;              /*!<  integer sign      */
+    int s;              /*!<  Sign: -1 if the mpi is negative, 1 otherwise */
     size_t n;           /*!<  total # of limbs  */
     mbedtls_mpi_uint *p;          /*!<  pointer to limbs  */
 }
@@ -560,6 +560,24 @@
 int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
 
 /**
+ * \brief          Check if an MPI is less than the other in constant time.
+ *
+ * \param X        The left-hand MPI. This must point to an initialized MPI
+ *                 with the same allocated length as Y.
+ * \param Y        The right-hand MPI. This must point to an initialized MPI
+ *                 with the same allocated length as X.
+ * \param ret      The result of the comparison:
+ *                 \c 1 if \p X is less than \p Y.
+ *                 \c 0 if \p X is greater than or equal to \p Y.
+ *
+ * \return         0 on success.
+ * \return         MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of
+ *                 the two input MPIs is not the same.
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+        unsigned *ret );
+
+/**
  * \brief          Compare an MPI with an integer.
  *
  * \param X        The left-hand MPI. This must point to an initialized MPI.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 347a8fa..4ee5920 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -747,6 +747,13 @@
 #define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
 #define MBEDTLS_CIPHER_PADDING_ZEROS
 
+/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ *
+ * Uncomment this macro to use a 128-bit key in the CTR_DRBG module.
+ * By default, CTR_DRBG uses a 256-bit key.
+ */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+
 /**
  * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
  *
@@ -2516,7 +2523,11 @@
  *
  * Enable the CTR_DRBG AES-based random generator.
  * The CTR_DRBG generator uses AES-256 by default.
- * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
+ * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above.
+ *
+ * \note To achieve a 256-bit security strength with CTR_DRBG,
+ *       you must use AES-256 *and* use sufficient entropy.
+ *       See ctr_drbg.h for more details.
  *
  * Module:  library/ctr_drbg.c
  * Caller:
@@ -3434,7 +3445,6 @@
 //#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
 //#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
 //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
-//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY              /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
 
 /* HMAC_DRBG options */
 //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index cc3df7b..e0b5ed9 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -1,7 +1,8 @@
 /**
  * \file ctr_drbg.h
  *
- * \brief    This file contains CTR_DRBG definitions and functions.
+ * \brief    This file contains definitions and functions for the
+ *           CTR_DRBG pseudorandom generator.
  *
  * CTR_DRBG is a standardized way of building a PRNG from a block-cipher
  * in counter mode operation, as defined in <em>NIST SP 800-90A:
@@ -9,13 +10,35 @@
  * Bit Generators</em>.
  *
  * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
- * as the underlying block cipher.
+ * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
+ * as the underlying block cipher, with a derivation function.
+ * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more details.
  *
- *  \warning Using 128-bit keys for CTR_DRBG limits the security of generated
- *  keys and operations that use random values generated to 128-bit security.
+ * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2,
+ * here are the security strengths achieved in typical configuration:
+ * - 256 bits under the default configuration of the library, with AES-256
+ *   and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more.
+ * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
+ *   to 32 or more, and the DRBG is initialized with an explicit
+ *   nonce in the \c custom parameter to mbedtls_ctr_drbg_seed().
+ * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
+ *   between 24 and 47 and the DRBG is not initialized with an explicit
+ *   nonce (see mbedtls_ctr_drbg_seed()).
+ * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
+ *   and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is
+ *   always the case unless it is explicitly set to a different value
+ *   in config.h).
+ *
+ * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to:
+ * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol
+ *   \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time.
+ *   This is the default configuration of the library.
+ * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time.
+ * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time.
  */
 /*
- *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ *  Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -56,9 +79,19 @@
 #define MBEDTLS_CTR_DRBG_BLOCKSIZE          16 /**< The block size used by the cipher. */
 
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-#define MBEDTLS_CTR_DRBG_KEYSIZE            16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE            16
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 16 bytes (128 bits)
+ * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled.
+ */
 #else
-#define MBEDTLS_CTR_DRBG_KEYSIZE            32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
+#define MBEDTLS_CTR_DRBG_KEYSIZE            32
+/**< The key size in bytes used by the cipher.
+ *
+ * Compile-time choice: 32 bytes (256 bits)
+ * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled.
+ */
 #endif
 
 #define MBEDTLS_CTR_DRBG_KEYBITS            ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
@@ -73,21 +106,31 @@
  * \{
  */
 
+/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN
+ *
+ * \brief The amount of entropy used per seed by default, in bytes.
+ */
 #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)
 #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
+/** This is 48 bytes because the entropy module uses SHA-512
+ * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled).
+ */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        48
-/**< The amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
+
+#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+
+/** This is 32 bytes because the entropy module uses SHA-256
+ * (the SHA512 module is disabled or
+ * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled).
  */
-#else
+#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+/** \warning To achieve a 256-bit security strength, you must pass a nonce
+ *           to mbedtls_ctr_drbg_seed().
+ */
+#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        32
-/**< Amount of entropy used per seed by default:
- * <ul><li>48 with SHA-512.</li>
- * <li>32 with SHA-256.</li></ul>
- */
-#endif
-#endif
+#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */
 
 #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)
 #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL    10000
@@ -106,7 +149,7 @@
 
 #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
 #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT     384
-/**< The maximum size of seed or reseed buffer. */
+/**< The maximum size of seed or reseed buffer in bytes. */
 #endif
 
 /* \} name SECTION: Module settings */
@@ -164,17 +207,68 @@
  * \brief               This function seeds and sets up the CTR_DRBG
  *                      entropy source for future reseeds.
  *
- * \note Personalization data can be provided in addition to the more generic
- *       entropy source, to make this instantiation as unique as possible.
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ *   with mbedtls_entropy_init() (which registers the platform's default
+ *   entropy sources).
  *
+ * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
+ * You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
+ *
+ * You can provide a personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ *
+ * \note                The _seed_material_ value passed to the derivation
+ *                      function in the CTR_DRBG Instantiate Process
+ *                      described in NIST SP 800-90A §10.2.1.3.2
+ *                      is the concatenation of the string obtained from
+ *                      calling \p f_entropy and the \p custom string.
+ *                      The origin of the nonce depends on the value of
+ *                      the entropy length relative to the security strength.
+ *                      - If the entropy length is at least 1.5 times the
+ *                        security strength then the nonce is taken from the
+ *                        string obtained with \p f_entropy.
+ *                      - If the entropy length is less than the security
+ *                        strength, then the nonce is taken from \p custom.
+ *                        In this case, for compliance with SP 800-90A,
+ *                        you must pass a unique value of \p custom at
+ *                        each invocation. See SP 800-90A §8.6.7 for more
+ *                        details.
+ */
+#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
+/** \warning            When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than
+ *                      #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the
+ *                      maximum security strength permitted by CTR_DRBG,
+ *                      you must pass a value of \p custom that is a nonce:
+ *                      this value must never be repeated in subsequent
+ *                      runs of the same application or on a different
+ *                      device.
+ */
+#endif
+/**
  * \param ctx           The CTR_DRBG context to seed.
+ *                      It must have been initialized with
+ *                      mbedtls_ctr_drbg_init().
+ *                      After a successful call to mbedtls_ctr_drbg_seed(),
+ *                      you may not call mbedtls_ctr_drbg_seed() again on
+ *                      the same context unless you call
+ *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
+ *                      again first.
  * \param f_entropy     The entropy callback, taking as arguments the
  *                      \p p_entropy context, the buffer to fill, and the
-                        length of the buffer.
- * \param p_entropy     The entropy context.
- * \param custom        Personalization data, that is device-specific
-                        identifiers. Can be NULL.
- * \param len           The length of the personalization data.
+ *                      length of the buffer.
+ *                      \p f_entropy is always called with a buffer size
+ *                      equal to the entropy length.
+ * \param p_entropy     The entropy context to pass to \p f_entropy.
+ * \param custom        The personalization string.
+ *                      This can be \c NULL, in which case the personalization
+ *                      string is empty regardless of the value of \p len.
+ * \param len           The length of the personalization string.
+ *                      This must be at most
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ *                      - #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -197,7 +291,8 @@
  *                      The default value is off.
  *
  * \note                If enabled, entropy is gathered at the beginning of
- *                      every call to mbedtls_ctr_drbg_random_with_add().
+ *                      every call to mbedtls_ctr_drbg_random_with_add()
+ *                      or mbedtls_ctr_drbg_random().
  *                      Only use this if your entropy source has sufficient
  *                      throughput.
  *
@@ -209,18 +304,37 @@
 
 /**
  * \brief               This function sets the amount of entropy grabbed on each
- *                      seed or reseed. The default value is
- *                      #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ *                      seed or reseed.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
+ *
+ * \note                The security strength of CTR_DRBG is bounded by the
+ *                      entropy length. Thus:
+ *                      - When using AES-256
+ *                        (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled,
+ *                        which is the default),
+ *                        \p len must be at least 32 (in bytes)
+ *                        to achieve a 256-bit strength.
+ *                      - When using AES-128
+ *                        (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled)
+ *                        \p len must be at least 16 (in bytes)
+ *                        to achieve a 128-bit strength.
  *
  * \param ctx           The CTR_DRBG context.
- * \param len           The amount of entropy to grab.
+ * \param len           The amount of entropy to grab, in bytes.
+ *                      This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
  */
 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
                                size_t len );
 
 /**
  * \brief               This function sets the reseed interval.
- *                      The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
+ *
+ * The reseed interval is the number of calls to mbedtls_ctr_drbg_random()
+ * or mbedtls_ctr_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
  *
  * \param ctx           The CTR_DRBG context.
  * \param interval      The reseed interval.
@@ -233,8 +347,12 @@
  *                      extracts data from the entropy source.
  *
  * \param ctx           The CTR_DRBG context.
- * \param additional    Additional data to add to the state. Can be NULL.
+ * \param additional    Additional data to add to the state. Can be \c NULL.
  * \param len           The length of the additional data.
+ *                      This must be less than
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ *                      where \c entropy_len is the entropy length
+ *                      configured for the context.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
@@ -246,7 +364,8 @@
  * \brief              This function updates the state of the CTR_DRBG context.
  *
  * \param ctx          The CTR_DRBG context.
- * \param additional   The data to update the state with.
+ * \param additional   The data to update the state with. This must not be
+ *                     \c NULL unless \p add_len is \c 0.
  * \param add_len      Length of \p additional in bytes. This must be at
  *                     most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
  *
@@ -264,14 +383,23 @@
  * \brief   This function updates a CTR_DRBG instance with additional
  *          data and uses it to generate random data.
  *
- * \note    The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
- * \param output_len    The length of the buffer.
- * \param additional    Additional data to update. Can be NULL.
- * \param add_len       The length of the additional data.
+ * \param output_len    The length of the buffer in bytes.
+ * \param additional    Additional data to update. Can be \c NULL, in which
+ *                      case the additional data is empty regardless of
+ *                      the value of \p add_len.
+ * \param add_len       The length of the additional data
+ *                      if \p additional is not \c NULL.
+ *                      This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT
+ *                      and less than
+ *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
+ *                      where \c entropy_len is the entropy length
+ *                      configured for the context.
  *
  * \return    \c 0 on success.
  * \return    #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -284,12 +412,14 @@
 /**
  * \brief   This function uses CTR_DRBG to generate random data.
  *
- * \note    The function automatically reseeds if the reseed counter is exceeded.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
+ *
  *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
- * \param output_len    The length of the buffer.
+ * \param output_len    The length of the buffer in bytes.
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
@@ -336,7 +466,7 @@
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed
  *                      failure.
  */
 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
@@ -350,8 +480,10 @@
  *
  * \return              \c 0 on success.
  * \return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
- * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
- *                      #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ *                      reseed failure.
+ * \return              #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing
+ *                      seed file is too large.
  */
 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
 #endif /* MBEDTLS_FS_IO */
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index f38337a..eec05e4 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -1,10 +1,14 @@
 /**
  * \file hmac_drbg.h
  *
- * \brief HMAC_DRBG (NIST SP 800-90A)
+ * \brief The HMAC_DRBG pseudorandom generator.
+ *
+ * This module implements the HMAC_DRBG pseudorandom generator described
+ * in <em>NIST SP 800-90A: Recommendation for Random Number Generation Using
+ * Deterministic Random Bit Generators</em>.
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2019, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -104,38 +108,72 @@
 } mbedtls_hmac_drbg_context;
 
 /**
- * \brief               HMAC_DRBG context initialization
- *                      Makes the context ready for mbedtls_hmac_drbg_seed(),
- *                      mbedtls_hmac_drbg_seed_buf() or
- *                      mbedtls_hmac_drbg_free().
+ * \brief               HMAC_DRBG context initialization.
  *
- * \param ctx           HMAC_DRBG context to be initialized
+ * This function makes the context ready for mbedtls_hmac_drbg_seed(),
+ * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().
+ *
+ * \param ctx           HMAC_DRBG context to be initialized.
  */
 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
 
 /**
- * \brief               HMAC_DRBG initial seeding
- *                      Seed and setup entropy source for future reseeds.
+ * \brief               HMAC_DRBG initial seeding.
  *
- * \param ctx           HMAC_DRBG context to be seeded
- * \param md_info       MD algorithm to use for HMAC_DRBG
- * \param f_entropy     Entropy callback (p_entropy, buffer to fill, buffer
- *                      length)
- * \param p_entropy     Entropy context
- * \param custom        Personalization data (Device specific identifiers)
- *                      (Can be NULL)
- * \param len           Length of personalization data
+ * Set the initial seed and set up the entropy source for future reseeds.
  *
- * \note                The "security strength" as defined by NIST is set to:
- *                      128 bits if md_alg is SHA-1,
- *                      192 bits if md_alg is SHA-224,
- *                      256 bits if md_alg is SHA-256 or higher.
+ * A typical choice for the \p f_entropy and \p p_entropy parameters is
+ * to use the entropy module:
+ * - \p f_entropy is mbedtls_entropy_func();
+ * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
+ *   with mbedtls_entropy_init() (which registers the platform's default
+ *   entropy sources).
+ *
+ * You can provide a personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ *
+ * \note                By default, the security strength as defined by NIST is:
+ *                      - 128 bits if \p md_info is SHA-1;
+ *                      - 192 bits if \p md_info is SHA-224;
+ *                      - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512.
  *                      Note that SHA-256 is just as efficient as SHA-224.
+ *                      The security strength can be reduced if a smaller
+ *                      entropy length is set with
+ *                      mbedtls_hmac_drbg_set_entropy_len().
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- *                      MBEDTLS_ERR_MD_ALLOC_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ * \note                The default entropy length is the security strength
+ *                      (converted from bits to bytes). You can override
+ *                      it by calling mbedtls_hmac_drbg_set_entropy_len().
+ *
+ * \note                During the initial seeding, this function calls
+ *                      the entropy source to obtain a nonce
+ *                      whose length is half the entropy length.
+ *
+ * \param ctx           HMAC_DRBG context to be seeded.
+ * \param md_info       MD algorithm to use for HMAC_DRBG.
+ * \param f_entropy     The entropy callback, taking as arguments the
+ *                      \p p_entropy context, the buffer to fill, and the
+ *                      length of the buffer.
+ *                      \p f_entropy is always called with a length that is
+ *                      less than or equal to the entropy length.
+ * \param p_entropy     The entropy context to pass to \p f_entropy.
+ * \param custom        The personalization string.
+ *                      This can be \c NULL, in which case the personalization
+ *                      string is empty regardless of the value of \p len.
+ * \param len           The length of the personalization string.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ *                      and also at most
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
+ *                      where \p entropy_len is the entropy length
+ *                      described above.
+ *
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ *                      invalid.
+ * \return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ *                      memory to allocate context data.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if the call to \p f_entropy failed.
  */
 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
                     mbedtls_md_handle_t md_info,
@@ -146,100 +184,134 @@
 
 /**
  * \brief               Initilisation of simpified HMAC_DRBG (never reseeds).
- *                      (For use with deterministic ECDSA.)
  *
- * \param ctx           HMAC_DRBG context to be initialised
- * \param md_info       MD algorithm to use for HMAC_DRBG
- * \param data          Concatenation of entropy string and additional data
- * \param data_len      Length of data in bytes
+ * This function is meant for use in algorithms that need a pseudorandom
+ * input such as deterministic ECDSA.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
- *                      MBEDTLS_ERR_MD_ALLOC_FAILED.
+ * \param ctx           HMAC_DRBG context to be initialised.
+ * \param md_info       MD algorithm to use for HMAC_DRBG.
+ * \param data          Concatenation of the initial entropy string and
+ *                      the additional data.
+ * \param data_len      Length of \p data in bytes.
+ *
+ * \return              \c 0 if successful. or
+ * \return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
+ *                      invalid.
+ * \return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
+ *                      memory to allocate context data.
  */
 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
                         mbedtls_md_handle_t  md_info,
                         const unsigned char *data, size_t data_len );
 
 /**
- * \brief               Enable / disable prediction resistance (Default: Off)
+ * \brief               This function turns prediction resistance on or off.
+ *                      The default value is off.
  *
- * Note: If enabled, entropy is used for ctx->entropy_len before each call!
- *       Only use this if you have ample supply of good entropy!
+ * \note                If enabled, entropy is gathered at the beginning of
+ *                      every call to mbedtls_hmac_drbg_random_with_add()
+ *                      or mbedtls_hmac_drbg_random().
+ *                      Only use this if your entropy source has sufficient
+ *                      throughput.
  *
- * \param ctx           HMAC_DRBG context
- * \param resistance    MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF
+ * \param ctx           The HMAC_DRBG context.
+ * \param resistance    #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF.
  */
 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
                                           int resistance );
 
 /**
- * \brief               Set the amount of entropy grabbed on each reseed
- *                      (Default: given by the security strength, which
- *                      depends on the hash used, see \c mbedtls_hmac_drbg_init() )
+ * \brief               This function sets the amount of entropy grabbed on each
+ *                      seed or reseed.
  *
- * \param ctx           HMAC_DRBG context
- * \param len           Amount of entropy to grab, in bytes
+ * See the documentation of mbedtls_hmac_drbg_seed() for the default value.
+ *
+ * \param ctx           The HMAC_DRBG context.
+ * \param len           The amount of entropy to grab, in bytes.
  */
 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
                                 size_t len );
 
 /**
- * \brief               Set the reseed interval
- *                      (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
+ * \brief               Set the reseed interval.
  *
- * \param ctx           HMAC_DRBG context
- * \param interval      Reseed interval
+ * The reseed interval is the number of calls to mbedtls_hmac_drbg_random()
+ * or mbedtls_hmac_drbg_random_with_add() after which the entropy function
+ * is called again.
+ *
+ * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL.
+ *
+ * \param ctx           The HMAC_DRBG context.
+ * \param interval      The reseed interval.
  */
 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
                                     int interval );
 
 /**
- * \brief               HMAC_DRBG update state
+ * \brief               This function updates the state of the HMAC_DRBG context.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to update state with, or NULL
- * \param add_len       Length of additional data, or 0
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    The data to update the state with.
+ *                      If this is \c NULL, there is no additional data.
+ * \param add_len       Length of \p additional in bytes.
+ *                      Unused if \p additional is \c NULL.
  *
  * \return              \c 0 on success, or an error from the underlying
  *                      hash calculation or
  *                      MBEDTLS_ERR_PLATFORM_FAULT_DETECTED.
- *
- * \note                Additional data is optional, pass NULL and 0 as second
- *                      third argument if no additional data is being used.
  */
 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
                        const unsigned char *additional, size_t add_len );
 
 /**
- * \brief               HMAC_DRBG reseeding (extracts data from entropy source)
+ * \brief               This function reseeds the HMAC_DRBG context, that is
+ *                      extracts data from the entropy source.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to add to state (Can be NULL)
- * \param len           Length of additional data
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    Additional data to add to the state.
+ *                      If this is \c NULL, there is no additional data
+ *                      and \p len should be \c 0.
+ * \param len           The length of the additional data.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
+ *                      and also at most
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
+ *                      where \p entropy_len is the entropy length
+ *                      (see mbedtls_hmac_drbg_set_entropy_len()).
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy function failed.
  */
 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
                       const unsigned char *additional, size_t len );
 
 /**
- * \brief               HMAC_DRBG generate random with additional update input
+ * \brief   This function updates an HMAC_DRBG instance with additional
+ *          data and uses it to generate random data.
  *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
- * \param p_rng         HMAC_DRBG context
- * \param output        Buffer to fill
- * \param output_len    Length of the buffer
- * \param additional    Additional data to update with (can be NULL)
- * \param add_len       Length of additional data (can be 0)
+ * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
+ *                      #mbedtls_hmac_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param output_len    The length of the buffer in bytes.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \param additional    Additional data to update with.
+ *                      If this is \c NULL, there is no additional data
+ *                      and \p add_len should be \c 0.
+ * \param add_len       The length of the additional data.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
- *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG, or
- *                      MBEDTLS_ERR_PLATFORM_FAULT_DETECTED.
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy source failed.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ *                      \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if
+ *                      \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT.
+ * \return              #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED if
+ *                      a logical fault is detected.
  */
 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
                                unsigned char *output, size_t output_len,
@@ -247,26 +319,31 @@
                                size_t add_len );
 
 /**
- * \brief               HMAC_DRBG generate random
+ * \brief   This function uses HMAC_DRBG to generate random data.
  *
- * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ * This function automatically reseeds if the reseed counter is exceeded
+ * or prediction resistance is enabled.
  *
- * \param p_rng         HMAC_DRBG context
- * \param output        Buffer to fill
- * \param out_len       Length of the buffer
+ * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
+ *                      #mbedtls_hmac_drbg_context structure.
+ * \param output        The buffer to fill.
+ * \param out_len       The length of the buffer in bytes.
+ *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
  *
- * \return              0 if successful, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
- *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG,
- *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG, or
- *                      MBEDTLS_ERR_PLATFORM_FAULT_DETECTED.
+ * \return              \c 0 if successful.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ *                      if a call to the entropy source failed.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
+ *                      \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
+ * \return              #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED if
+ *                      a logical fault is detected.
  */
 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
 
 /**
  * \brief               Free an HMAC_DRBG context
  *
- * \param ctx           HMAC_DRBG context to free.
+ * \param ctx           The HMAC_DRBG context to free.
  */
 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
 
@@ -277,17 +354,16 @@
 #define MBEDTLS_DEPRECATED
 #endif
 /**
- * \brief               HMAC_DRBG update state
+ * \brief               This function updates the state of the HMAC_DRBG context.
  *
  * \deprecated          Superseded by mbedtls_hmac_drbg_update_ret()
  *                      in 2.16.0.
  *
- * \param ctx           HMAC_DRBG context
- * \param additional    Additional data to update state with, or NULL
- * \param add_len       Length of additional data, or 0
- *
- * \note                Additional data is optional, pass NULL and 0 as second
- *                      third argument if no additional data is being used.
+ * \param ctx           The HMAC_DRBG context.
+ * \param additional    The data to update the state with.
+ *                      If this is \c NULL, there is no additional data.
+ * \param add_len       Length of \p additional in bytes.
+ *                      Unused if \p additional is \c NULL.
  */
 MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
     mbedtls_hmac_drbg_context *ctx,
@@ -297,26 +373,31 @@
 
 #if defined(MBEDTLS_FS_IO)
 /**
- * \brief               Write a seed file
+ * \brief               This function writes a seed file.
  *
- * \param ctx           HMAC_DRBG context
- * \param path          Name of the file
+ * \param ctx           The HMAC_DRBG context.
+ * \param path          The name of the file.
  *
- * \return              0 if successful, 1 on file error, or
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed
+ *                      failure.
  */
 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
 
 /**
- * \brief               Read and update a seed file. Seed is added to this
- *                      instance
+ * \brief               This function reads and updates a seed file. The seed
+ *                      is added to this instance.
  *
- * \param ctx           HMAC_DRBG context
- * \param path          Name of the file
+ * \param ctx           The HMAC_DRBG context.
+ * \param path          The name of the file.
  *
- * \return              0 if successful, 1 on file error,
- *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
- *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ * \return              \c 0 on success.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on
+ *                      reseed failure.
+ * \return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing
+ *                      seed file is too large.
  */
 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
 #endif /* MBEDTLS_FS_IO */
@@ -324,9 +405,10 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 /**
- * \brief               Checkup routine
+ * \brief               The HMAC_DRBG Checkup routine.
  *
- * \return              0 if successful, or 1 if the test failed
+ * \return              \c 0 if successful.
+ * \return              \c 1 if the test failed.
  */
 int mbedtls_hmac_drbg_self_test( int verbose );
 #endif
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index b4eef71..aeffb16 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -40,16 +40,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  16
-#define MBEDTLS_VERSION_PATCH  3
+#define MBEDTLS_VERSION_PATCH  4
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02100300
-#define MBEDTLS_VERSION_STRING         "2.16.3"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.3"
+#define MBEDTLS_VERSION_NUMBER         0x02100400
+#define MBEDTLS_VERSION_STRING         "2.16.4"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.4"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 0156856..d5e34eb 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -162,15 +162,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.3 SOVERSION 3)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.4 SOVERSION 3)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.3 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.4 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.16.3 SOVERSION 12)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.16.4 SOVERSION 12)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/aes.c b/library/aes.c
index 9098d47..5746987 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1246,6 +1246,18 @@
     PUT_UINT32_LE( X2, output,  8 );
     PUT_UINT32_LE( X3, output, 12 );
 
+    mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+    mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+    mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+    mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+    mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+    mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+    mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+    mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+    mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
     return( 0 );
 }
 #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */
@@ -1513,6 +1525,18 @@
     PUT_UINT32_LE( X2, output,  8 );
     PUT_UINT32_LE( X3, output, 12 );
 
+    mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+    mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+    mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+    mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+    mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+    mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+    mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+    mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+    mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
     return( 0 );
 }
 #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */
diff --git a/library/bignum.c b/library/bignum.c
index 842b38b..00df10d 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -157,9 +157,10 @@
     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
 
-    /* Actually resize up in this case */
+    /* Actually resize up if there are currently fewer than nblimbs limbs. */
     if( X->n <= nblimbs )
         return( mbedtls_mpi_grow( X, nblimbs ) );
+    /* After this point, then X->n > nblimbs and in particular X->n > 0. */
 
     for( i = X->n - 1; i > 0; i-- )
         if( X->p[i] != 0 )
@@ -198,7 +199,7 @@
     if( X == Y )
         return( 0 );
 
-    if( Y->p == NULL )
+    if( Y->n == 0 )
     {
         mbedtls_mpi_free( X );
         return( 0 );
@@ -1071,6 +1072,107 @@
     return( 0 );
 }
 
+/** Decide if an integer is less than the other, without branches.
+ *
+ * \param x         First integer.
+ * \param y         Second integer.
+ *
+ * \return          1 if \p x is less than \p y, 0 otherwise
+ */
+static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
+        const mbedtls_mpi_uint y )
+{
+    mbedtls_mpi_uint ret;
+    mbedtls_mpi_uint cond;
+
+    /*
+     * Check if the most significant bits (MSB) of the operands are different.
+     */
+    cond = ( x ^ y );
+    /*
+     * If the MSB are the same then the difference x-y will be negative (and
+     * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
+     */
+    ret = ( x - y ) & ~cond;
+    /*
+     * If the MSB are different, then the operand with the MSB of 1 is the
+     * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
+     * the MSB of y is 0.)
+     */
+    ret |= y & cond;
+
+
+    ret = ret >> ( biL - 1 );
+
+    return (unsigned) ret;
+}
+
+/*
+ * Compare signed values in constant time
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+        unsigned *ret )
+{
+    size_t i;
+    /* The value of any of these variables is either 0 or 1 at all times. */
+    unsigned cond, done, X_is_negative, Y_is_negative;
+
+    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET( Y != NULL );
+    MPI_VALIDATE_RET( ret != NULL );
+
+    if( X->n != Y->n )
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    /*
+     * Set sign_N to 1 if N >= 0, 0 if N < 0.
+     * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
+     */
+    X_is_negative = ( X->s & 2 ) >> 1;
+    Y_is_negative = ( Y->s & 2 ) >> 1;
+
+    /*
+     * If the signs are different, then the positive operand is the bigger.
+     * That is if X is negative (X_is_negative == 1), then X < Y is true and it
+     * is false if X is positive (X_is_negative == 0).
+     */
+    cond = ( X_is_negative ^ Y_is_negative );
+    *ret = cond & X_is_negative;
+
+    /*
+     * This is a constant-time function. We might have the result, but we still
+     * need to go through the loop. Record if we have the result already.
+     */
+    done = cond;
+
+    for( i = X->n; i > 0; i-- )
+    {
+        /*
+         * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
+         * X and Y are negative.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
+        *ret |= cond & ( 1 - done ) & X_is_negative;
+        done |= cond;
+
+        /*
+         * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
+         * X and Y are positive.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
+        *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
+        done |= cond;
+    }
+
+    return( 0 );
+}
+
 /*
  * Compare signed values
  */
diff --git a/library/cipher.c b/library/cipher.c
index 20af256..7164741 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -361,6 +361,10 @@
 
     *olen = 0;
     block_size = mbedtls_cipher_get_block_size( ctx );
+    if ( 0 == block_size )
+    {
+        return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
+    }
 
     if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
     {
@@ -396,11 +400,6 @@
     }
 #endif
 
-    if ( 0 == block_size )
-    {
-        return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
-    }
-
     if( input == output &&
        ( ctx->unprocessed_len != 0 || ilen % block_size ) )
     {
@@ -459,11 +458,6 @@
          */
         if( 0 != ilen )
         {
-            if( 0 == block_size )
-            {
-                return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
-            }
-
             /* Encryption: only cache partial blocks
              * Decryption w/ padding: always keep at least one whole block
              * Decryption w/o padding: only cache partial blocks
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 069303f..1c71288 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -62,68 +62,6 @@
 #endif
 }
 
-/*
- * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
- * NIST tests to succeed (which require known length fixed entropy)
- */
-/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
- * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
- *                                   custom, len, entropy_len)
- * implements
- * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
- *                      security_strength) -> initial_working_state
- * with inputs
- *   custom[:len] = nonce || personalization_string
- * where entropy_input comes from f_entropy for entropy_len bytes
- * and with outputs
- *   ctx = initial_working_state
- */
-int mbedtls_ctr_drbg_seed_entropy_len(
-                   mbedtls_ctr_drbg_context *ctx,
-                   int (*f_entropy)(void *, unsigned char *, size_t),
-                   void *p_entropy,
-                   const unsigned char *custom,
-                   size_t len,
-                   size_t entropy_len )
-{
-    int ret;
-    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
-
-    mbedtls_platform_memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
-
-    mbedtls_aes_init( &ctx->aes_ctx );
-
-    ctx->f_entropy = f_entropy;
-    ctx->p_entropy = p_entropy;
-
-    ctx->entropy_len = entropy_len;
-    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-    /*
-     * Initialize with an empty key
-     */
-    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
-    {
-        return( ret );
-    }
-    return( 0 );
-}
-
-int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
-                   int (*f_entropy)(void *, unsigned char *, size_t),
-                   void *p_entropy,
-                   const unsigned char *custom,
-                   size_t len )
-{
-    return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
-                                       MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
-}
-
 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
 {
     if( ctx == NULL )
@@ -427,6 +365,63 @@
     return( ret );
 }
 
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ *                      security_strength) -> initial_working_state
+ * with inputs
+ *   custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for ctx->entropy_len bytes
+ * and with outputs
+ *   ctx = initial_working_state
+ */
+int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
+                           int (*f_entropy)(void *, unsigned char *, size_t),
+                           void *p_entropy,
+                           const unsigned char *custom,
+                           size_t len )
+{
+    int ret;
+    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+
+    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+
+    mbedtls_aes_init( &ctx->aes_ctx );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    if( ctx->entropy_len == 0 )
+        ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
+    /*
+     * Initialize with an empty key
+     */
+    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+    {
+        return( ret );
+    }
+    return( 0 );
+}
+
+/* Backward compatibility wrapper */
+int mbedtls_ctr_drbg_seed_entropy_len(
+    mbedtls_ctr_drbg_context *ctx,
+    int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
+    const unsigned char *custom, size_t len,
+    size_t entropy_len )
+{
+    mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
+    return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
+}
+
 /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
  * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
  * implements
@@ -517,7 +512,7 @@
 exit:
     mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-    return( 0 );
+    return( ret );
 }
 
 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
@@ -678,8 +673,11 @@
         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
 
     test_offset = 0;
-    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
-                                (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+    CHK( mbedtls_ctr_drbg_seed( &ctx,
+                                ctr_drbg_self_test_entropy,
+                                (void *) entropy_source_pr,
+                                nonce_pers_pr, 16 ) );
     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
@@ -699,8 +697,11 @@
     mbedtls_ctr_drbg_init( &ctx );
 
     test_offset = 0;
-    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
-                            (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+    CHK( mbedtls_ctr_drbg_seed( &ctx,
+                                ctr_drbg_self_test_entropy,
+                                (void *) entropy_source_nopr,
+                                nonce_pers_nopr, 16 ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
diff --git a/library/ecdsa.c b/library/ecdsa.c
index a9734f6..6cfaa08 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -297,7 +297,7 @@
     *p_sign_tries = 0;
     do
     {
-        if( *p_sign_tries++ > 10 )
+        if( (*p_sign_tries)++ > 10 )
         {
             ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
             goto cleanup;
@@ -310,7 +310,7 @@
         *p_key_tries = 0;
         do
         {
-            if( *p_key_tries++ > 10 )
+            if( (*p_key_tries)++ > 10 )
             {
                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
                 goto cleanup;
@@ -363,6 +363,7 @@
         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
diff --git a/library/ecp.c b/library/ecp.c
index 5c2e0f1..661112b 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -2724,6 +2724,7 @@
     {
         /* SEC1 3.2.1: Generate d such that 1 <= n < N */
         int count = 0;
+        unsigned cmp = 0;
 
         /*
          * Match the procedure given in RFC 6979 (deterministic ECDSA):
@@ -2748,9 +2749,14 @@
              */
             if( ++count > 30 )
                 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+
+            ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
+            if( ret != 0 )
+            {
+                goto cleanup;
+            }
         }
-        while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
-               mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
+        while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
     }
 #endif /* ECP_SHORTWEIERSTRASS */
 
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 82703b0..dd895be 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -320,16 +320,19 @@
 
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
 
-    /*
-     * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
-     * each hash function, then according to SP800-90A rev1 10.1 table 2,
-     * min_entropy_len (in bits) is security_strength.
-     *
-     * (This also matches the sizes used in the NIST test vectors.)
-     */
-    ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
-                       md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
-                       32;  /* better (256+) -> 256 bits */
+    if( ctx->entropy_len == 0 )
+    {
+        /*
+         * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+         * each hash function, then according to SP800-90A rev1 10.1 table 2,
+         * min_entropy_len (in bits) is security_strength.
+         *
+         * (This also matches the sizes used in the NIST test vectors.)
+         */
+        ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+                           md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+                           32;  /* better (256+) -> 256 bits */
+    }
 
     if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 )
     {
@@ -349,7 +352,7 @@
 }
 
 /*
- * Set entropy length grabbed for reseeds
+ * Set entropy length grabbed for seeding
  */
 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
 {
diff --git a/library/pkparse.c b/library/pkparse.c
index 3f20225..de45552 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -843,14 +843,40 @@
         goto cleanup;
     p += len;
 
-    /* Complete the RSA private key */
-    if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
-        goto cleanup;
+#if !defined(MBEDTLS_RSA_NO_CRT)
+    /*
+    * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+    * that they can be easily recomputed from D, P and Q. However by
+    * parsing them from the PKCS1 structure it is possible to avoid
+    * recalculating them which both reduces the overhead of loading
+    * RSA private keys into memory and also avoids side channels which
+    * can arise when computing those values, since all of D, P, and Q
+    * are secret. See https://eprint.iacr.org/2020/055 for a
+    * description of one such attack.
+    */
 
-    /* Check optional parameters */
+    /* Import DP */
+    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0)
+       goto cleanup;
+
+    /* Import DQ */
+    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0)
+       goto cleanup;
+
+    /* Import QP */
+    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0)
+       goto cleanup;
+
+#else
+    /* Verify existance of the CRT params */
     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
         ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
         ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
+       goto cleanup;
+#endif
+
+    /* Complete the RSA private key */
+    if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
         goto cleanup;
 
     if( p != end )
diff --git a/library/rsa.c b/library/rsa.c
index cde07e3..3f480a3 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -249,6 +249,9 @@
 {
     int ret = 0;
     int have_N, have_P, have_Q, have_D, have_E;
+#if !defined(MBEDTLS_RSA_NO_CRT)
+    int have_DP, have_DQ, have_QP;
+#endif
     int n_missing, pq_missing, d_missing, is_pub, is_priv;
 
     RSA_VALIDATE_RET( ctx != NULL );
@@ -259,6 +262,12 @@
     have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
     have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
 
+#if !defined(MBEDTLS_RSA_NO_CRT)
+    have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
+    have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
+    have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
+#endif
+
     /*
      * Check whether provided parameters are enough
      * to deduce all others. The following incomplete
@@ -324,7 +333,7 @@
      */
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    if( is_priv )
+    if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
     {
         ret = mbedtls_rsa_deduce_crt( &ctx->P,  &ctx->Q,  &ctx->D,
                                       &ctx->DP, &ctx->DQ, &ctx->QP );
diff --git a/library/version_features.c b/library/version_features.c
index 6882830..d60758c 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -306,6 +306,9 @@
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
     "MBEDTLS_CIPHER_PADDING_ZEROS",
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+    "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY",
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
 #if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES)
     "MBEDTLS_ENABLE_WEAK_CIPHERSUITES",
 #endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index 623db76..5a5bc6e 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -227,7 +227,9 @@
     /*
      * Prepare signature
      */
-    mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+    ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+    if( ret != 0 )
+        return( ret );
 
     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
                                  f_rng, p_rng ) ) != 0 )
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 315065b..8093c0d 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -858,6 +858,14 @@
     }
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
 
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+    if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
+
 #if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES)
     if( strcmp( "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", config ) == 0 )
     {
@@ -2266,14 +2274,6 @@
     }
 #endif /* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT */
 
-#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-    if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 )
-    {
-        MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY );
-        return( 0 );
-    }
-#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
-
 #if defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
     if( strcmp( "MBEDTLS_HMAC_DRBG_RESEED_INTERVAL", config ) == 0 )
     {
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 9c6aafb..71bee47 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -686,12 +686,13 @@
         mbedtls_ctr_drbg_context ctr_drbg;
 
         mbedtls_ctr_drbg_init( &ctr_drbg );
-
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         TIME_AND_TSC( "CTR_DRBG (NOPR)",
                 mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
+        mbedtls_ctr_drbg_free( &ctr_drbg );
 
+        mbedtls_ctr_drbg_init( &ctr_drbg );
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 82f08fa..4a8ed68 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -66,6 +66,8 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
+#define mbedtls_calloc     calloc
+#define mbedtls_free       free
 #define mbedtls_printf     printf
 #define mbedtls_snprintf   snprintf
 #define mbedtls_exit       exit
@@ -78,6 +80,86 @@
 #endif
 
 
+#if defined MBEDTLS_SELF_TEST
+/* Sanity check for malloc. This is not expected to fail, and is rather
+ * intended to display potentially useful information about the platform,
+ * in particular the behavior of malloc(0). */
+static int calloc_self_test( int verbose )
+{
+    int failures = 0;
+    void *empty1 = mbedtls_calloc( 0, 1 );
+    void *empty2 = mbedtls_calloc( 0, 1 );
+    void *buffer1 = mbedtls_calloc( 1, 1 );
+    void *buffer2 = mbedtls_calloc( 1, 1 );
+    uintptr_t old_buffer1;
+
+    if( empty1 == NULL && empty2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (NULL)\n" );
+    }
+    else if( empty1 == NULL || empty2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): failed (mix of NULL and non-NULL)\n" );
+        ++failures;
+    }
+    else if( empty1 == empty2 )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (same non-null)\n" );
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (distinct non-null)\n" );
+    }
+
+    if( buffer1 == NULL || buffer2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): failed (NULL)\n" );
+        ++failures;
+    }
+    else if( buffer1 == buffer2 )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): failed (same buffer twice)\n" );
+        ++failures;
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): passed\n" );
+    }
+
+    old_buffer1 = (uintptr_t) buffer1;
+    mbedtls_free( buffer1 );
+    buffer1 = mbedtls_calloc( 1, 1 );
+    if( buffer1 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1 again): failed (NULL)\n" );
+        ++failures;
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1 again): passed (%s address)\n",
+                            (uintptr_t) old_buffer1 == (uintptr_t) buffer1 ?
+                            "same" : "different" );
+    }
+
+    if( verbose )
+        mbedtls_printf( "\n" );
+    mbedtls_free( empty1 );
+    mbedtls_free( empty2 );
+    mbedtls_free( buffer1 );
+    mbedtls_free( buffer2 );
+    return( failures );
+}
+#endif /* MBEDTLS_SELF_TEST */
+
 static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
 {
     int ret;
@@ -174,6 +256,7 @@
 
 const selftest_t selftests[] =
 {
+    {"calloc", calloc_self_test},
 #if defined(MBEDTLS_MD2_C)
     {"md2", mbedtls_md2_self_test},
 #endif
diff --git a/scripts/config.pl b/scripts/config.pl
index 2519623..8918202 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -100,6 +100,7 @@
 MBEDTLS_DEPRECATED_REMOVED
 MBEDTLS_HAVE_SSE2
 MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
 MBEDTLS_ECP_DP_M221_ENABLED
 MBEDTLS_ECP_DP_M383_ENABLED
 MBEDTLS_ECP_DP_M511_ENABLED
diff --git a/tests/configs/config-wrapper-malloc-0-null.h b/tests/configs/config-wrapper-malloc-0-null.h
new file mode 100644
index 0000000..ed74eda
--- /dev/null
+++ b/tests/configs/config-wrapper-malloc-0-null.h
@@ -0,0 +1,39 @@
+/* config.h wrapper that forces calloc(0) to return NULL.
+ * Used for testing.
+ */
+/*
+ *  Copyright (C) 2019, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CONFIG_H
+/* Don't #define MBEDTLS_CONFIG_H, let config.h do it. */
+
+#include "mbedtls/config.h"
+
+#include <stdlib.h>
+static inline void *custom_calloc( size_t nmemb, size_t size )
+{
+    if( nmemb == 0 || size == 0 )
+        return( NULL );
+    return( calloc( nmemb, size ) );
+}
+
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_STD_CALLOC custom_calloc
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index bd7e98f..ae2e112 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -137,6 +137,9 @@
         export MAKEFLAGS="-j"
     fi
 
+    # CFLAGS and LDFLAGS for Asan builds that don't use CMake
+    ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
+
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
     # Parse the script with sed, because in sh there is no way to list
@@ -1106,8 +1109,8 @@
     scripts/config.pl unset MBEDTLS_FS_IO
     # Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19,
     # to re-enable platform integration features otherwise disabled in C99 builds
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' test
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -Os -D_DEFAULT_SOURCE' lib programs
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -Os' test
 }
 
 component_build_no_std_function () {
@@ -1116,21 +1119,21 @@
     scripts/config.pl full
     scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -Os'
 }
 
 component_build_no_ssl_srv () {
     msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_SSL_SRV_C
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1'
 }
 
 component_build_no_ssl_cli () {
     msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_SSL_CLI_C
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0'
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1'
 }
 
 component_build_no_sockets () {
@@ -1140,7 +1143,7 @@
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc.
     scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux
-    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib
+    make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1 -std=c99 -pedantic' lib
 }
 
 component_test_memory_buffer_allocator_backtrace () {
@@ -1284,6 +1287,21 @@
     make test
 }
 
+component_test_malloc_0_null () {
+    msg "build: malloc(0) returns NULL (ASan+UBSan build)"
+    scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined'
+
+    msg "test: malloc(0) returns NULL (ASan+UBSan build)"
+    make test
+
+    msg "selftest: malloc(0) returns NULL (ASan+UBSan build)"
+    # Just the calloc selftest. "make test" ran the others as part of the
+    # test suites.
+    if_build_succeeded programs/test/selftest calloc
+}
+
 component_test_aes_fewer_tables () {
     msg "build: default config with AES_FEWER_TABLES enabled"
     scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
@@ -1357,6 +1375,30 @@
     make test
 }
 
+test_build_opt () {
+    info=$1 cc=$2; shift 2
+    for opt in "$@"; do
+          msg "build/test: $cc $opt, $info" # ~ 30s
+          make CC="$cc" CFLAGS="$opt -Wall -Wextra -Werror"
+          # We're confident enough in compilers to not run _all_ the tests,
+          # but at least run the unit tests. In particular, runs with
+          # optimizations use inline assembly whereas runs with -O0
+          # skip inline assembly.
+          make test # ~30s
+          make clean
+    done
+}
+
+component_test_clang_opt () {
+    scripts/config.pl full
+    test_build_opt 'full config' clang -O0 -Os -O2
+}
+
+component_test_gcc_opt () {
+    scripts/config.pl full
+    test_build_opt 'full config' gcc -O0 -Os -O2
+}
+
 component_build_mbedtls_config_file () {
     msg "build: make with MBEDTLS_CONFIG_FILE" # ~40s
     # Use the full config so as to catch a maximum of places where
@@ -1372,7 +1414,7 @@
     # Build once with -O0, to compile out the i386 specific inline assembly
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc PTHREAD=1 CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32'
+    make CC=gcc PTHREAD=1 CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O0 (ASan build)"
     make test
@@ -1388,7 +1430,7 @@
     # Build again with -O1, to compile in the i386 specific inline assembly
     msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc PTHREAD=1 CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32'
+    make CC=gcc PTHREAD=1 CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O1 (ASan build)"
     make test
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 1c9dc1d..d06badd 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -93,7 +93,7 @@
     $suite_cases_failed = () = $result =~ /.. FAILED/g;
     $suite_cases_skipped = () = $result =~ /.. ----/g;
 
-    if( $result =~ /PASSED/ ) {
+    if( $? == 0 ) {
         print "PASS\n";
         if( $verbose > 2 ) {
             pad_print_center( 72, '-', "Begin $suite" );
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 00ed391..67cf502 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1162,6 +1162,18 @@
             -S "error" \
             -C "error"
 
+requires_config_enabled MBEDTLS_ZLIB_SUPPORT
+run_test    "Default (compression enabled)" \
+            "$P_SRV debug_level=3" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -s "Allocating compression buffer" \
+            -c "Allocating compression buffer" \
+            -s "Record expansion is unknown (compression)" \
+            -c "Record expansion is unknown (compression)" \
+            -S "error" \
+            -C "error"
+
 # Test current time in ServerHello
 requires_config_enabled MBEDTLS_HAVE_TIME
 run_test    "ServerHello contains gmt_unix_time" \
@@ -5380,15 +5392,8 @@
 # Test for ClientHello without extensions
 
 requires_gnutls
-run_test    "ClientHello without extensions, SHA-1 allowed" \
-            "$P_SRV debug_level=3 key_file=data_files/server2.key crt_file=data_files/server2.crt" \
-            "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \
-            0 \
-            -s "dumping 'client hello extensions' (0 bytes)"
-
-requires_gnutls
-run_test    "ClientHello without extensions, SHA-1 forbidden in certificates on server" \
-            "$P_SRV debug_level=3 key_file=data_files/server2.key crt_file=data_files/server2.crt allow_sha1=0" \
+run_test    "ClientHello without extensions" \
+            "$P_SRV debug_level=3" \
             "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
             -s "dumping 'client hello extensions' (0 bytes)"
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 4a97826..01050d9 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -44,11 +44,11 @@
 
     /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
      * where nonce||perso = nonce[nonce->len] */
-    TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len(
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len );
+    TEST_ASSERT( mbedtls_ctr_drbg_seed(
                      &ctx,
                      mbedtls_test_entropy_func, entropy->x,
-                     nonce->x, nonce->len,
-                     entropy_chunk_len ) == 0 );
+                     nonce->x, nonce->len ) == 0 );
     if( reseed_mode == RESEED_ALWAYS )
         mbedtls_ctr_drbg_set_prediction_resistance(
             &ctx,
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index 4f3143f..9e82bb5 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -527,7 +527,9 @@
     TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     hlen = mbedtls_md_get_size( md_info );
-    mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
+    TEST_ASSERT( mbedtls_md( md_info,
+                             (const unsigned char *) msg, strlen( msg ),
+                             hash ) == 0 );
 
     mbedtls_ecp_set_max_ops( max_ops );
 
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_mpi.data b/tests/suites/test_suite_mpi.data
index 425e93a..00926ff 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -163,6 +163,93 @@
 Base test mbedtls_mpi_cmp_mpi (Mixed values) #6
 mbedtls_mpi_cmp_mpi:10:"-2":10:"31231231289798":-1
 
+Base test mbedtls_mpi_lt_mpi_ct #1
+mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B5":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct #2
+mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B4":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct #3
+mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B6":1:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Negative values) #1
+mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-2":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Negative values) #2
+mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-3":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Negative values) #3
+mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-1":1:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #1
+mbedtls_mpi_lt_mpi_ct:1:"-3":1:"2":1:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #2
+mbedtls_mpi_lt_mpi_ct:1:"2":1:"-3":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #3
+mbedtls_mpi_lt_mpi_ct:2:"-2":2:"1C67967269C6":1:0
+
+Base test mbedtls_mpi_lt_mpi_ct (X is longer in storage)
+mbedtls_mpi_lt_mpi_ct:3:"2B5":2:"2B5":0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Base test mbedtls_mpi_lt_mpi_ct (Y is longer in storage)
+mbedtls_mpi_lt_mpi_ct:3:"2B5":4:"2B5":0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #1
+mbedtls_mpi_lt_mpi_ct:2:"7FFFFFFFFFFFFFFF":2:"FF":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #2
+mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"7FFFFFFFFFFFFFFF":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #3
+mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"1":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #4
+mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"0":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #5
+mbedtls_mpi_lt_mpi_ct:2:"FFFFFFFFFFFFFFFF":2:"FF":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #1
+mbedtls_mpi_lt_mpi_ct:1:"7FFFFFFF":1:"FF":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #2
+mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"7FFFFFFF":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #3
+mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"1":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #4
+mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"0":0:0
+
+Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #5
+mbedtls_mpi_lt_mpi_ct:1:"FFFFFFFF":1:"FF":0:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (X<Y, zero vs non-zero MS limb)
+mbedtls_mpi_lt_mpi_ct:2:"0FFFFFFFFFFFFFFFF":2:"1FFFFFFFFFFFFFFFF":1:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (X>Y, equal MS limbs)
+mbedtls_mpi_lt_mpi_ct:2:"-EEFFFFFFFFFFFFFFF1":2:"-EEFFFFFFFFFFFFFFFF":0:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (X=Y)
+mbedtls_mpi_lt_mpi_ct:2:"EEFFFFFFFFFFFFFFFF":2:"EEFFFFFFFFFFFFFFFF":0:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (X=-Y)
+mbedtls_mpi_lt_mpi_ct:2:"-EEFFFFFFFFFFFFFFFF":2:"EEFFFFFFFFFFFFFFFF":1:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #1
+mbedtls_mpi_lt_mpi_ct:2:"11FFFFFFFFFFFFFFFF":2:"FF1111111111111111":1:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #2
+mbedtls_mpi_lt_mpi_ct:2:"FF1111111111111111":2:"11FFFFFFFFFFFFFFFF":0:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #3
+mbedtls_mpi_lt_mpi_ct:2:"-11FFFFFFFFFFFFFFFF":2:"-FF1111111111111111":0:0
+
+Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #4
+mbedtls_mpi_lt_mpi_ct:2:"-FF1111111111111111":2:"-11FFFFFFFFFFFFFFFF":1:0
+
 Base test mbedtls_mpi_cmp_abs #1
 mbedtls_mpi_cmp_abs:10:"693":10:"693":0
 
@@ -193,37 +280,106 @@
 Base test mbedtls_mpi_cmp_abs (Mix values) #3
 mbedtls_mpi_cmp_abs:10:"-2":10:"1":1
 
-Base test mbedtls_mpi_copy #1
-mbedtls_mpi_copy:0:1500
+Copy zero (1 limb) to positive (1 limb)
+mbedtls_mpi_copy_sint:0:1500
 
-Base test mpi_copy_self #1
+Copy zero (1 limb) to negative (1 limb)
+mbedtls_mpi_copy_sint:0:-1500
+
+Copy positive (1 limb) to zero (1 limb)
+mbedtls_mpi_copy_sint:1500:0
+
+Copy negative (1 limb) to zero (1 limb)
+mbedtls_mpi_copy_sint:-1500:0
+
+Copy positive (1 limb) to negative (1 limb)
+mbedtls_mpi_copy_sint:1500:-42
+
+Copy negative (1 limb) to positive (1 limb)
+mbedtls_mpi_copy_sint:-42:1500
+
+Copy zero (null) to zero (null)
+mbedtls_mpi_copy_binary:"":""
+
+Copy zero (null) to positive (1 limb)
+mbedtls_mpi_copy_binary:"":"1234"
+
+Copy positive (1 limb) to zero (null)
+mbedtls_mpi_copy_binary:"1234":""
+
+Copy positive to larger
+mbedtls_mpi_copy_binary:"bead":"ca5cadedb01dfaceacc01ade"
+
+Copy positive to smaller
+mbedtls_mpi_copy_binary:"ca5cadedb01dfaceacc01ade":"bead"
+
+Copy self: positive (1 limb)
 mpi_copy_self:14
 
-Base test mbedtls_mpi_swap #1
-mbedtls_mpi_swap:0:1500
+Copy self: zero (1 limb)
+mpi_copy_self:0
 
-Test mbedtls_mpi_shrink #1
+Swap zero (1 limb) with positive (1 limb)
+mbedtls_mpi_swap_sint:0:1500
+
+Swap zero (1 limb) with negative (1 limb)
+mbedtls_mpi_swap_sint:0:-1500
+
+Swap positive (1 limb) with zero (1 limb)
+mbedtls_mpi_swap_sint:1500:0
+
+Swap negative (1 limb) with zero (1 limb)
+mbedtls_mpi_swap_sint:-1500:0
+
+Swap positive (1 limb) with negative (1 limb)
+mbedtls_mpi_swap_sint:1500:-42
+
+Swap negative (1 limb) with positive (1 limb)
+mbedtls_mpi_swap_sint:-42:1500
+
+Swap zero (null) with zero (null)
+mbedtls_mpi_swap_binary:"":""
+
+Swap zero (null) with positive (1 limb)
+mbedtls_mpi_swap_binary:"":"1234"
+
+Swap positive (1 limb) with zero (null)
+mbedtls_mpi_swap_binary:"1234":""
+
+Swap positive with larger
+mbedtls_mpi_swap_binary:"bead":"ca5cadedb01dfaceacc01ade"
+
+Swap positive with smaller
+mbedtls_mpi_swap_binary:"ca5cadedb01dfaceacc01ade":"bead"
+
+Swap self: 1 limb
+mpi_swap_self:"face"
+
+Swap self: null
+mpi_swap_self:""
+
+Shrink 2 limbs in a buffer of size 2 to 4
 mbedtls_mpi_shrink:2:2:4:4
 
-Test mbedtls_mpi_shrink #2
+Shrink 2 limbs in a buffer of size 4 to 4
 mbedtls_mpi_shrink:4:2:4:4
 
-Test mbedtls_mpi_shrink #3
+Shrink 2 limbs in a buffer of size 8 to 4
 mbedtls_mpi_shrink:8:2:4:4
 
-Test mbedtls_mpi_shrink #4
+Shrink 4 limbs in a buffer of size 8 to 4
 mbedtls_mpi_shrink:8:4:4:4
 
-Test mbedtls_mpi_shrink #5
+Shrink 6 limbs in a buffer of size 8 to 4 yielding 6
 mbedtls_mpi_shrink:8:6:4:6
 
-Test mbedtls_mpi_shrink #6
+Shrink 2 limbs in a buffer of size 4 to 0 yielding 2
 mbedtls_mpi_shrink:4:2:0:2
 
-Test mbedtls_mpi_shrink #7
+Shrink 1 limbs in a buffer of size 4 to 0 yielding 1
 mbedtls_mpi_shrink:4:1:0:1
 
-Test mbedtls_mpi_shrink #8
+Shrink 0 limbs in a buffer of size 4 to 0 yielding 1
 mbedtls_mpi_shrink:4:0:0:1
 
 Test mbedtls_mpi_safe_cond_assign #1
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index f982385..f2702f1 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -538,6 +538,31 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mbedtls_mpi_lt_mpi_ct( int size_X, char * input_X,
+                            int size_Y, char * input_Y,
+                            int input_ret, int input_err )
+{
+    unsigned ret;
+    unsigned input_uret = input_ret;
+    mbedtls_mpi X, Y;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, input_Y ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_grow( &X, size_X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_grow( &Y, size_Y ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_lt_mpi_ct( &X, &Y, &ret ) == input_err );
+    if( input_err == 0 )
+        TEST_ASSERT( ret == input_uret );
+
+exit:
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mbedtls_mpi_cmp_abs( int radix_X, char * input_X, int radix_Y,
                           char * input_Y, int input_A )
 {
@@ -554,22 +579,40 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_mpi_copy( int input_X, int input_A )
+void mbedtls_mpi_copy_sint( int input_X, int input_Y )
 {
-    mbedtls_mpi X, Y, A;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &A );
+    mbedtls_mpi X, Y;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
     TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_lset( &Y, input_A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_lset( &A, input_A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 );
+
     TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) != 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 );
 
 exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &A );
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_mpi_copy_binary( data_t *input_X, data_t *input_Y )
+{
+    mbedtls_mpi X, Y, X0;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &X0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
+
+exit:
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &X0 );
 }
 /* END_CASE */
 
@@ -661,22 +704,61 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_mpi_swap( int input_X, int input_Y )
+void mbedtls_mpi_swap_sint( int input_X, int input_Y )
 {
-    mbedtls_mpi X, Y, A;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &A );
+    mbedtls_mpi X, Y;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
     TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_lset( &A, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_Y ) == 0 );
+
     mbedtls_mpi_swap( &X, &Y );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 );
 
 exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &A );
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_mpi_swap_binary( data_t *input_X, data_t *input_Y )
+{
+    mbedtls_mpi X, Y, X0, Y0;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
+    mbedtls_mpi_init( &X0 ); mbedtls_mpi_init( &Y0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &Y0, input_Y->x, input_Y->len ) == 0 );
+
+    mbedtls_mpi_swap( &X, &Y );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y0 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
+
+exit:
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
+    mbedtls_mpi_free( &X0 ); mbedtls_mpi_free( &Y0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_swap_self( data_t *input_X )
+{
+    mbedtls_mpi X, X0;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &X0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
+
+    mbedtls_mpi_swap( &X, &X );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
+
+exit:
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &X0 );
 }
 /* END_CASE */
 
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 61bf95c..9153862 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -735,7 +735,9 @@
     TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     hlen = mbedtls_md_get_size( md_info );
-    mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
+    TEST_ASSERT( mbedtls_md( md_info,
+                             (const unsigned char *) msg, strlen( msg ),
+                             hash ) == 0 );
 
     mbedtls_ecp_set_max_ops( max_ops );
 
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index c3189c8..f7dd90c 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.16.3"
+check_compiletime_version:"2.16.4"
 
 Check runtime library version
-check_runtime_version:"2.16.3"
+check_runtime_version:"2.16.4"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0