Merge remote-tracking branch 'restricted/pr/519' into mbedtls-2.1
diff --git a/.travis.yml b/.travis.yml
index 91a36c9..3a12b56 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@
 - tests/scripts/check-doxy-blocks.pl
 - tests/scripts/check-names.sh
 - tests/scripts/check-files.py
+- tests/scripts/doxygen.sh
 - cmake -D CMAKE_BUILD_TYPE:String="Check" .
 - make
 - make test
@@ -24,6 +25,10 @@
     secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
 
 addons:
+  apt:
+    packages:
+    - doxygen
+    - graphviz
   coverity_scan:
     project:
       name: "ARMmbed/mbedtls"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f032ad4..d321357 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -130,20 +130,9 @@
     add_subdirectory(programs)
 endif()
 
-# targets for doxygen only work on Unix
-if(UNIX)
-    ADD_CUSTOM_TARGET(apidoc
-        COMMAND mkdir -p apidoc
-        COMMAND cp include/mbedtls/config.h include/mbedtls/config.h.bak
-        COMMAND scripts/config.pl realfull
-        COMMAND doxygen doxygen/mbedtls.doxyfile
-        COMMAND mv include/mbedtls/config.h.bak include/mbedtls/config.h
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-
-    ADD_CUSTOM_TARGET(apidoc_clean
-        COMMAND rm -rf apidoc
-        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-endif(UNIX)
+ADD_CUSTOM_TARGET(apidoc
+    COMMAND doxygen doxygen/mbedtls.doxyfile
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 
 if(ENABLE_TESTING)
     enable_testing()
diff --git a/ChangeLog b/ChangeLog
index 98b95ca..0936755 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
-= mbed TLS x.x.x branch released xxxx-xx-xx
+= mbed TLS 2.1.x branch released xxxx-xx-xx
 
 Security
    * Fix timing variations and memory access variations in RSA PKCS#1 v1.5
@@ -9,17 +9,76 @@
      ECDHE. Reported by Yuval Yarom, Eyal Ronen, Adi Shamir, David Wong and
      Daniel Genkin.
 
+= mbed TLS 2.1.16 branch released 2018-11-19
+
+Security
+   * Fix overly strict DN comparison when looking for CRLs belonging to a
+     particular CA. This previously led to ignoring CRLs when the CRL's issuer
+     name and the CA's subject name differed in their string encoding (e.g.,
+     one using PrintableString and the other UTF8String) or in the choice of
+     upper and lower case. Reported by Henrik Andersson of Bosch GmbH in issue
+     #1784.
+   * Fix a flawed bounds check in server PSK hint parsing. In case the
+     incoming message buffer was placed within the first 64KiB of address
+     space and a PSK-(EC)DHE ciphersuite was used, this allowed an attacker
+     to trigger a memory access up to 64KiB beyond the incoming message buffer,
+     potentially leading to application crash or information disclosure.
+   * Fix mbedtls_mpi_is_prime() to use more rounds of probabilistic testing. The
+     previous settings for the number of rounds made it practical for an
+     adversary to construct non-primes that would be erroneously accepted as
+     primes with high probability. This does not have an impact on the
+     security of TLS, but can matter in other contexts with numbers chosen
+     potentially by an adversary that should be prime and can be validated.
+     For example, the number of rounds was enough to securely generate RSA key
+     pairs or Diffie-Hellman parameters, but was insufficient to validate
+     Diffie-Hellman parameters properly.
+     See "Prime and Prejudice" by by Martin R. Albrecht and Jake Massimo and
+     Kenneth G. Paterson and Juraj Somorovsky.
+
 Bugfix
-    * Fix failure in hmac_drbg in the benchmark sample application, when
-      MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095
-    * Fix a bug in the update function for SSL ticket keys which previously
-      invalidated keys of a lifetime of less than a 1s. Fixes #1968.
+   * Fix failure in hmac_drbg in the benchmark sample application, when
+     MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095
+   * Fix a bug in the update function for SSL ticket keys which previously
+     invalidated keys of a lifetime of less than a 1s. Fixes #1968.
+   * Fix potential build failures related to the 'apidoc' target, introduced
+     in the previous patch release. Found by Robert Scheck. #390 #391
+   * Fix a bug in the record decryption routine ssl_decrypt_buf()
+     which led to accepting properly authenticated but improperly
+     padded records in case of CBC ciphersuites using Encrypt-then-MAC.
+   * Fix wrong order of freeing in programs/ssl/ssl_server2 example
+     application leading to a memory leak in case both
+     MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE are set.
+     Fixes #2069.
+   * Fix memory leak and freeing without initialization in the example
+     program programs/x509/cert_write. Fixes #1422.
+   * Ignore IV in mbedtls_cipher_set_iv() when the cipher mode is
+     MBEDTLS_MODE_ECB. Found by ezdevelop, Fixes #1091.
+   * Zeroize memory used for reassembling handshake messages after use.
+   * Use `mbedtls_zeroize()` instead of `memset()` for zeroization of
+     sensitive data in the example programs aescrypt2 and crypt_and_hash.
+   * Fix compilation failure for configurations which use compile time
+     replacements of standard calloc/free functions through the macros
+     MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO.
+     Reported by ole-de and ddhome2006. Fixes #882, #1642 and #1706.
+   * Fix programs/pkey/dh_server.c so that it actually works with dh_client.c.
+     Found and fixed by Martijn de Milliano.
 
 Changes
+   * "make apidoc" now generates the documentation for the current
+     configuration. Run "scripts/apidoc_full.sh" to generate the full
+     documentation. This aligns the behavior with Mbed TLS versions 2.2 and
+     later and reverts it back to how it behaved in version 2.1.3.
    * Add tests for session resumption in DTLS.
    * Close a test gap in (D)TLS between the client side and the server side:
      test the handling of large packets and small packets on the client side
      in the same way as on the server side.
+   * Change the dtls_client and dtls_server samples to work by default over
+     IPv6 and optionally by a build option over IPv4.
+   * Change the use of Windows threading to use Microsoft Visual C++ runtime
+     calls, rather than Win32 API calls directly. This is necessary to avoid
+     conflict with C runtime usage. Found and fixed by irwir.
+   * Improve documentation of mbedtls_ssl_get_verify_result().
+     Fixes #517 reported by github-monoculture.
 
 = mbed TLS 2.1.15 branch released 2018-08-31
 
diff --git a/Makefile b/Makefile
index 0eece74..dd76b40 100644
--- a/Makefile
+++ b/Makefile
@@ -87,10 +87,7 @@
 
 apidoc:
 	mkdir -p apidoc
-	cp include/mbedtls/config.h include/mbedtls/config.h.bak
-	scripts/config.pl realfull
 	doxygen doxygen/mbedtls.doxyfile
-	mv include/mbedtls/config.h.bak include/mbedtls/config.h
 
 apidoc_clean:
 	rm -rf apidoc
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index a44f02d..a4d68cc 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -21,7 +21,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.1.15 source code documentation
+ * @mainpage mbed TLS v2.1.16 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 89a10c2..73432b9 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.1.15"
+PROJECT_NAME           = "mbed TLS v2.1.16"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
@@ -664,7 +664,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = .
+INPUT                  = include doxygen/input
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -696,7 +696,7 @@
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = configs
+EXCLUDE                =
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
@@ -710,7 +710,7 @@
 # against the file with absolute path, so to exclude all test directories
 # for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       =
+EXCLUDE_PATTERNS       = *_internal.h *_wrap.h
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1485,13 +1485,13 @@
 # which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_SCHEMA             =
+#XML_SCHEMA             =
 
 # The XML_DTD tag can be used to specify an XML DTD,
 # which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_DTD                =
+#XML_DTD                =
 
 # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
 # dump the program listings (including syntax highlighting
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index f9ae71e..a111d29 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -991,7 +991,7 @@
 /**
  * \def MBEDTLS_SSL_RENEGOTIATION
  *
- * Disable support for TLS renegotiation.
+ * Enable support for TLS renegotiation.
  *
  * The two main uses of renegotiation are (1) refresh keys on long-lived
  * connections and (2) client authentication after the initial handshake.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index d98e5ed..1fe8d8c 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1998,13 +1998,14 @@
 /**
  * \brief          Return the result of the certificate verification
  *
- * \param ssl      SSL context
+ * \param ssl      The SSL context to use.
  *
- * \return         0 if successful,
- *                 -1 if result is not available (eg because the handshake was
- *                 aborted too early), or
- *                 a combination of BADCERT_xxx and BADCRL_xxx flags, see
- *                 x509.h
+ * \return         \c 0 if the certificate verification was successful.
+ * \return         \c -1u if the result is not available. This may happen
+ *                 e.g. if the handshake aborts early, or a verification
+ *                 callback returned a fatal error.
+ * \return         A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX
+ *                 and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h.
  */
 uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl );
 
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index 7d78ac4..393bc35 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -39,16 +39,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  1
-#define MBEDTLS_VERSION_PATCH  15
+#define MBEDTLS_VERSION_PATCH  16
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02010F00
-#define MBEDTLS_VERSION_STRING         "2.1.15"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.1.15"
+#define MBEDTLS_VERSION_NUMBER         0x02011000
+#define MBEDTLS_VERSION_STRING         "2.1.16"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.1.16"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index e5a9546..caef16d 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -138,15 +138,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.15 SOVERSION 0)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.16 SOVERSION 0)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.1.15 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.1.16 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.1.15 SOVERSION 10)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.1.16 SOVERSION 10)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/bignum.c b/library/bignum.c
index 165cf87..61aa961 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -2043,12 +2043,12 @@
 /*
  * Miller-Rabin pseudo-primality test  (HAC 4.24)
  */
-static int mpi_miller_rabin( const mbedtls_mpi *X,
+static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
                              int (*f_rng)(void *, unsigned char *, size_t),
                              void *p_rng )
 {
     int ret, count;
-    size_t i, j, k, n, s;
+    size_t i, j, k, s;
     mbedtls_mpi W, R, T, A, RR;
 
     mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
@@ -2064,27 +2064,12 @@
     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
 
     i = mbedtls_mpi_bitlen( X );
-    /*
-     * HAC, table 4.4
-     */
-    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
-          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
-          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
 
-    for( i = 0; i < n; i++ )
+    for( i = 0; i < rounds; i++ )
     {
         /*
          * pick a random A, 1 < A < |X| - 1
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
-
-        if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
-        {
-            j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
-        }
-        A.p[0] |= 3;
-
         count = 0;
         do {
             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
@@ -2092,7 +2077,7 @@
             j = mbedtls_mpi_bitlen( &A );
             k = mbedtls_mpi_bitlen( &W );
             if (j > k) {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
+                A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
             }
 
             if (count++ > 30) {
@@ -2147,7 +2132,7 @@
 /*
  * Pseudo-primality test: small factors, then Miller-Rabin
  */
-int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
+static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
                   int (*f_rng)(void *, unsigned char *, size_t),
                   void *p_rng )
 {
@@ -2173,7 +2158,17 @@
         return( ret );
     }
 
-    return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+    return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
+}
+
+/*
+ * Pseudo-primality test, error probability 2^-80
+ */
+int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng )
+{
+    return mpi_is_prime_internal( X, 40, f_rng, p_rng );
 }
 
 /*
@@ -2185,6 +2180,7 @@
 {
     int ret;
     size_t k, n;
+    int rounds;
     mbedtls_mpi_uint r;
     mbedtls_mpi Y;
 
@@ -2195,6 +2191,13 @@
 
     n = BITS_TO_LIMBS( nbits );
 
+    /*
+     * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
+     */
+    rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
+               ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
+               ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
+
     MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
 
     k = mbedtls_mpi_bitlen( X );
@@ -2206,7 +2209,7 @@
 
     if( dh_flag == 0 )
     {
-        while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+        while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
         {
             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
                 goto cleanup;
@@ -2242,8 +2245,10 @@
              */
             if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
                 ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
-                ( ret = mpi_miller_rabin(  X, f_rng, p_rng  ) ) == 0 &&
-                ( ret = mpi_miller_rabin( &Y, f_rng, p_rng  ) ) == 0 )
+                ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
+                                                                == 0 &&
+                ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
+                                                                == 0 )
             {
                 break;
             }
diff --git a/library/cipher.c b/library/cipher.c
index fe34929..5784f06 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -192,9 +192,13 @@
                    const unsigned char *iv, size_t iv_len )
 {
     size_t actual_iv_size;
-
-    if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+    if( NULL == ctx || NULL == ctx->cipher_info )
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    else if( NULL == iv && iv_len != 0  )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if( NULL == iv && iv_len == 0 )
+        ctx->iv_size = 0;
 
     /* avoid buffer overflow in ctx->iv */
     if( iv_len > MBEDTLS_MAX_IV_LENGTH )
@@ -210,9 +214,11 @@
         if( actual_iv_size > iv_len )
             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     }
-
-    memcpy( ctx->iv, iv, actual_iv_size );
-    ctx->iv_size = actual_iv_size;
+    if ( actual_iv_size != 0 )
+    {
+        memcpy( ctx->iv, iv, actual_iv_size );
+        ctx->iv_size = actual_iv_size;
+    }
 
     return( 0 );
 }
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index dc76af8..dbc5d3f 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -204,7 +204,7 @@
     MBEDTLS_MODE_ECB,
     128,
     "AES-128-ECB",
-    16,
+    0,
     0,
     16,
     &aes_info
@@ -215,7 +215,7 @@
     MBEDTLS_MODE_ECB,
     192,
     "AES-192-ECB",
-    16,
+    0,
     0,
     16,
     &aes_info
@@ -226,7 +226,7 @@
     MBEDTLS_MODE_ECB,
     256,
     "AES-256-ECB",
-    16,
+    0,
     0,
     16,
     &aes_info
diff --git a/library/pkparse.c b/library/pkparse.c
index a899082..be9d829 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -1239,6 +1239,7 @@
         return( 0 );
 
     mbedtls_pk_free( pk );
+    mbedtls_pk_init( pk );
 
     if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
     {
@@ -1250,39 +1251,42 @@
         return( 0 );
 
     mbedtls_pk_free( pk );
+    mbedtls_pk_init( pk );
 
 #if defined(MBEDTLS_RSA_C)
 
     pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
-    if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
-        ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
-                                        key, keylen ) ) != 0 )
-    {
-        mbedtls_pk_free( pk );
-    }
-    else
+    if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
+        pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
     {
         return( 0 );
     }
 
+    mbedtls_pk_free( pk );
+    mbedtls_pk_init( pk );
 #endif /* MBEDTLS_RSA_C */
 
 #if defined(MBEDTLS_ECP_C)
-
     pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
-    if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
-        ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
-                                       key, keylen ) ) != 0 )
-    {
-        mbedtls_pk_free( pk );
-    }
-    else
+    if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
+        pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
+                               key, keylen ) == 0 )
     {
         return( 0 );
     }
-
+    mbedtls_pk_free( pk );
 #endif /* MBEDTLS_ECP_C */
 
+    /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
+     * it is ok to leave the PK context initialized but not
+     * freed: It is the caller's responsibility to call pk_init()
+     * before calling this function, and to call pk_free()
+     * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
+     * isn't, this leads to mbedtls_pk_free() being called
+     * twice, once here and once by the caller, but this is
+     * also ok and in line with the mbedtls_pk_free() calls
+     * on failed PEM parsing attempts. */
+
     return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
 }
 
diff --git a/library/platform.c b/library/platform.c
index e90dc3c..2cdfe70 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -29,7 +29,14 @@
 
 #include "mbedtls/platform.h"
 
-#if defined(MBEDTLS_PLATFORM_MEMORY)
+/* The compile time configuration of memory allocation via the macros
+ * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
+ * configuration via mbedtls_platform_set_calloc_free(). So, omit everything
+ * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
+#if defined(MBEDTLS_PLATFORM_MEMORY) &&                 \
+    !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&        \
+       defined(MBEDTLS_PLATFORM_FREE_MACRO) )
+
 #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
 static void *platform_calloc_uninit( size_t n, size_t size )
 {
@@ -60,7 +67,9 @@
     mbedtls_free = free_func;
     return( 0 );
 }
-#endif /* MBEDTLS_PLATFORM_MEMORY */
+#endif /* MBEDTLS_PLATFORM_MEMORY &&
+          !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
+             defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
 
 #if defined(_WIN32)
 #include <stdarg.h>
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 8e5c02b..0c3f1a8 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1884,7 +1884,7 @@
      *
      * opaque psk_identity_hint<0..2^16-1>;
      */
-    if( (*p) > end - 2 )
+    if( end - (*p) < 2 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
                                     "(psk_identity_hint length)" ) );
@@ -1893,7 +1893,7 @@
     len = (*p)[0] << 8 | (*p)[1];
     *p += 2;
 
-    if( (*p) > end -len )
+    if( end - (*p) < (int) len )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
                                     "(psk_identity_hint length)" ) );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 8091795..4d3aa91 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2110,13 +2110,13 @@
             correct = 0;
         }
         auth_done++;
-
-        /*
-         * Finally check the correct flag
-         */
-        if( correct == 0 )
-            return( MBEDTLS_ERR_SSL_INVALID_MAC );
     }
+
+    /*
+     * Finally check the correct flag
+     */
+    if( correct == 0 )
+        return( MBEDTLS_ERR_SSL_INVALID_MAC );
 #endif /* SSL_SOME_MODES_USE_MAC */
 
     /* Make extra sure authentication was performed, exactly once */
@@ -3212,6 +3212,7 @@
 
     memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
 
+    mbedtls_zeroize( ssl->handshake->hs_msg, ssl->in_hslen );
     mbedtls_free( ssl->handshake->hs_msg );
     ssl->handshake->hs_msg = NULL;
 
diff --git a/library/timing.c b/library/timing.c
index d9db5d2..4feb79d 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -46,6 +46,7 @@
 
 #include <windows.h>
 #include <winbase.h>
+#include <process.h>
 
 struct _hr_time
 {
@@ -261,18 +262,17 @@
 /* It's OK to use a global because alarm() is supposed to be global anyway */
 static DWORD alarmMs;
 
-static DWORD WINAPI TimerProc( LPVOID TimerContext )
+static void TimerProc( void *TimerContext )
 {
-    ((void) TimerContext);
+    (void) TimerContext;
     Sleep( alarmMs );
     mbedtls_timing_alarmed = 1;
-    return( TRUE );
+    /* _endthread will be called implicitly on return
+     * That ensures execution of thread funcition's epilogue */
 }
 
 void mbedtls_set_alarm( int seconds )
 {
-    DWORD ThreadId;
-
     if( seconds == 0 )
     {
         /* No need to create a thread for this simple case.
@@ -283,7 +283,7 @@
 
     mbedtls_timing_alarmed = 0;
     alarmMs = seconds * 1000;
-    CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
+    (void) _beginthread( TimerProc, 0, NULL );
 }
 
 #else /* _WIN32 && !EFIX64 && !EFI32 */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 86fba64..c9177ef 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -40,7 +40,6 @@
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/oid.h"
 
-#include <stdio.h>
 #include <string.h>
 
 #if defined(MBEDTLS_PEM_PARSE_C)
@@ -50,6 +49,7 @@
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
+#include <stdio.h>
 #include <stdlib.h>
 #define mbedtls_free       free
 #define mbedtls_calloc    calloc
@@ -216,6 +216,135 @@
 }
 
 /*
+ * Like memcmp, but case-insensitive and always returns -1 if different
+ */
+static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
+{
+    size_t i;
+    unsigned char diff;
+    const unsigned char *n1 = s1, *n2 = s2;
+
+    for( i = 0; i < len; i++ )
+    {
+        diff = n1[i] ^ n2[i];
+
+        if( diff == 0 )
+            continue;
+
+        if( diff == 32 &&
+            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
+        {
+            continue;
+        }
+
+        return( -1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Return 0 if name matches wildcard, -1 otherwise
+ */
+static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name )
+{
+    size_t i;
+    size_t cn_idx = 0, cn_len = strlen( cn );
+
+    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+        return( 0 );
+
+    for( i = 0; i < cn_len; ++i )
+    {
+        if( cn[i] == '.' )
+        {
+            cn_idx = i;
+            break;
+        }
+    }
+
+    if( cn_idx == 0 )
+        return( -1 );
+
+    if( cn_len - cn_idx == name->len - 1 &&
+        x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+    {
+        return( 0 );
+    }
+
+    return( -1 );
+}
+
+/*
+ * Compare two X.509 strings, case-insensitive, and allowing for some encoding
+ * variations (but not all).
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
+{
+    if( a->tag == b->tag &&
+        a->len == b->len &&
+        memcmp( a->p, b->p, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+        ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+        a->len == b->len &&
+        x509_memcasecmp( a->p, b->p, b->len ) == 0 )
+    {
+        return( 0 );
+    }
+
+    return( -1 );
+}
+
+/*
+ * Compare two X.509 Names (aka rdnSequence).
+ *
+ * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
+ * we sometimes return unequal when the full algorithm would return equal,
+ * but never the other way. (In particular, we don't do Unicode normalisation
+ * or space folding.)
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
+{
+    /* Avoid recursion, it might not be optimised by the compiler */
+    while( a != NULL || b != NULL )
+    {
+        if( a == NULL || b == NULL )
+            return( -1 );
+
+        /* type */
+        if( a->oid.tag != b->oid.tag ||
+            a->oid.len != b->oid.len ||
+            memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
+        {
+            return( -1 );
+        }
+
+        /* value */
+        if( x509_string_cmp( &a->val, &b->val ) != 0 )
+            return( -1 );
+
+        /* structure of the list of sets */
+        if( a->next_merged != b->next_merged )
+            return( -1 );
+
+        a = a->next;
+        b = b->next;
+    }
+
+    /* a == NULL == b */
+    return( 0 );
+}
+
+/*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
 static int x509_get_version( unsigned char **p,
@@ -1643,9 +1772,7 @@
     while( crl_list != NULL )
     {
         if( crl_list->version == 0 ||
-            crl_list->issuer_raw.len != ca->subject_raw.len ||
-            memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
-                    crl_list->issuer_raw.len ) != 0 )
+            x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
         {
             crl_list = crl_list->next;
             continue;
@@ -1655,7 +1782,8 @@
          * Check if the CA is configured to sign CRLs
          */
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-        if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
+        if( mbedtls_x509_crt_check_key_usage( ca,
+                                              MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
         {
             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
             break;
@@ -1716,135 +1844,6 @@
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
 
 /*
- * Like memcmp, but case-insensitive and always returns -1 if different
- */
-static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
-{
-    size_t i;
-    unsigned char diff;
-    const unsigned char *n1 = s1, *n2 = s2;
-
-    for( i = 0; i < len; i++ )
-    {
-        diff = n1[i] ^ n2[i];
-
-        if( diff == 0 )
-            continue;
-
-        if( diff == 32 &&
-            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
-              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
-        {
-            continue;
-        }
-
-        return( -1 );
-    }
-
-    return( 0 );
-}
-
-/*
- * Return 0 if name matches wildcard, -1 otherwise
- */
-static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name )
-{
-    size_t i;
-    size_t cn_idx = 0, cn_len = strlen( cn );
-
-    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
-        return( 0 );
-
-    for( i = 0; i < cn_len; ++i )
-    {
-        if( cn[i] == '.' )
-        {
-            cn_idx = i;
-            break;
-        }
-    }
-
-    if( cn_idx == 0 )
-        return( -1 );
-
-    if( cn_len - cn_idx == name->len - 1 &&
-        x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
-    {
-        return( 0 );
-    }
-
-    return( -1 );
-}
-
-/*
- * Compare two X.509 strings, case-insensitive, and allowing for some encoding
- * variations (but not all).
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
-{
-    if( a->tag == b->tag &&
-        a->len == b->len &&
-        memcmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
-    }
-
-    if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
-        ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
-        a->len == b->len &&
-        x509_memcasecmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
-    }
-
-    return( -1 );
-}
-
-/*
- * Compare two X.509 Names (aka rdnSequence).
- *
- * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
- * we sometimes return unequal when the full algorithm would return equal,
- * but never the other way. (In particular, we don't do Unicode normalisation
- * or space folding.)
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
-{
-    /* Avoid recursion, it might not be optimised by the compiler */
-    while( a != NULL || b != NULL )
-    {
-        if( a == NULL || b == NULL )
-            return( -1 );
-
-        /* type */
-        if( a->oid.tag != b->oid.tag ||
-            a->oid.len != b->oid.len ||
-            memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
-        {
-            return( -1 );
-        }
-
-        /* value */
-        if( x509_string_cmp( &a->val, &b->val ) != 0 )
-            return( -1 );
-
-        /* structure of the list of sets */
-        if( a->next_merged != b->next_merged )
-            return( -1 );
-
-        a = a->next;
-        b = b->next;
-    }
-
-    /* a == NULL == b */
-    return( 0 );
-}
-
-/*
  * Check if 'parent' is a suitable parent (signing CA) for 'child'.
  * Return 0 if yes, -1 if not.
  *
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index de9d422..939c927 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -69,6 +69,12 @@
     return( 0 );
 }
 #else
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 int main( int argc, char *argv[] )
 {
     int ret = 1;
@@ -441,13 +447,13 @@
        the case when the user has missed or reordered some,
        in which case the key might not be in argv[4]. */
     for( i = 0; i < argc; i++ )
-        memset( argv[i], 0, strlen( argv[i] ) );
+        mbedtls_zeroize( argv[i], strlen( argv[i] ) );
 
-    memset( IV,     0, sizeof( IV ) );
-    memset( key,    0, sizeof( key ) );
-    memset( tmp,    0, sizeof( tmp ) );
-    memset( buffer, 0, sizeof( buffer ) );
-    memset( digest, 0, sizeof( digest ) );
+    mbedtls_zeroize( IV,     sizeof( IV ) );
+    mbedtls_zeroize( key,    sizeof( key ) );
+    mbedtls_zeroize( tmp,    sizeof( tmp ) );
+    mbedtls_zeroize( buffer, sizeof( buffer ) );
+    mbedtls_zeroize( digest, sizeof( digest ) );
 
     mbedtls_aes_free( &aes_ctx );
     mbedtls_md_free( &sha_ctx );
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 5885bdb..caad604 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -71,6 +71,12 @@
     return( 0 );
 }
 #else
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 int main( int argc, char *argv[] )
 {
     int ret = 1, i, n;
@@ -533,13 +539,13 @@
        the case when the user has missed or reordered some,
        in which case the key might not be in argv[6]. */
     for( i = 0; i < argc; i++ )
-        memset( argv[i], 0, strlen( argv[i] ) );
+        mbedtls_zeroize( argv[i], strlen( argv[i] ) );
 
-    memset( IV,     0, sizeof( IV ) );
-    memset( key,    0, sizeof( key ) );
-    memset( buffer, 0, sizeof( buffer ) );
-    memset( output, 0, sizeof( output ) );
-    memset( digest, 0, sizeof( digest ) );
+    mbedtls_zeroize( IV,     sizeof( IV ) );
+    mbedtls_zeroize( key,    sizeof( key ) );
+    mbedtls_zeroize( buffer, sizeof( buffer ) );
+    mbedtls_zeroize( output, sizeof( output ) );
+    mbedtls_zeroize( digest, sizeof( digest ) );
 
     mbedtls_cipher_free( &cipher_ctx );
     mbedtls_md_free( &md_ctx );
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 83b0b44..dbae4d7 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -229,6 +229,7 @@
 
     memset( buf, 0, sizeof( buf ) );
 
+    n = dhm.len;
     if( ( ret = mbedtls_net_recv( &client_fd, buf, n ) ) != (int) n )
     {
         mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index 2527d8d..97db808 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -60,9 +60,18 @@
 #include "mbedtls/certs.h"
 #include "mbedtls/timing.h"
 
+/* Uncomment out the following line to default to IPv4 and disable IPv6 */
+//#define FORCE_IPV4
+
 #define SERVER_PORT "4433"
 #define SERVER_NAME "localhost"
-#define SERVER_ADDR "127.0.0.1" /* forces IPv4 */
+
+#ifdef FORCE_IPV4
+#define SERVER_ADDR "127.0.0.1"     /* Forces IPv4 */
+#else
+#define SERVER_ADDR "::1"
+#endif
+
 #define MESSAGE     "Echo this"
 
 #define READ_TIMEOUT_MS 1000
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index df0fc78..4f8177f 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -33,6 +33,15 @@
 #define mbedtls_fprintf    fprintf
 #endif
 
+/* Uncomment out the following line to default to IPv4 and disable IPv6 */
+//#define FORCE_IPV4
+
+#ifdef FORCE_IPV4
+#define BIND_IP     "0.0.0.0"     /* Forces IPv4 */
+#else
+#define BIND_IP     "::"
+#endif
+
 #if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ||    \
     !defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) ||          \
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||        \
@@ -169,7 +178,7 @@
     printf( "  . Bind on udp/*/4433 ..." );
     fflush( stdout );
 
-    if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
+    if( ( ret = mbedtls_net_bind( &listen_fd, BIND_IP, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
     {
         printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 5e6a705..a291696 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -94,6 +94,10 @@
 #include <windows.h>
 #endif
 
+/* Size of memory to be allocated for the heap, when using the library's memory
+ * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */
+#define MEMORY_HEAP_SIZE        120000
+
 #define DFL_SERVER_ADDR         NULL
 #define DFL_SERVER_PORT         "4433"
 #define DFL_RESPONSE_SIZE       -1
@@ -887,7 +891,7 @@
     const char *alpn_list[ALPN_LIST_SIZE];
 #endif
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    unsigned char alloc_buf[100000];
+    unsigned char alloc_buf[MEMORY_HEAP_SIZE];
 #endif
 
     int i;
@@ -2495,6 +2499,8 @@
     mbedtls_ssl_cookie_free( &cookie_ctx );
 #endif
 
+    mbedtls_free( buf );
+
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
 #if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_status();
@@ -2502,7 +2508,6 @@
     mbedtls_memory_buffer_alloc_free();
 #endif
 
-    mbedtls_free( buf );
     mbedtls_printf( " done.\n" );
 
 #if defined(_WIN32)
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index e4f3643..f3de95d 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -238,6 +238,7 @@
     mbedtls_pk_init( &loaded_subject_key );
     mbedtls_mpi_init( &serial );
     mbedtls_ctr_drbg_init( &ctr_drbg );
+    mbedtls_entropy_init( &entropy );
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
     mbedtls_x509_csr_init( &csr );
 #endif
@@ -472,7 +473,6 @@
     mbedtls_printf( "  . Seeding the random number generator..." );
     fflush( stdout );
 
-    mbedtls_entropy_init( &entropy );
     if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                                (const unsigned char *) pers,
                                strlen( pers ) ) ) != 0 )
@@ -789,6 +789,10 @@
     mbedtls_printf( " ok\n" );
 
 exit:
+#if defined(MBEDTLS_X509_CSR_PARSE_C)
+    mbedtls_x509_csr_free( &csr );
+#endif /* MBEDTLS_X509_CSR_PARSE_C */
+    mbedtls_x509_crt_free( &issuer_crt );
     mbedtls_x509write_crt_free( &crt );
     mbedtls_pk_free( &loaded_subject_key );
     mbedtls_pk_free( &loaded_issuer_key );
diff --git a/scripts/apidoc_full.sh b/scripts/apidoc_full.sh
new file mode 100755
index 0000000..bebab10
--- /dev/null
+++ b/scripts/apidoc_full.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Generate doxygen documentation with a full config.h (this ensures that every
+# available flag is documented, and avoids warnings about documentation
+# without a corresponding #define).
+#
+# /!\ This must not be a Makefile target, as it would create a race condition
+# when multiple targets are invoked in the same parallel build.
+
+set -eu
+
+CONFIG_H='include/mbedtls/config.h'
+
+if [ -r $CONFIG_H ]; then :; else
+    echo "$CONFIG_H not found" >&2
+    exit 1
+fi
+
+CONFIG_BAK=${CONFIG_H}.bak
+cp -p $CONFIG_H $CONFIG_BAK
+
+scripts/config.pl realfull
+make apidoc
+
+mv $CONFIG_BAK $CONFIG_H
diff --git a/tests/.jenkins/Jenkinsfile b/tests/.jenkins/Jenkinsfile
new file mode 100644
index 0000000..ed04053
--- /dev/null
+++ b/tests/.jenkins/Jenkinsfile
@@ -0,0 +1 @@
+mbedtls.run_job()
diff --git a/tests/data_files/test-ca_printable.crt b/tests/data_files/test-ca_printable.crt
new file mode 100644
index 0000000..d16da09
--- /dev/null
+++ b/tests/data_files/test-ca_printable.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH
+/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV
+BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz
+dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ
+SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H
+DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF
+pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf
+m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ
+7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca_uppercase.crt b/tests/data_files/test-ca_uppercase.crt
new file mode 100644
index 0000000..e8b537c
--- /dev/null
+++ b/tests/data_files/test-ca_uppercase.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/
+MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA
+A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI
+yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv
+czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST
+S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM
+iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS
+NWqiX9GyusBZjezaCaHabjDLU0qQ
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca_utf8.crt b/tests/data_files/test-ca_utf8.crt
new file mode 100644
index 0000000..e8b537c
--- /dev/null
+++ b/tests/data_files/test-ca_utf8.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx
+mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny
+50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n
+YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL
+R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu
+KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj
+UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/
+MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA
+A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI
+yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv
+czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST
+S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM
+iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS
+NWqiX9GyusBZjezaCaHabjDLU0qQ
+-----END CERTIFICATE-----
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 53c5e37..ffc5f77 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -384,21 +384,27 @@
 # Indicative running times are given for reference.
 
 msg "test: recursion.pl" # < 1s
-tests/scripts/recursion.pl library/*.c
+record_status tests/scripts/recursion.pl library/*.c
 
 msg "test: freshness of generated source files" # < 1s
-tests/scripts/check-generated-files.sh
+record_status tests/scripts/check-generated-files.sh
 
 msg "test: doxygen markup outside doxygen blocks" # < 1s
-tests/scripts/check-doxy-blocks.pl
+record_status tests/scripts/check-doxy-blocks.pl
 
 msg "test: check-files.py" # < 1s
 cleanup
-tests/scripts/check-files.py
+record_status tests/scripts/check-files.py
 
 msg "test/build: declared and exported names" # < 3s
 cleanup
-tests/scripts/check-names.sh
+record_status tests/scripts/check-names.sh
+
+if which doxygen >/dev/null; then
+    msg "test: doxygen warnings" # ~ 3s
+    cleanup
+    tests/scripts/doxygen.sh
+fi
 
 
 
@@ -440,7 +446,7 @@
 make
 
 msg "test: ssl-opt.sh, MFL-related tests"
-tests/ssl-opt.sh -f "Max fragment length"
+if_build_succeeded tests/ssl-opt.sh -f "Max fragment length"
 
 msg "build: Default + SSLv3 (ASan build)" # ~ 6 min
 cleanup
@@ -484,10 +490,10 @@
 make test
 
 msg "test: RSA_NO_CRT - RSA-related part of ssl-opt.sh (ASan build)" # ~ 5s
-tests/ssl-opt.sh -f RSA
+if_build_succeeded tests/ssl-opt.sh -f RSA
 
 msg "test: RSA_NO_CRT - RSA-related part of compat.sh (ASan build)" # ~ 3 min
-tests/compat.sh -t RSA
+if_build_succeeded tests/compat.sh -t RSA
 
 
 msg "build: cmake, full config, clang" # ~ 50s
@@ -591,6 +597,18 @@
 scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux
 make CC=gcc CFLAGS='-Werror -O0 -std=c99 -pedantic' lib
 
+msg "build: MBEDTLS_PLATFORM_{CALLOC/FREE}_MACRO enabled (ASan build)"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_PLATFORM_MEMORY
+scripts/config.pl set MBEDTLS_PLATFORM_CALLOC_MACRO calloc
+scripts/config.pl set MBEDTLS_PLATFORM_FREE_MACRO   free
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: MBEDTLS_PLATFORM_{CALLOC/FREE}_MACRO enabled (ASan build)"
+make test
+
 if uname -a | grep -F Linux >/dev/null; then
     msg "build/test: make shared" # ~ 40s
     cleanup
diff --git a/tests/scripts/check-files.py b/tests/scripts/check-files.py
index f560d03..0fb2117 100755
--- a/tests/scripts/check-files.py
+++ b/tests/scripts/check-files.py
@@ -155,6 +155,12 @@
             ".c", ".h", ".sh", ".pl", ".py", ".md", ".function", ".data",
             "Makefile", "CMakeLists.txt", "ChangeLog"
         )
+        self.excluded_directories = ['.git', 'mbed-os']
+        self.excluded_paths = list(map(os.path.normpath, [
+            'cov-int',
+            'examples',
+            'yotta/module'
+        ]))
         self.issues_to_check = [
             PermissionIssueTracker(),
             EndOfFileNewlineIssueTracker(),
@@ -179,12 +185,19 @@
             console = logging.StreamHandler()
             self.logger.addHandler(console)
 
+    def prune_branch(self, root, d):
+        if d in self.excluded_directories:
+            return True
+        if os.path.normpath(os.path.join(root, d)) in self.excluded_paths:
+            return True
+        return False
+
     def check_files(self):
-        for root, dirs, files in sorted(os.walk(".")):
+        for root, dirs, files in os.walk("."):
+            dirs[:] = sorted(d for d in dirs if not self.prune_branch(root, d))
             for filename in sorted(files):
                 filepath = os.path.join(root, filename)
-                if (os.path.join("yotta", "module") in filepath or
-                        not filepath.endswith(self.files_to_check)):
+                if not filepath.endswith(self.files_to_check):
                     continue
                 for issue_to_check in self.issues_to_check:
                     if issue_to_check.should_check_file(filepath):
diff --git a/tests/scripts/doxygen.sh b/tests/scripts/doxygen.sh
new file mode 100755
index 0000000..e7758c9
--- /dev/null
+++ b/tests/scripts/doxygen.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Make sure the doxygen documentation builds without warnings
+
+# Abort on errors (and uninitiliased variables)
+set -eu
+
+if [ -d library -a -d include -a -d tests ]; then :; else
+    echo "Must be run from mbed TLS root" >&2
+    exit 1
+fi
+
+if scripts/apidoc_full.sh > doc.out 2>doc.err; then :; else
+    cat doc.err
+    echo "FAIL" >&2
+    exit 1;
+fi
+
+cat doc.out doc.err | \
+    grep -v "warning: ignoring unsupported tag" \
+    > doc.filtered
+
+if egrep "(warning|error):" doc.filtered; then
+    echo "FAIL" >&2
+    exit 1;
+fi
+
+make apidoc_clean
+rm -f doc.out doc.err doc.filtered
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index 5cbc9fe..b93d4de 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -1121,3 +1121,191 @@
 AES-256-ECB Decrypt NIST KAT #12
 depends_on:MBEDTLS_AES_C
 test_vec_ecb:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"9b80eefb7ebe2d2b16247aa0efc72f5d":"e0000000000000000000000000000000":0
+
+AES-128-ECB crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0
+
+AES-128-ECB crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"f0000000000000000000000000000000":"":"00000000000000000000000000000000":"970014d634e2b7650777e8e84d03ccd8":0
+
+AES-128-ECB crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"ffffffffffffffc00000000000000000":"3a4d354f02bb5a5e47d39666867f246a":0
+
+AES-128-ECB crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"":"db4f1aa530967d6732ce4715eb0ee24b":"ff000000000000000000000000000000":0
+
+AES-128-ECB crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"b69418a85332240dc82492353956ae0c":"":"a303d940ded8f0baff6f75414cac5243":"00000000000000000000000000000000":0
+
+AES-128-ECB crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"ffffffffffffffff8000000000000000":"":"32cd652842926aea4aa6137bb2be2b5e":"00000000000000000000000000000000":0
+
+AES-192-ECB crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"fffffffffffffffffffff80000000000":"156f07767a85a4312321f63968338a01":0
+
+AES-192-ECB crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"51719783d3185a535bd75adc65071ce1":"4f354592ff7c8847d2d0870ca9481b7c":0
+
+AES-192-ECB crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"d2926527e0aa9f37b45e2ec2ade5853ef807576104c7ace3":"":"00000000000000000000000000000000":"dd619e1cf204446112e0af2b9afa8f8c":0
+
+AES-192-ECB crypt Encrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"fffffffffffffffffffffffffff800000000000000000000":"":"00000000000000000000000000000000":"8dd274bd0f1b58ae345d9e7233f9b8f3":0
+
+AES-192-ECB crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"fffffffffffffffffffffffffffffffff000000000000000":"":"bb2852c891c5947d2ed44032c421b85f":"00000000000000000000000000000000":0
+
+AES-192-ECB crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"61257134a518a0d57d9d244d45f6498cbc32f2bafc522d79":"":"cfe4d74002696ccf7d87b14a2f9cafc9":"00000000000000000000000000000000":0
+
+AES-192-ECB crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"275cfc0413d8ccb70513c3859b1d0f72":"1b077a6af4b7f98229de786d7516b639":0
+
+AES-192-ECB crypt Decrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"b2099795e88cc158fd75ea133d7e7fbe":"ffffffffffffffffffffc00000000000":0
+
+AES-256-ECB crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c":"":"00000000000000000000000000000000":"352065272169abf9856843927d0674fd":0
+
+AES-256-ECB crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"0b24af36193ce4665f2825d7b4749c98":"a9ff75bd7cf6613d3731c77c3b6d0c04":0
+
+AES-256-ECB crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"ffffff80000000000000000000000000":"36aff0ef7bf3280772cf4cac80a0d2b2":0
+
+AES-256-ECB crypt Encrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"ffffffffffffffffffffffffffffffffffff8000000000000000000000000000":"":"00000000000000000000000000000000":"45d089c36d5c5a4efc689e3b0de10dd5":0
+
+AES-256-ECB crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000":"":"edf61ae362e882ddc0167474a7a77f3a":"00000000000000000000000000000000":0
+
+AES-256-ECB crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"f8be9ba615c5a952cabbca24f68f8593039624d524c816acda2c9183bd917cb9":"":"a3944b95ca0b52043584ef02151926a8":"00000000000000000000000000000000":0
+
+AES-256-ECB crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"623a52fcea5d443e48d9181ab32c7421":"761c1fe41a18acf20d241650611d90f1":0
+
+AES-256-ECB crypt Decrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"ddc6bf790c15760d8d9aeb6f9a75fd4e":"80000000000000000000000000000000":0
+
+AES-128-CBC crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"00000000000000000000000000000000":"80000000000000000000000000000000":"3ad78e726c1ec02b7ebfe92b23d9ec34":0
+
+AES-128-CBC crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_ENCRYPT:"ffffffffffffffffffffffffffffe000":"00000000000000000000000000000000":"00000000000000000000000000000000":"323994cfb9da285a5d9642e1759b224a":0
+
+AES-128-CBC crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_ENCRYPT:"10a58869d74be5a374cf867cfb473859":"00000000000000000000000000000000":"00000000000000000000000000000000":"6d251e6944b051e04eaa6fb4dbf78465":0
+
+AES-128-CBC crypt Encrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"00000000000000000000000000000000":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0
+
+AES-128-CBC crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"00000000000000000000000000000000":"3ad78e726c1ec02b7ebfe92b23d9ec34":"80000000000000000000000000000000":0
+
+AES-128-CBC crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_DECRYPT:"ffffc000000000000000000000000000":"00000000000000000000000000000000":"df556a33438db87bc41b1752c55e5e49":"00000000000000000000000000000000":0
+
+AES-128-CBC crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_DECRYPT:"10a58869d74be5a374cf867cfb473859":"00000000000000000000000000000000":"6d251e6944b051e04eaa6fb4dbf78465":"00000000000000000000000000000000":0
+
+AES-128-CBC crypt Decrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"00000000000000000000000000000000":"0336763e966d92595a567cc9ce537f5e":"f34481ec3cc627bacd5dc3fb08f273e6":0
+
+AES-192-CBC crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"80000000000000000000000000000000":"6cd02513e8d4dc986b4afe087a60bd0c":0
+
+AES-192-CBC crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_ENCRYPT:"ff0000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"00000000000000000000000000000000":"833f71258d53036b02952c76c744f5a1":0
+
+AES-192-CBC crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_ENCRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"00000000000000000000000000000000":"00000000000000000000000000000000":"0956259c9cd5cfd0181cca53380cde06":0
+
+AES-192-CBC crypt Encrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"1b077a6af4b7f98229de786d7516b639":"275cfc0413d8ccb70513c3859b1d0f72":0
+
+AES-192-CBC crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"6cd02513e8d4dc986b4afe087a60bd0c":"80000000000000000000000000000000":0
+
+AES-192-CBC crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_DECRYPT:"ffe000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"7ababc4b3f516c9aafb35f4140b548f9":"00000000000000000000000000000000":0
+
+AES-192-CBC crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_DECRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"00000000000000000000000000000000":"0956259c9cd5cfd0181cca53380cde06":"00000000000000000000000000000000":0
+
+AES-192-CBC crypt Decrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"275cfc0413d8ccb70513c3859b1d0f72":"1b077a6af4b7f98229de786d7516b639":0
+
+AES-256-CBC crypt Encrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"80000000000000000000000000000000":"ddc6bf790c15760d8d9aeb6f9a75fd4e":0
+
+AES-256-CBC crypt Encrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_ENCRYPT:"ff00000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"00000000000000000000000000000000":"ec52a212f80a09df6317021bc2a9819e":0
+
+AES-256-CBC crypt Encrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_ENCRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"00000000000000000000000000000000":"00000000000000000000000000000000":"46f2fb342d6f0ab477476fc501242c5f":0
+
+AES-256-CBC crypt Encrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"014730f80ac625fe84f026c60bfd547d":"5c9d844ed46f9885085e5d6a4f94c7d7":0
+
+AES-256-CBC crypt Decrypt NIST KAT #1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"ddc6bf790c15760d8d9aeb6f9a75fd4e":"80000000000000000000000000000000":0
+
+AES-256-CBC crypt Decrypt NIST KAT #2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"ffe0000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"d1ccb9b1337002cbac42c520b5d67722":"00000000000000000000000000000000":0
+
+AES-256-CBC crypt Decrypt NIST KAT #3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"00000000000000000000000000000000":"46f2fb342d6f0ab477476fc501242c5f":"00000000000000000000000000000000":0
+
+AES-256-CBC crypt Decrypt NIST KAT #4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"5c9d844ed46f9885085e5d6a4f94c7d7":"014730f80ac625fe84f026c60bfd547d":0
+
+Cipher Corner Case behaviours
+depends_on:MBEDTLS_AES_C
+cipher_special_behaviours:
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 8e7b12e..343dd78 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -91,6 +91,55 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
+void cipher_special_behaviours( )
+{
+    const mbedtls_cipher_info_t *cipher_info;
+    mbedtls_cipher_context_t ctx;
+    unsigned char input[32];
+    unsigned char output[32];
+#if defined (MBEDTLS_CIPHER_MODE_CBC)
+    unsigned char iv[32];
+#endif
+    size_t olen = 0;
+
+    mbedtls_cipher_init( &ctx );
+    memset( input, 0, sizeof( input ) );
+    memset( output, 0, sizeof( output ) );
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    memset( iv, 0, sizeof( iv ) );
+
+    /* Check and get info structures */
+    cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_CBC );
+    TEST_ASSERT( NULL != cipher_info );
+
+    TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx, cipher_info ) );
+
+    /* IV too big */
+    TEST_ASSERT( mbedtls_cipher_set_iv( &ctx, iv, MBEDTLS_MAX_IV_LENGTH + 1 )
+                 == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+    /* IV too small */
+    TEST_ASSERT( mbedtls_cipher_set_iv( &ctx, iv, 0 )
+                 == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    mbedtls_cipher_free( &ctx );
+    mbedtls_cipher_init( &ctx );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+    cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
+    TEST_ASSERT( NULL != cipher_info );
+
+    TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx, cipher_info ) );
+
+    /* Update ECB with partial block */
+    TEST_ASSERT( mbedtls_cipher_update( &ctx, input, 1, output, &olen )
+                 == MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void enc_dec_buf( int cipher_id, char *cipher_string, int key_len,
                   int length_val, int pad_mode )
@@ -653,6 +702,55 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_WITH_PADDING */
+void test_vec_crypt( int cipher_id, int operation, char *hex_key,
+                   char *hex_iv, char *hex_input, char *hex_result,
+                   int finish_result )
+{
+    unsigned char key[50];
+    unsigned char input[16];
+    unsigned char result[16];
+    unsigned char iv[16];
+    size_t key_len, iv_len, inputlen, resultlen;
+    mbedtls_cipher_context_t ctx;
+    unsigned char output[32];
+    size_t outlen;
+
+    mbedtls_cipher_init( &ctx );
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( input, 0x00, sizeof( input ) );
+    memset( result, 0x00, sizeof( result ) );
+    memset( output, 0x00, sizeof( output ) );
+    memset( iv, 0x00, sizeof( iv ) );
+
+    /* Prepare context */
+    TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx,
+                                       mbedtls_cipher_info_from_type( cipher_id ) ) );
+
+    key_len = unhexify( key, hex_key );
+    inputlen =  unhexify( input, hex_input );
+    resultlen = unhexify( result, hex_result );
+
+    TEST_ASSERT( 0 == mbedtls_cipher_setkey( &ctx, key, 8 * key_len, operation ) );
+    if( MBEDTLS_MODE_CBC == ctx.cipher_info->mode )
+        TEST_ASSERT( 0 == mbedtls_cipher_set_padding_mode( &ctx, MBEDTLS_PADDING_NONE ) );
+
+    iv_len = unhexify( iv, hex_iv );
+
+    TEST_ASSERT( finish_result == mbedtls_cipher_crypt( &ctx, iv_len ? iv : NULL,
+                                                        iv_len, input, inputlen,
+                                                        output, &outlen ) );
+    TEST_ASSERT( resultlen == outlen );
+    /* check plaintext only if everything went fine */
+    if( 0 == finish_result )
+        TEST_ASSERT( 0 == memcmp( output, result, outlen ) );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_WITH_PADDING */
 void set_padding( int cipher_id, int pad_mode, int ret )
 {
     const mbedtls_cipher_info_t *cipher_info;
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index b730953..9b1315f 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -121,7 +121,8 @@
     md_info = mbedtls_md_info_from_type( md_alg );
     TEST_ASSERT( md_info != NULL );
     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 );
 
     TEST_ASSERT( mbedtls_ecdsa_sign_det( &grp, &r, &s, &d, hash, hlen, md_alg ) == 0 );
 
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 797505a..e8dac5e 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -680,6 +680,14 @@
 depends_on:MBEDTLS_GENPRIME
 mbedtls_mpi_is_prime:10:"49979687":0
 
+Test mbedtls_mpi_is_prime_det (4 non-witnesses)
+depends_on:MBEDTLS_GENPRIME
+mbedtls_mpi_is_prime_det:"043BD64BA10B11DA83FBD296B04BCA9E0552FAF6E09CAC74E2D7E735ED0DB09FC47ED76145644203EE0C826013BC602F560BCDAAED557D04683859A65D659FF828A245A2C5B1AC41E01E4669A525A45E23AF":"040EA852F7935ACCECC0E87B845281F047D10DC9AAFEF990AF9D3D66770DA30B0C5B5E03EEA8C0CB79B936FE0BB8EE5389EC1D34EB16C58AA3F2E11AF084160CDF6400BE1CC179867AB074866952D9F34EE7042D27F960E715A97FCB93F3182247D0A6AE51BD21CC2F6B0651F9E572C5FB86F3137053FA85FD7A51816D69B3A53A5A438C17754836D04E98CA240B901F828332F2D72D88C497DA45F533F99A6E53EDEA6B0424EC8951B048FA9A80134B37D0A67014597934E3CFC52C5A4DD4751ADF8D66FC79E84E2A3148C4B15C17E12CB659390FD275F39A331FFC80EC699BC3F6FAB868E30E9B14575FCDAB6FAED01E00112DD28704177E09C335AD43A696FEA761E8DF3B0663277A5C3637F9060CB5E5654F72E9A6B0F369E660AD4CF7ABF4195493545B367BD55271CD4BB7D9C15D3F508FE8F7409C2126FC8E73B43A67CD4EFB21E9F15DBF040A2A8D5F5ED75CEAC12B595C0051F3EC9D5A58ACE82A9506E64F780E9836728260FFE1BFD73E8A9869E3D46A35A856D3028F7FEAB9F4F1A04449AEDC80017EE1014080D87F0B50C8EF255324CD89F7D039":82:MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+Test mbedtls_mpi_is_prime_det (39 non-witnesses)
+depends_on:MBEDTLS_GENPRIME
+mbedtls_mpi_is_prime_det:"155102B67930FBE8858DF6C0642D77D419A7B7968E622CC7500F3E3F2C5168368C50E0083187":"119B3E2C721834D83416239B04447AA18AE0163E61DCAE97054563D79E094A6FA4485BD6A0501445BF57FE9C058926CDB862E04CC1A95D79D61D9AB3466857A53E04F8D7470C9C86649B226A13DDC534E18DFD5C22FAEA317CA4D4960F18457FD6D2FFB5F3273F74C89980DC774590D8D30D1159CA81999ED94A042D67DA68C82616AD46C2C88288A8EBD0B37AC7C152D9522CA4544642AD1210F6B642FEBF43563FA872B0DEFAFC69D0B6570E8FEA9570D0AADCFA9B06CC8BFD62CEDC221541210EEEF9762448C6D49F26AA767A4D66CB168589E0201923015314E6CD4A480E5936E7CF145F73A564C5B782635B3AFC3028E2632C5D3458224A7C9E8BA1876E8F690463C878292D3DC011E9640331E7F7621F2B5E0F6713DD8C9D6767521C4BA880DA8D11C67753C8493D2C4C4F1443147550D0B25B7FAD04EAFA9F8AA60974C1365C8A794CFEECEB4279B1150909A97E5A7A10B5D91186CA5B25A612036631FE73529C8CFAE51E76FB704A772DE5320EFC1212E7A399B1FEBF57D014AF9129DFF5D2C5DFBBEEAC55F360CF6D22FA90B8E2E9AD0C71AB6495A9452A58D653B8CC26128C66B43EFBA6E39AEC5717A1A3C2AE1449FCABAFE1180B159DA55190CD81A3D9E8D798647E11B827F0A057D6DA5AAD78AB5112EE65E10E8B8B369BA24E1B8AD2CD8548C497016C07A143DE1232F8059BE303572456FA92E76A0F23D1340629228B7D27C02D3833A72745B91A3DBEB5E081117A9F19597F00E4277B414FAEA8C8CEB895C37F956A5A22F8D7A10ADA50B22BAB312504904511AA0EFDD4D3BF20ECB17E8A684564FFB5BBD5E22C429F9A75A4FB4AE468FE7612ED53C7A11212E7EF3435CC9CA6E7DB167B8CCE2BECF35F89013F8F876223C77FA81570970858663C6E32B91080AA47F9C90177F51E6FD7747B910C9489C7B6ACB070996198AD9A40A69711274159210A9A12DBAAA4FB4632446066AB70D735DC95F7C2BCE517E88C064D728DE82B1B043DF4AEE0EFF5131120A4E5B9B4180EB6F6B8A0D1491ABDA069058A9966B1A517D8E7B4997DC52A1E698FD79E271153DF1913FE6787A5D99DE69F39C3F22D26DC731CFBB33FF5C267D85D7A3DAE8E1C87E1DB2F1236212EF1942EA756967FB3D07D629E59EA4034D9A9B5E270DD4A31C8A3DFDA99C1094B5537132C196DA2AEAF5253A019B9AF25B5DCB0D4DD75C7C9C353DA9DAABFB23959A5455312E7E1C21268C1BC14E83DCFDF50C27FD3E8B4EDC04C5F3CB5FCFFF2B57151E1B1EE1A6456DC006BC43E1158674AA4CF7D146DE4A57103BE43ED130C8007294ED2418C7A2B769A7D20EBB5A8367A77B313F81BB119B9954305FF160FF83EED7F808EE6D340A5CCC000CF81AA497D315D350CCE4E86A31456B8AA85B677491FC662933DFA55EB5BFF64B8D85430D676A85D1CAFAFF383E68C4E6C22A51063739EC03FC58C36C07C44E54828BE2152B2E9AFB0F179B157D09B64C147B524BB5424BB1914419424D9100D06EDCFC718F4DF3D562E9E16C446663F35273CA7BC5426B868A80C8D415C9A12A1619CDB7CDB5BEBC70313150BDF8C3AB26B809FE62D28E798EF1EF98C410A2DA0A9071F82154AC569078B0E647E2C085D1D907E634453442803D0492D3D0C78CACB762020C0E589C8B0981321EA2771305FD0413F3B2963FCE9A232F6641DB7E12ADC009A032063C41756E5E19E5711DE12711F07AFE7545B4D83F3EFD7BFD0435297C89DF3D4AF96EBE2CE8D64B93E36EA5D7E5A0492151D0CAEE7449A7D35E1A3C83E22C3B35162C073CC3B1CF76FBDEE84270721FC042EAAEB7325110181415E2031CFB7462F15111291CDAC0560FF9F4C7341F2FA261B97CEF348D074AA2EB4DB153FE6B1410519DA4213B611999868F3B867A2B6D758D333C4989DE80782683CA26ECDE373C71524F01B76349CE8A07A5EBECBB42259CF970DDA756EC996B189FEA045FEE45F23D476960913106ECA2510B8517AA75D56FA4152B2BDDC212014E5D07FD964D6EE532F0616DF74E104659955132331FABF2D2AD265E71C93C648A956FA0A3DB21FF103D516527F2DA0E870340B61EE8A8ED913B60605EB5A67B834D0FC90564386012585609870FEF6530B3E3C037B55506F0B5694F6B0FC":38:MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
 Test mbedtls_mpi_gen_prime (Too small)
 depends_on:MBEDTLS_GENPRIME
 mbedtls_mpi_gen_prime:2:0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 6ceae15..952cac4 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -1,5 +1,49 @@
 /* BEGIN_HEADER */
 #include "mbedtls/bignum.h"
+
+typedef struct mbedtls_test_mpi_random
+{
+    uint8_t     *data;
+    uint32_t    data_len;
+    size_t      pos;
+    size_t      chunk_len;
+} mbedtls_test_mpi_random;
+
+/*
+ * This function is called by the Miller-Rabin primality test each time it
+ * chooses a random witness. The witnesses (or non-witnesses as provided by the
+ * test) are stored in the data member of the state structure. Each number is in
+ * the format that mbedtls_mpi_read_string understands and is chunk_len long.
+ */
+int mbedtls_test_mpi_miller_rabin_determinizer( void* state,
+                                                unsigned char* buf,
+                                                size_t len )
+{
+    mbedtls_test_mpi_random *random = (mbedtls_test_mpi_random*) state;
+
+    if( random == NULL || random->data == NULL || buf == NULL )
+        return( -1 );
+
+    if( random->pos + random->chunk_len > random->data_len
+            || random->chunk_len > len )
+    {
+        return( -1 );
+    }
+
+    memset( buf, 0, len );
+
+    /* The witness is written to the end of the buffer, since the buffer is
+     * used as big endian, unsigned binary data in mbedtls_mpi_read_binary.
+     * Writing the witness to the start of the buffer would result in the
+     * buffer being 'witness 000...000', which would be treated as
+     * witness * 2^n for some n. */
+    memcpy( buf + len - random->chunk_len, &random->data[random->pos],
+            random->chunk_len );
+
+    random->pos += random->chunk_len;
+
+    return( 0 );
+}
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -806,6 +850,39 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_GENPRIME */
+void mbedtls_mpi_is_prime_det( char *input_X, char *witnesses,
+                               int chunk_len, int div_result )
+{
+    mbedtls_mpi X;
+    int res;
+    mbedtls_test_mpi_random rand;
+    uint8_t *witness_buf = NULL;
+    uint8_t *input_buf = NULL;
+    size_t witness_len;
+    size_t input_len;
+
+    witness_buf = unhexify_alloc( witnesses, &witness_len );
+    input_buf = unhexify_alloc( input_X, &input_len );
+
+    mbedtls_mpi_init( &X );
+    rand.data = witness_buf;
+    rand.data_len = witness_len;
+    rand.pos = 0;
+    rand.chunk_len = chunk_len;
+
+    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_buf, input_len ) == 0 );
+    res = mbedtls_mpi_is_prime( &X, mbedtls_test_mpi_miller_rabin_determinizer,
+                                    &rand );
+    TEST_ASSERT( res == div_result );
+
+exit:
+    mbedtls_mpi_free( &X );
+    mbedtls_free( witness_buf );
+    mbedtls_free( input_buf );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_GENPRIME */
 void mbedtls_mpi_gen_prime( int bits, int safe, int ref_ret )
 {
     mbedtls_mpi X;
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 4db9f94..a8660fb 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.1.15"
+check_compiletime_version:"2.1.16"
 
 Check runtime library version
-check_runtime_version:"2.1.15"
+check_runtime_version:"2.1.16"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 3e23825..099c4d1 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -399,6 +399,18 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_HAVE_TIME_DATE
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_REVOKED:"compat":"NULL"
 
+X509 Certificate verification #5' (Revoked Cert, differing DN string formats #1)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_HAVE_TIME_DATE
+x509_verify:"data_files/server1.crt":"data_files/test-ca_utf8.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_REVOKED:"compat":"NULL"
+
+X509 Certificate verification #5'' (Revoked Cert, differing DN string formats #2)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_HAVE_TIME_DATE
+x509_verify:"data_files/server1.crt":"data_files/test-ca_printable.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_REVOKED:"compat":"NULL"
+
+X509 Certificate verification #5''' (Revoked Cert, differing upper and lower case)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_HAVE_TIME_DATE
+x509_verify:"data_files/server1.crt":"data_files/test-ca_uppercase.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_REVOKED:"compat":"NULL"
+
 X509 Certificate verification #6 (Revoked Cert)
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_HAVE_TIME_DATE
 x509_verify:"data_files/server1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"PolarSSL Server 1":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_REVOKED:"compat":"NULL"
diff --git a/yotta/data/module.json b/yotta/data/module.json
index e9d2578..8e62441 100644
--- a/yotta/data/module.json
+++ b/yotta/data/module.json
@@ -1,6 +1,6 @@
 {
     "name": "mbedtls",
-    "version": "2.1.15",
+    "version": "2.1.16",
     "description": "The mbed TLS crypto/SSL/TLS library",
     "licenses": [
         {