Merge pull request #2949 from zfields/patch-1

[cmake] Propagate public headers
diff --git a/ChangeLog b/ChangeLog
index c6210d1..e184c96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,66 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
-= mbed TLS 2.20.0 branch released xxxx-xx-xx
+= mbed TLS X.X.X branch released XXXX-XX-XX
+
+Bugfix
+   * Allow loading symlinked certificates. Fixes #3005. Reported and fixed
+     by Jonathan Bennett <JBennett@incomsystems.biz> via #3008.
+   * Fix an unchecked call to mbedtls_md() in the x509write module.
+
+= mbed TLS 2.20.0 branch released 2020-01-15
+
+Default behavior changes
+   * The initial seeding of a CTR_DRBG instance makes a second call to the
+     entropy function to obtain entropy for a nonce if the entropy size is less
+     than 3/2 times the key size. In case you want to disable the extra call to
+     grab entropy, you can call mbedtls_ctr_drbg_set_nonce_len() to force the
+     nonce length to 0.
+
+Security
+   * Enforce that mbedtls_entropy_func() gathers a total of
+     MBEDTLS_ENTROPY_BLOCK_SIZE bytes or more from strong sources. In the
+     default configuration, on a platform with a single entropy source, the
+     entropy module formerly only grabbed 32 bytes, which is good enough for
+     security if the source is genuinely strong, but less than the expected 64
+     bytes (size of the entropy accumulator).
+   * 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. 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.
+   * 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.
+
+Features
+   * Key derivation inputs in the PSA API can now either come from a key object
+     or from a buffer regardless of the step type.
+   * The CTR_DRBG module can grab a nonce from the entropy source during the
+     initial seeding. The default nonce length is chosen based on the key size
+     to achieve the security strength defined by NIST SP 800-90A. You can
+     change it with mbedtls_ctr_drbg_set_nonce_len().
+   * Add ENUMERATED tag support to the ASN.1 module. Contributed by
+     msopiha-linaro in ARMmbed/mbed-crypto#307.
+
+API changes
+   * In the PSA API, forbid zero-length keys. To pass a zero-length input to a
+     key derivation function, use a buffer instead (this is now always
+     possible).
+   * Rename psa_asymmetric_sign() to psa_sign_hash() and
+     psa_asymmetric_verify() to psa_verify_hash().
 
 Bugfix
    * Fix an incorrect size in a debugging message. Reported and fix
@@ -9,6 +69,34 @@
      Reported and fix submitted by irwir. Fixes #2800.
    * Remove a useless assignment. Reported and fix submitted by irwir.
      Fixes #2801.
+   * Fix a buffer overflow in the PSA HMAC code when using a long key with an
+     unsupported algorithm. Fixes ARMmbed/mbed-crypto#254.
+   * Fix mbedtls_asn1_get_int to support any number of leading zeros. Credit
+     to OSS-Fuzz for finding a bug in an intermediate version of the fix.
+   * Fix mbedtls_asn1_get_bitstring_null to correctly parse bitstrings of at
+     most 2 bytes.
+   * mbedtls_ctr_drbg_set_entropy_len() and
+     mbedtls_hmac_drbg_set_entropy_len() now work if you call them before
+     mbedtls_ctr_drbg_seed() or mbedtls_hmac_drbg_seed().
+   * Fix some false-positive uninitialized variable warnings. Fix contributed
+     by apple-ihack-geek in #2663.
+
+Changes
+   * Remove the technical possibility to define custom mbedtls_md_info
+     structures, which was exposed only in an internal header.
+   * psa_close_key(0) and psa_destroy_key(0) now succeed (doing nothing, as
+     before).
+   * Variables containing error codes are now initialized to an error code
+     rather than success, so that coding mistakes or memory corruption tends to
+     cause functions to return this error code rather than a success. There are
+     no known instances where this changes the behavior of the library: this is
+     merely a robustness improvement. ARMmbed/mbed-crypto#323
+   * Remove a useless call to mbedtls_ecp_group_free(). Contributed by
+     Alexander Krizhanovsky in ARMmbed/mbed-crypto#210.
+   * Speed up PBKDF2 by caching the digest calculation. Contributed by Jack
+     Lloyd and Fortanix Inc in ARMmbed/mbed-crypto#277.
+   * Small performance improvement of mbedtls_mpi_div_mpi(). Contributed by
+     Alexander Krizhanovsky in ARMmbed/mbed-crypto#308.
 
 = mbed TLS 2.19.1 branch released 2019-09-16
 
diff --git a/README.md b/README.md
index 43065b1..16ba188 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
 
 -   GNU Make
 -   CMake
--   Microsoft Visual Studio (Microsoft Visual Studio 2010 or later)
+-   Microsoft Visual Studio (Microsoft Visual Studio 2013 or later)
 
 The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
 
diff --git a/crypto b/crypto
index 0b3dd8d..1146b4e 160000
--- a/crypto
+++ b/crypto
@@ -1 +1 @@
-Subproject commit 0b3dd8d0249adb54abc7ad46303f3c22e44aefb7
+Subproject commit 1146b4e06011b69a6437e6b728f2af043a06ec19
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index d5ead37..5b5aefb 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.19.1 source code documentation
+ * @mainpage mbed TLS v2.20.0 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 eb2d96e..47a9740 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.19.1"
+PROJECT_NAME           = "mbed TLS v2.20.0"
 
 # 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/error.h b/include/mbedtls/error.h
index 06bb1c9..82b0188 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -52,9 +52,10 @@
  * For historical reasons, low-level error codes are divided in even and odd,
  * even codes were assigned first, and -1 is reserved for other errors.
  *
- * Low-level module errors (0x0002-0x007E, 0x0003-0x007F)
+ * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)
  *
  * Module   Nr  Codes assigned
+ * ERROR     2  0x006E          0x0001
  * MPI       7  0x0002-0x0010
  * GCM       3  0x0012-0x0014   0x0013-0x0013
  * BLOWFISH  3  0x0016-0x0018   0x0017-0x0017
@@ -86,7 +87,7 @@
  * CHACHA20  3                  0x0051-0x0055
  * POLY1305  3                  0x0057-0x005B
  * CHACHAPOLY 2 0x0054-0x0056
- * PLATFORM  1  0x0070-0x0072
+ * PLATFORM  2  0x0070-0x0072
  *
  * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
@@ -112,6 +113,9 @@
 extern "C" {
 #endif
 
+#define MBEDTLS_ERR_ERROR_GENERIC_ERROR       -0x0001  /**< Generic error */
+#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E  /**< This is a bug in the library */
+
 /**
  * \brief Translate a mbed TLS error code into a string representation,
  *        Result is truncated if necessary and always includes a terminating
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index ae694ee..d4e5d54 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -39,17 +39,17 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  2
-#define MBEDTLS_VERSION_MINOR  19
-#define MBEDTLS_VERSION_PATCH  1
+#define MBEDTLS_VERSION_MINOR  20
+#define MBEDTLS_VERSION_PATCH  0
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02130100
-#define MBEDTLS_VERSION_STRING         "2.19.1"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.19.1"
+#define MBEDTLS_VERSION_NUMBER         0x02140000
+#define MBEDTLS_VERSION_STRING         "2.20.0"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.20.0"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 5e36a5b..d990d43 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -174,14 +174,14 @@
 if(USE_SHARED_MBEDTLS_LIBRARY)
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.19.1 SOVERSION 1)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.20.0 SOVERSION 1)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
     target_include_directories(mbedx509
         PUBLIC ${MBEDTLS_DIR}/include/
         PUBLIC ${MBEDTLS_DIR}/crypto/include/)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.19.1 SOVERSION 13)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.20.0 SOVERSION 13)
     target_link_libraries(mbedtls ${libs} mbedx509)
     target_include_directories(mbedtls
         PUBLIC ${MBEDTLS_DIR}/include/
diff --git a/library/Makefile b/library/Makefile
index bc9363d..6fc110c 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -37,7 +37,7 @@
 
 SOEXT_TLS=so.13
 SOEXT_X509=so.1
-SOEXT_CRYPTO=so.3
+SOEXT_CRYPTO=so.4
 
 # Set AR_DASH= (empty string) to use an ar implementation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
diff --git a/library/debug.c b/library/debug.c
index 0c46c06..ae78a69 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -39,6 +39,7 @@
 #endif
 
 #include "mbedtls/debug.h"
+#include "mbedtls/error.h"
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -85,7 +86,7 @@
 {
     va_list argp;
     char str[DEBUG_BUF_SIZE];
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( NULL == ssl              ||
         NULL == ssl->conf        ||
diff --git a/library/error.c b/library/error.c
index d8b5780..c451f4d 100644
--- a/library/error.c
+++ b/library/error.c
@@ -25,8 +25,7 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
-#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include "mbedtls/error.h"
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
 #include <string.h>
 #endif
 
@@ -109,6 +108,10 @@
 #include "mbedtls/entropy.h"
 #endif
 
+#if defined(MBEDTLS_ERROR_C)
+#include "mbedtls/error.h"
+#endif
+
 #if defined(MBEDTLS_GCM_C)
 #include "mbedtls/gcm.h"
 #endif
@@ -754,6 +757,13 @@
         mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" );
 #endif /* MBEDTLS_ENTROPY_C */
 
+#if defined(MBEDTLS_ERROR_C)
+    if( use_ret == -(MBEDTLS_ERR_ERROR_GENERIC_ERROR) )
+        mbedtls_snprintf( buf, buflen, "ERROR - Generic error" );
+    if( use_ret == -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED) )
+        mbedtls_snprintf( buf, buflen, "ERROR - This is a bug in the library" );
+#endif /* MBEDTLS_ERROR_C */
+
 #if defined(MBEDTLS_GCM_C)
     if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) )
         mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
diff --git a/library/net_sockets.c b/library/net_sockets.c
index c7b358d..dbde510 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -45,6 +45,7 @@
 #endif
 
 #include "mbedtls/net_sockets.h"
+#include "mbedtls/error.h"
 
 #include <string.h>
 
@@ -147,7 +148,7 @@
 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
                          const char *port, int proto )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct addrinfo hints, *addr_list, *cur;
 
     if( ( ret = net_prepare() ) != 0 )
@@ -313,7 +314,7 @@
                         mbedtls_net_context *client_ctx,
                         void *client_ip, size_t buf_size, size_t *ip_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int type;
 
     struct sockaddr_storage client_addr;
@@ -455,7 +456,7 @@
 
 int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct timeval tv;
 
     fd_set read_fds;
@@ -540,7 +541,7 @@
  */
 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
     if( fd < 0 )
@@ -577,7 +578,7 @@
 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
                               size_t len, uint32_t timeout )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct timeval tv;
     fd_set read_fds;
     int fd = ((mbedtls_net_context *) ctx)->fd;
@@ -620,7 +621,7 @@
  */
 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
     if( fd < 0 )
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 57e5d8a..1005bd9 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -35,9 +35,10 @@
 #define mbedtls_free      free
 #endif
 
-#include "mbedtls/debug.h"
 #include "mbedtls/ssl.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "mbedtls/psa_util.h"
@@ -402,7 +403,7 @@
                                         unsigned char *buf,
                                         size_t *olen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = buf;
     const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t kkpp_len;
@@ -766,7 +767,7 @@
  */
 static int ssl_generate_random( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = ssl->handshake->randbytes;
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t t;
@@ -858,7 +859,7 @@
 
 static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n, olen, ext_len = 0;
     unsigned char *buf;
     unsigned char *p, *q;
@@ -1470,7 +1471,7 @@
                                    const unsigned char *buf,
                                    size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ssl->handshake->ciphersuite_info->key_exchange !=
         MBEDTLS_KEY_EXCHANGE_ECJPAKE )
@@ -2384,7 +2385,7 @@
                                     size_t offset, size_t *olen,
                                     size_t pms_offset )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
     unsigned char *p = ssl->handshake->premaster + pms_offset;
     mbedtls_pk_context * peer_pk;
@@ -2531,7 +2532,7 @@
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_ecp_keypair *peer_key;
     mbedtls_pk_context * peer_pk;
 
@@ -2582,7 +2583,7 @@
 
 static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
         ssl->handshake->ciphersuite_info;
     unsigned char *p = NULL, *end = NULL;
@@ -2971,7 +2972,7 @@
 #else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
 static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *buf;
     size_t n = 0;
     size_t cert_type_len = 0, dn_len = 0;
@@ -3135,7 +3136,7 @@
 
 static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
 
@@ -3174,7 +3175,7 @@
 
 static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     size_t header_len;
     size_t content_len;
@@ -3595,7 +3596,7 @@
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
         ssl->handshake->ciphersuite_info;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
 
@@ -3790,7 +3791,7 @@
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t lifetime;
     size_t ticket_len;
     unsigned char *ticket;
diff --git a/library/ssl_cookie.c b/library/ssl_cookie.c
index 56e9bdd..4bf9058 100644
--- a/library/ssl_cookie.c
+++ b/library/ssl_cookie.c
@@ -40,6 +40,7 @@
 
 #include "mbedtls/ssl_cookie.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -104,7 +105,7 @@
                       int (*f_rng)(void *, unsigned char *, size_t),
                       void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char key[COOKIE_MD_OUTLEN];
 
     if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
@@ -157,7 +158,7 @@
                       unsigned char **p, unsigned char *end,
                       const unsigned char *cli_id, size_t cli_id_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
     unsigned long t;
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index b1da073..b0b09cd 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -35,9 +35,10 @@
 #define mbedtls_free      free
 #endif
 
-#include "mbedtls/debug.h"
 #include "mbedtls/ssl.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -85,7 +86,7 @@
                                      const unsigned char *buf,
                                      size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t servername_list_size, hostname_len;
     const unsigned char *p;
 
@@ -432,7 +433,7 @@
                                    const unsigned char *buf,
                                    size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
     {
@@ -624,7 +625,7 @@
                                          unsigned char *buf,
                                          size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_session session;
 
     mbedtls_ssl_session_init( &session );
@@ -2428,7 +2429,7 @@
                                         unsigned char *buf,
                                         size_t *olen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = buf;
     const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t kkpp_len;
@@ -2506,7 +2507,7 @@
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
 static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = ssl->out_msg + 4;
     unsigned char *cookie_len_byte;
 
@@ -2580,7 +2581,7 @@
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t t;
 #endif
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen, ext_len = 0, n;
     unsigned char *buf, *p;
 
@@ -3007,7 +3008,7 @@
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
     {
@@ -3088,7 +3089,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t len = 0;
 
         ret = mbedtls_ecjpake_write_round_two(
@@ -3128,7 +3129,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
     if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t len = 0;
 
         if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
@@ -3193,7 +3194,7 @@
          */
         const mbedtls_ecp_curve_info **curve = NULL;
         const mbedtls_ecp_group_id *gid;
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t len = 0;
 
         /* Match our preference list against the offered curves */
@@ -3251,7 +3252,7 @@
         size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
         size_t hashlen = 0;
         unsigned char hash[MBEDTLS_MD_MAX_SIZE];
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         /*
          * 2.1: Choose hash algorithm:
@@ -3424,7 +3425,7 @@
  * machine. */
 static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t signature_len = 0;
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3521,7 +3522,7 @@
 
 static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
 
@@ -3625,7 +3626,7 @@
                                       size_t *peer_pmslen,
                                       size_t peer_pmssize )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
     mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
     size_t len = mbedtls_pk_get_len( public_key );
@@ -3714,7 +3715,7 @@
                                     const unsigned char *end,
                                     size_t pms_offset )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *pms = ssl->handshake->premaster + pms_offset;
     unsigned char ver[2];
     unsigned char fake_pms[48], peer_pms[48];
@@ -3868,7 +3869,7 @@
 
 static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
     unsigned char *p, *end;
 
@@ -4385,7 +4386,7 @@
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t tlen;
     uint32_t lifetime;
 
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index 6dad5d1..8a76b42 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -36,6 +36,7 @@
 #endif
 
 #include "mbedtls/ssl_ticket.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -73,7 +74,7 @@
 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
                                unsigned char index )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[MAX_KEY_BYTES];
     mbedtls_ssl_ticket_key *key = ctx->keys + index;
 
@@ -133,7 +134,7 @@
     mbedtls_cipher_type_t cipher,
     uint32_t lifetime )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
 
     ctx->f_rng = f_rng;
@@ -206,7 +207,7 @@
                               size_t *tlen,
                               uint32_t *ticket_lifetime )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_ticket_context *ctx = p_ticket;
     mbedtls_ssl_ticket_key *key;
     unsigned char *key_name = start;
@@ -306,7 +307,7 @@
                               unsigned char *buf,
                               size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_ticket_context *ctx = p_ticket;
     mbedtls_ssl_ticket_key *key;
     unsigned char *key_name = buf;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index e450207..6cf7781 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -43,9 +43,10 @@
 #define mbedtls_free      free
 #endif
 
-#include "mbedtls/debug.h"
 #include "mbedtls/ssl.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/version.h"
 
@@ -314,7 +315,7 @@
 
 static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t remaining, expansion;
     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
 
@@ -446,7 +447,7 @@
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     if( src->peer_cert != NULL )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) );
         if( dst->peer_cert == NULL )
@@ -586,7 +587,7 @@
     unsigned char h_i[20];
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     mbedtls_md_init( &md_ctx );
 
@@ -832,7 +833,7 @@
     unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     mbedtls_md_init( &md_ctx );
 
@@ -1683,7 +1684,7 @@
                                unsigned char *master,
                                const mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* cf. RFC 5246, Section 8.1:
      * "The master secret is always exactly 48 bytes in length." */
@@ -1810,7 +1811,7 @@
 
 int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
         ssl->handshake->ciphersuite_info;
 
@@ -2140,7 +2141,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
     if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t len;
 
         /* Write length only when we know the actual value */
@@ -2162,7 +2163,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
     if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t zlen;
 
         if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
@@ -2559,7 +2560,7 @@
 #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
     if( mode == MBEDTLS_MODE_STREAM )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t olen;
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
                                     "including %d bytes of padding",
@@ -2590,7 +2591,7 @@
         mode == MBEDTLS_MODE_CCM ||
         mode == MBEDTLS_MODE_CHACHAPOLY )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         unsigned char iv[12];
         size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
 
@@ -2673,7 +2674,7 @@
     ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
     if( mode == MBEDTLS_MODE_CBC )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t padlen, i;
         size_t olen;
 
@@ -3462,7 +3463,7 @@
  */
 static int ssl_compress_buf( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *msg_post = ssl->out_msg;
     ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
     size_t len_pre = ssl->out_msglen;
@@ -3509,7 +3510,7 @@
 
 static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *msg_post = ssl->in_msg;
     ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
     size_t len_pre = ssl->in_msglen;
@@ -3604,7 +3605,7 @@
  */
 int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
@@ -3823,7 +3824,7 @@
  */
 int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *buf;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
@@ -4022,7 +4023,7 @@
  */
 int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
 
     if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
@@ -4251,7 +4252,7 @@
  */
 int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const size_t hs_len = ssl->out_msglen - 4;
     const unsigned char hs_type = ssl->out_msg[0];
 
@@ -4737,7 +4738,7 @@
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
 
         if( ssl_check_hs_header( ssl ) != 0 )
@@ -4881,7 +4882,7 @@
 
 static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *original_in_ctr;
 
     // save original in_ctr
@@ -5107,7 +5108,7 @@
  */
 static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     if( ssl->conf->f_cookie_write == NULL ||
@@ -5619,7 +5620,7 @@
 int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
                              unsigned update_hs_digest )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
 
@@ -6265,7 +6266,7 @@
 
 static int ssl_get_next_record( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_record rec;
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -6473,7 +6474,7 @@
 
 int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
      * Handle particular types of records
@@ -6616,7 +6617,7 @@
                             unsigned char level,
                             unsigned char message )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ssl == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -6835,14 +6836,14 @@
     if( peer_crt->raw.len != crt_buf_len )
         return( -1 );
 
-    return( memcmp( peer_crt->raw.p, crt_buf, crt_buf_len ) );
+    return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
 }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
                                          unsigned char *crt_buf,
                                          size_t crt_buf_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char const * const peer_cert_digest =
         ssl->session->peer_cert_digest;
     mbedtls_md_type_t const peer_cert_digest_type =
@@ -6875,7 +6876,7 @@
 static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
                                         mbedtls_x509_crt *chain )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
     int crt_cnt=0;
 #endif
@@ -7290,7 +7291,7 @@
 static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
                                          unsigned char *start, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     /* Remember digest of the peer's end-CRT. */
     ssl->session_negotiate->peer_cert_digest =
         mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
@@ -7322,7 +7323,7 @@
                                      unsigned char *start, size_t len )
 {
     unsigned char *end = start + len;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Make a copy of the peer's raw public key. */
     mbedtls_pk_init( &ssl->handshake->peer_pubkey );
@@ -7492,7 +7493,7 @@
 
 int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
 
@@ -7515,7 +7516,7 @@
 
 int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
 
@@ -8214,7 +8215,7 @@
 
 int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned int hash_len;
     unsigned char buf[SSL_MAX_HASH_LEN];
 
@@ -8607,7 +8608,7 @@
 int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
                        const mbedtls_ssl_config *conf )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     ssl->conf = conf;
 
@@ -8674,7 +8675,7 @@
  */
 static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
 #if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) ||     \
     !defined(MBEDTLS_SSL_SRV_C)
@@ -8922,7 +8923,7 @@
 #if defined(MBEDTLS_SSL_CLI_C)
 int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ssl == NULL ||
         session == NULL ||
@@ -9166,7 +9167,7 @@
                 const unsigned char *psk, size_t psk_len,
                 const unsigned char *psk_identity, size_t psk_identity_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     /* Remove opaque/raw PSK + PSK Identity */
     ssl_conf_remove_psk( conf );
 
@@ -9235,7 +9236,7 @@
                                  const unsigned char *psk_identity,
                                  size_t psk_identity_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     /* Clear opaque/raw PSK + PSK Identity, if present. */
     ssl_conf_remove_psk( conf );
 
@@ -9280,7 +9281,7 @@
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 ||
         ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 )
@@ -9298,7 +9299,7 @@
                                    const unsigned char *dhm_P, size_t P_len,
                                    const unsigned char *dhm_G, size_t G_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
         ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
@@ -9313,7 +9314,7 @@
 
 int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
         ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
@@ -10361,7 +10362,7 @@
 
     if( cert_len != 0 )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         if( cert_len > (size_t)( end - p ) )
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -10549,7 +10550,7 @@
  */
 static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) );
 
@@ -10580,7 +10581,7 @@
  */
 static int ssl_start_renegotiation( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
 
@@ -10707,7 +10708,7 @@
  */
 int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     if( ssl == NULL || ssl->conf == NULL )
@@ -11091,7 +11092,7 @@
 static int ssl_write_split( mbedtls_ssl_context *ssl,
                             const unsigned char *buf, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ssl->conf->cbc_record_splitting ==
             MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
@@ -11123,7 +11124,7 @@
  */
 int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
 
@@ -11163,7 +11164,7 @@
  */
 int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ssl == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -11746,7 +11747,7 @@
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
     size_t session_len;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
      * The context should have been freshly setup or reset.
@@ -12167,7 +12168,7 @@
                                  int endpoint, int transport, int preset )
 {
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
 
     /* Use the functions here so that they are covered in tests,
diff --git a/library/x509.c b/library/x509.c
index 2e0b0e8..7f8181b 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -39,6 +39,7 @@
 
 #include "mbedtls/x509.h"
 #include "mbedtls/asn1.h"
+#include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 
 #include <stdio.h>
@@ -83,7 +84,7 @@
 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
                      mbedtls_x509_buf *serial )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( end - *p ) < 1 )
         return( MBEDTLS_ERR_X509_INVALID_SERIAL +
@@ -114,7 +115,7 @@
 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
                        mbedtls_x509_buf *alg )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -128,7 +129,7 @@
 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
                   mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
         return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -148,7 +149,7 @@
  */
 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p;
     const unsigned char *end;
     mbedtls_x509_buf md_oid;
@@ -209,7 +210,7 @@
                                 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
                                 int *salt_len )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p;
     const unsigned char *end, *end2;
     size_t len;
@@ -352,7 +353,7 @@
                                      const unsigned char *end,
                                      mbedtls_x509_name *cur )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     mbedtls_x509_buf *oid;
     mbedtls_x509_buf *val;
@@ -433,7 +434,7 @@
 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
                    mbedtls_x509_name *cur )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t set_len;
     const unsigned char *end_set;
 
@@ -539,7 +540,7 @@
 static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
                             mbedtls_x509_time *tm )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
      * Minimum length is 10 or 12 depending on yearlen
@@ -604,7 +605,7 @@
 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
                            mbedtls_x509_time *tm )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len, year_len;
     unsigned char tag;
 
@@ -633,7 +634,7 @@
 
 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     int tag_type;
 
@@ -662,7 +663,7 @@
                       mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
                       void **sig_opts )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( *sig_opts != NULL )
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@@ -710,7 +711,7 @@
 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
                           mbedtls_x509_buf *ext, int tag )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     /* Extension structure use EXPLICIT tagging. That is, the actual
@@ -745,7 +746,7 @@
  */
 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n;
     unsigned char c, merge = 0;
     const mbedtls_x509_name *name;
@@ -807,7 +808,7 @@
  */
 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n, nr;
     char *p;
 
@@ -843,7 +844,7 @@
                        mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
                        const void *sig_opts )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     char *p = buf;
     size_t n = size;
     const char *desc = NULL;
@@ -888,7 +889,7 @@
 {
     char *p = buf;
     size_t n = buf_size;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     ret = mbedtls_snprintf( p, n, "%s key size", name );
     MBEDTLS_X509_SAFE_SNPRINTF;
diff --git a/library/x509_create.c b/library/x509_create.c
index 546e8fa..7df2f0e 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -29,6 +29,7 @@
 
 #include "mbedtls/x509.h"
 #include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 
 #include <string.h>
@@ -241,7 +242,7 @@
  */
 static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     const char *oid             = (const char*)cur_name->oid.p;
     size_t oid_len              = cur_name->oid.len;
@@ -274,7 +275,7 @@
 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
                               mbedtls_asn1_named_data *first )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     mbedtls_asn1_named_data *cur = first;
 
@@ -295,7 +296,7 @@
                     const char *oid, size_t oid_len,
                     unsigned char *sig, size_t size )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     if( *p < start || (size_t)( *p - start ) < size )
@@ -325,7 +326,7 @@
 static int x509_write_extension( unsigned char **p, unsigned char *start,
                                  mbedtls_asn1_named_data *ext )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
@@ -363,7 +364,7 @@
 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
                            mbedtls_asn1_named_data *first )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     mbedtls_asn1_named_data *cur_ext = first;
 
diff --git a/library/x509_crl.c b/library/x509_crl.c
index 00f8545..d1176fc 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
 
 #include "mbedtls/x509_crl.h"
+#include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -74,7 +75,7 @@
                              const unsigned char *end,
                              int *ver )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
     {
@@ -101,7 +102,7 @@
                              const unsigned char *end,
                              mbedtls_x509_buf *ext )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( *p == end )
         return( 0 );
@@ -181,7 +182,7 @@
                              const unsigned char *end,
                              mbedtls_x509_buf *ext )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     /* OPTIONAL */
@@ -235,7 +236,7 @@
                              const unsigned char *end,
                              mbedtls_x509_crl_entry *entry )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t entry_len;
     mbedtls_x509_crl_entry *cur_entry = entry;
 
@@ -300,7 +301,7 @@
 int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
                         const unsigned char *buf, size_t buflen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *p = NULL, *end = NULL;
     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -539,7 +540,7 @@
 int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
 {
 #if defined(MBEDTLS_PEM_PARSE_C)
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t use_len;
     mbedtls_pem_context pem;
     int is_pem = 0;
@@ -603,7 +604,7 @@
  */
 int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
@@ -630,7 +631,7 @@
 int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
                    const mbedtls_x509_crl *crl )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     char *p;
     const mbedtls_x509_crl_entry *entry;
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 48f244e..ca60011 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -40,6 +40,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #include "mbedtls/x509_crt.h"
+#include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -390,7 +391,7 @@
                              const unsigned char *end,
                              int *ver )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -427,7 +428,7 @@
                            mbedtls_x509_time *from,
                            mbedtls_x509_time *to )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -456,7 +457,7 @@
                          const unsigned char *end,
                          mbedtls_x509_buf *uid, int n )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( *p == end )
         return( 0 );
@@ -483,7 +484,7 @@
                                        int *ca_istrue,
                                        int *max_pathlen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     /*
@@ -532,7 +533,7 @@
                                        const unsigned char *end,
                                        unsigned char *ns_cert_type)
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
@@ -551,7 +552,7 @@
                                const unsigned char *end,
                                unsigned int *key_usage)
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
@@ -581,7 +582,7 @@
                                const unsigned char *end,
                                mbedtls_x509_sequence *ext_key_usage)
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
         return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
@@ -625,7 +626,7 @@
                                       const unsigned char *end,
                                       mbedtls_x509_sequence *subject_alt_name )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len, tag_len;
     mbedtls_asn1_buf *buf;
     unsigned char tag;
@@ -887,7 +888,7 @@
                              const unsigned char *end,
                              mbedtls_x509_crt *crt )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *end_ext_data, *end_ext_octet;
 
@@ -1056,7 +1057,7 @@
                                     size_t buflen,
                                     int make_copy )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *p, *end, *crt_end;
     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -1318,7 +1319,7 @@
                                                 size_t buflen,
                                                 int make_copy )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *crt = chain, *prev = NULL;
 
     /*
@@ -1415,7 +1416,7 @@
 #if defined(MBEDTLS_PEM_PARSE_C)
     if( buf_format == MBEDTLS_X509_FORMAT_PEM )
     {
-        int ret;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         mbedtls_pem_context pem;
 
         /* 1 rather than 0 since the terminating NULL byte is counted in */
@@ -1499,7 +1500,7 @@
  */
 int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
@@ -1612,7 +1613,7 @@
             goto cleanup;
         }
 
-        if( !S_ISREG( sb.st_mode ) )
+        if( !( S_ISREG( sb.st_mode ) || S_ISLNK( sb.st_mode ) ) )
             continue;
 
         // Ignore parse errors
@@ -1737,7 +1738,7 @@
                                                     *subject_alt_name,
                                        const char *prefix )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n = *size;
     char *p = *buf;
     const mbedtls_x509_sequence *cur = subject_alt_name;
@@ -1848,7 +1849,7 @@
 int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
                                          mbedtls_x509_subject_alternative_name *san )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     switch( san_buf->tag &
             ( MBEDTLS_ASN1_TAG_CLASS_MASK |
               MBEDTLS_ASN1_TAG_VALUE_MASK ) )
@@ -1909,7 +1910,7 @@
 static int x509_info_cert_type( char **buf, size_t *size,
                                 unsigned char ns_cert_type )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n = *size;
     char *p = *buf;
     const char *sep = "";
@@ -1936,7 +1937,7 @@
 static int x509_info_key_usage( char **buf, size_t *size,
                                 unsigned int key_usage )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n = *size;
     char *p = *buf;
     const char *sep = "";
@@ -1960,7 +1961,7 @@
 static int x509_info_ext_key_usage( char **buf, size_t *size,
                                     const mbedtls_x509_sequence *extended_key_usage )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *desc;
     size_t n = *size;
     char *p = *buf;
@@ -1989,7 +1990,7 @@
 static int x509_info_cert_policies( char **buf, size_t *size,
                                     const mbedtls_x509_sequence *certificate_policies )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *desc;
     size_t n = *size;
     char *p = *buf;
@@ -2023,7 +2024,7 @@
 int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
                    const mbedtls_x509_crt *crt )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     char *p;
     char key_size_str[BEFORE_COLON];
@@ -2195,7 +2196,7 @@
 int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
                           uint32_t flags )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const struct x509_crt_verify_string *cur;
     char *p = buf;
     size_t n = size;
@@ -2535,7 +2536,7 @@
                         unsigned self_cnt,
                         mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *parent, *fallback_parent;
     int signature_is_good, fallback_signature_is_good;
 
@@ -2658,7 +2659,7 @@
                         unsigned self_cnt,
                         mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *search_list;
 
     *parent_is_trusted = 1;
@@ -2791,7 +2792,7 @@
 {
     /* Don't initialize any of those variables here, so that the compiler can
      * catch potential issues with jumping ahead when restarting */
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t *flags;
     mbedtls_x509_crt_verify_chain_item *cur;
     mbedtls_x509_crt *child;
@@ -3020,7 +3021,7 @@
            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
            void *p_vrfy )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned i;
     uint32_t cur_flags;
     const mbedtls_x509_crt_verify_chain_item *cur;
@@ -3068,7 +3069,7 @@
                      void *p_vrfy,
                      mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_pk_type_t pk_type;
     mbedtls_x509_crt_verify_chain ver_chain;
     uint32_t ee_flags;
diff --git a/library/x509_csr.c b/library/x509_csr.c
index c8c08c8..7e2cfba 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
 
 #include "mbedtls/x509_csr.h"
+#include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
@@ -68,7 +69,7 @@
                              const unsigned char *end,
                              int *ver )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
     {
@@ -90,7 +91,7 @@
 int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
                         const unsigned char *buf, size_t buflen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *p, *end;
     mbedtls_x509_buf sig_params;
@@ -262,7 +263,7 @@
 int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
 {
 #if defined(MBEDTLS_PEM_PARSE_C)
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t use_len;
     mbedtls_pem_context pem;
 #endif
@@ -312,7 +313,7 @@
  */
 int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
@@ -336,7 +337,7 @@
 int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
                    const mbedtls_x509_csr *csr )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     char *p;
     char key_size_str[BEFORE_COLON];
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 0a2357a..5947e43 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -34,10 +34,11 @@
 #if defined(MBEDTLS_X509_CRT_WRITE_C)
 
 #include "mbedtls/x509_crt.h"
-#include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
-#include "mbedtls/sha1.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
+#include "mbedtls/sha1.h"
 
 #include <string.h>
 
@@ -103,7 +104,7 @@
 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
                                       const mbedtls_mpi *serial )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
         return( ret );
@@ -140,7 +141,7 @@
 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
                                                  int is_ca, int max_pathlen )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[9];
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
@@ -174,7 +175,7 @@
 #if defined(MBEDTLS_SHA1_C)
 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
@@ -202,7 +203,7 @@
 
 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
     unsigned char *c = buf + sizeof( buf );
     size_t len = 0;
@@ -240,7 +241,7 @@
 {
     unsigned char buf[5], ku[2];
     unsigned char *c;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
         MBEDTLS_X509_KU_NON_REPUDIATION   |
         MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
@@ -279,7 +280,7 @@
 {
     unsigned char buf[4];
     unsigned char *c;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
@@ -299,7 +300,7 @@
 static int x509_write_time( unsigned char **p, unsigned char *start,
                             const char *t, size_t size )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     /*
@@ -332,7 +333,7 @@
                                int (*f_rng)(void *, unsigned char *, size_t),
                                void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *sig_oid;
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
@@ -526,7 +527,7 @@
                                int (*f_rng)(void *, unsigned char *, size_t),
                                void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen;
 
     if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index 23e3f78..7c51798 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -33,8 +33,9 @@
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
 
 #include "mbedtls/x509_csr.h"
-#include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -90,7 +91,7 @@
 {
     unsigned char buf[4];
     unsigned char *c;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
@@ -112,7 +113,7 @@
 {
     unsigned char buf[4];
     unsigned char *c;
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
@@ -133,7 +134,7 @@
                        int (*f_rng)(void *, unsigned char *, size_t),
                        void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *sig_oid;
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
@@ -213,7 +214,9 @@
         return( MBEDTLS_ERR_X509_FATAL_ERROR );
     }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
-    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 );
 #endif
     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
                                  f_rng, p_rng ) ) != 0 )
@@ -263,7 +266,7 @@
                        int (*f_rng)(void *, unsigned char *, size_t),
                        void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen = 0;
 
     if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size,
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index 8242ea7..048028d 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -96,7 +96,7 @@
     unsigned char IV[16];
     unsigned char tmp[16];
     unsigned char key[512];
-    unsigned char digest[32];
+    unsigned char digest[64];
     unsigned char buffer[1024];
     unsigned char diff;
 
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 8f0d3b5..c188900 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -619,6 +619,7 @@
         if( fwrite( nss_keylog_line, 1, len, f ) != len )
         {
             ret = -1;
+            fclose( f );
             goto exit;
         }
 
diff --git a/scripts/config.pl b/scripts/config.pl
index 95e3191..c836b37 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -19,9 +19,9 @@
 ## This file is part of Mbed TLS (https://tls.mbed.org)
 
 my $py = $0;
-$py =~ s/\.pl$/.py/;
+$py =~ s/\.pl$/.py/ or die "Unable to determine the name of the Python script";
 exec 'python3', $py, @ARGV;
-print STDERR "$0: python3: $!\n";
+print STDERR "$0: python3: $!. Trying python instead.\n";
 exec 'python', $py, @ARGV;
 print STDERR "$0: python: $!\n";
 exit 127;
diff --git a/scripts/data_files/error.fmt b/scripts/data_files/error.fmt
index a08742c..6360705 100644
--- a/scripts/data_files/error.fmt
+++ b/scripts/data_files/error.fmt
@@ -25,8 +25,7 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
-#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include "mbedtls/error.h"
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
 #include <string.h>
 #endif
 
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 2fe202e..7b66eca 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -38,7 +38,7 @@
 
 my @low_level_modules = qw( AES ARC4 ARIA ASN1 BASE64 BIGNUM BLOWFISH
                             CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES
-                            ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
+                            ENTROPY ERROR GCM HKDF HMAC_DRBG MD2 MD4 MD5
                             NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160
                             SHA1 SHA256 SHA512 THREADING XTEA );
 my @high_level_modules = qw( CIPHER DHM ECP MD
diff --git a/tests/scripts/check-test-cases.py b/tests/scripts/check-test-cases.py
index 87a35e4..939ca23 100755
--- a/tests/scripts/check-test-cases.py
+++ b/tests/scripts/check-test-cases.py
@@ -26,6 +26,7 @@
 import sys
 
 class Results:
+    """Store file and line information about errors or warnings in test suites."""
     def __init__(self):
         self.errors = 0
         self.warnings = 0
@@ -41,6 +42,7 @@
         self.warnings += 1
 
 def collect_test_directories():
+    """Get the relative path for the TLS and Crypto test directories."""
     if os.path.isdir('tests'):
         tests_dir = 'tests'
     elif os.path.isdir('suites'):
@@ -55,6 +57,7 @@
     return directories
 
 def check_description(results, seen, file_name, line_number, description):
+    """Check test case descriptions for errors."""
     if description in seen:
         results.error(file_name, line_number,
                       'Duplicate description (also line {})',
diff --git a/tests/scripts/mbedtls_test.py b/tests/scripts/mbedtls_test.py
index 6ac68a4..8f24435 100755
--- a/tests/scripts/mbedtls_test.py
+++ b/tests/scripts/mbedtls_test.py
@@ -310,7 +310,10 @@
 
         param_bytes, length = self.test_vector_to_bytes(function_id,
                                                         dependencies, args)
-        self.send_kv(''.join('{:02x}'.format(x) for x in length), ''.join('{:02x}'.format(x) for x in param_bytes))
+        self.send_kv(
+            ''.join('{:02x}'.format(x) for x in length),
+            ''.join('{:02x}'.format(x) for x in param_bytes)
+        )
 
     @staticmethod
     def get_result(value):
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 5d0a390..7cc9c09 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -230,13 +230,45 @@
 #define TEST_VALID_PARAM( TEST )                                    \
     TEST_ASSERT( ( TEST, 1 ) );
 
-#define TEST_HELPER_ASSERT(a) if( !( a ) )                                      \
+#define TEST_HELPER_ASSERT(a) if( !( a ) )                          \
 {                                                                   \
-    mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n",   \
+    mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n",    \
                              __FILE__, __LINE__, #a );              \
-    mbedtls_exit( 1 );                                             \
+    mbedtls_exit( 1 );                                              \
 }
 
+/** Allocate memory dynamically and fail the test case if this fails.
+ *
+ * You must set \p pointer to \c NULL before calling this macro and
+ * put `mbedtls_free( pointer )` in the test's cleanup code.
+ *
+ * If \p length is zero, the resulting \p pointer will be \c NULL.
+ * This is usually what we want in tests since API functions are
+ * supposed to accept null pointers when a buffer size is zero.
+ *
+ * This macro expands to an instruction, not an expression.
+ * It may jump to the \c exit label.
+ *
+ * \param pointer   An lvalue where the address of the allocated buffer
+ *                  will be stored.
+ *                  This expression may be evaluated multiple times.
+ * \param length    Number of elements to allocate.
+ *                  This expression may be evaluated multiple times.
+ *
+ */
+#define ASSERT_ALLOC( pointer, length )                           \
+    do                                                            \
+    {                                                             \
+        TEST_ASSERT( ( pointer ) == NULL );                       \
+        if( ( length ) != 0 )                                     \
+        {                                                         \
+            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
+                                          ( length ) );           \
+            TEST_ASSERT( ( pointer ) != NULL );                   \
+        }                                                         \
+    }                                                             \
+    while( 0 )
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index 9e56ca3..b956c0c 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -525,15 +525,6 @@
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) );
 #endif
 
-    if( outcome_file_name != NULL )
-    {
-        outcome_file = fopen( outcome_file_name, "a" );
-        if( outcome_file == NULL )
-        {
-            mbedtls_fprintf( stderr, "Unable to open outcome file. Continuing anyway.\n" );
-        }
-    }
-
     /*
      * The C standard doesn't guarantee that all-bits-0 is the representation
      * of a NULL pointer. We do however use that in our code for initializing
@@ -555,6 +546,15 @@
         return( 1 );
     }
 
+    if( outcome_file_name != NULL )
+    {
+        outcome_file = fopen( outcome_file_name, "a" );
+        if( outcome_file == NULL )
+        {
+            mbedtls_fprintf( stderr, "Unable to open outcome file. Continuing anyway.\n" );
+        }
+    }
+
     while( arg_index < argc )
     {
         next_arg = argv[arg_index];
@@ -607,6 +607,8 @@
         {
             mbedtls_fprintf( stderr, "Failed to open test file: %s\n",
                              test_filename );
+            if( outcome_file != NULL )
+                fclose( outcome_file );
             return( 1 );
         }
 
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
index d430d9d..b097589 100644
--- a/tests/suites/target_test.function
+++ b/tests/suites/target_test.function
@@ -75,7 +75,7 @@
     c[1] = greentea_getc();
     c[2] = '\0';
 
-    assert( unhexify( &byte, c ) != 2 );
+    TEST_HELPER_ASSERT( unhexify( &byte, c ) != 2 );
     return( byte );
 }
 
@@ -100,7 +100,7 @@
                            greentea_getc(),
                            '\0'
                          };
-    assert( unhexify( &value, c ) != 8 );
+    TEST_HELPER_ASSERT( unhexify( &value, c ) != 8 );
     return( (uint32_t)value );
 }
 
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 45765de..59b4769 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -1,3 +1,51 @@
+Test calback buffer sanity
+test_callback_buffer_sanity:
+
+Callback buffer test: Exercise simple write/read
+test_callback_buffer:50:25:25:25:25:0:0:0:0
+
+Callback buffer test: Filling up the buffer
+test_callback_buffer:50:50:50:50:50:0:0:0:0
+
+Callback buffer test: Filling up the buffer in two steps
+test_callback_buffer:50:20:20:0:0:30:30:50:50
+
+Callback buffer test: Reading out the buffer in two steps
+test_callback_buffer:50:50:50:30:30:0:0:20:20
+
+Callback buffer test: Data wraps in buffer
+test_callback_buffer:50:45:45:10:10:10:10:45:45
+
+Callback buffer test: Data starts at the end
+test_callback_buffer:50:50:50:49:49:10:10:11:11
+
+Callback buffer test: Can write less than requested
+test_callback_buffer:50:75:50:30:30:25:25:45:45
+
+Callback buffer test: Can read less than requested
+test_callback_buffer:50:25:25:30:25:5:5:5:5
+
+Callback buffer test: Writing to full buffer
+test_callback_buffer:50:50:50:0:0:10:0:60:50
+
+Callback buffer test: Reading from empty buffer
+test_callback_buffer:50:0:0:10:0:0:0:0:0
+
+Test mock socket sanity
+ssl_mock_sanity:
+
+Test mock blocking TCP connection
+ssl_mock_tcp:1
+
+Test mock non-blocking TCP connection
+ssl_mock_tcp:0
+
+Test mock blocking TCP connection (interleaving)
+ssl_mock_tcp_interleaving:1
+
+Test mock non-blocking TCP connection (interleaving)
+ssl_mock_tcp_interleaving:0
+
 SSL DTLS replay: initial state, seqnum 0
 ssl_dtls_replay:"":"000000000000":0
 
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 2fa716b..a936d83 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2,6 +2,331 @@
 #include <mbedtls/ssl.h>
 #include <mbedtls/ssl_internal.h>
 
+
+/*
+ * Buffer structure for custom I/O callbacks.
+ */
+
+typedef struct mbedtls_test_buffer
+{
+    size_t start;
+    size_t content_length;
+    size_t capacity;
+    unsigned char *buffer;
+} mbedtls_test_buffer;
+
+/*
+ * Initialises \p buf. After calling this function it is safe to call
+ * `mbedtls_test_buffer_free()` on \p buf.
+ */
+void mbedtls_test_buffer_init( mbedtls_test_buffer *buf )
+{
+    memset( buf, 0, sizeof( *buf ) );
+}
+
+/*
+ * Sets up \p buf. After calling this function it is safe to call
+ * `mbedtls_test_buffer_put()` and `mbedtls_test_buffer_get()` on \p buf.
+ */
+int mbedtls_test_buffer_setup( mbedtls_test_buffer *buf, size_t capacity )
+{
+    buf->buffer = (unsigned char*) mbedtls_calloc( capacity,
+                                                   sizeof(unsigned char) );
+    if( NULL == buf->buffer )
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    buf->capacity = capacity;
+
+    return 0;
+}
+
+void mbedtls_test_buffer_free( mbedtls_test_buffer *buf )
+{
+    if( buf->buffer != NULL )
+        mbedtls_free( buf->buffer );
+
+    memset( buf, 0, sizeof( *buf ) );
+}
+
+/*
+ * Puts \p input_len bytes from the \p input buffer into the ring buffer \p buf.
+ *
+ * \p buf must have been initialized and set up by calling
+ * `mbedtls_test_buffer_init()` and `mbedtls_test_buffer_setup()`.
+ *
+ * \retval  \p input_len, if the data fits.
+ * \retval  0 <= value < \p input_len, if the data does not fit.
+ * \retval  -1, if \p buf is NULL, it hasn't been set up or \p input_len is not
+ *          zero and \p input is NULL.
+ */
+int mbedtls_test_buffer_put( mbedtls_test_buffer *buf,
+                             const unsigned char* input, size_t input_len )
+{
+    size_t overflow = 0;
+
+    if( ( buf == NULL ) || ( buf->buffer == NULL ) )
+        return -1;
+
+    /* Reduce input_len to a number that fits in the buffer. */
+    if ( ( buf->content_length + input_len ) > buf->capacity )
+    {
+        input_len = buf->capacity - buf->content_length;
+    }
+
+    if( input == NULL )
+    {
+        return ( input_len == 0 ) ? 0 : -1;
+    }
+
+     /* Check if the buffer has not come full circle and free space is not in
+      * the middle */
+    if( buf->start + buf->content_length < buf->capacity )
+    {
+
+        /* Calculate the number of bytes that need to be placed at lower memory
+        * address */
+        if( buf->start + buf->content_length + input_len
+            > buf->capacity )
+        {
+            overflow = ( buf->start + buf->content_length + input_len )
+                        % buf->capacity;
+        }
+
+        memcpy( buf->buffer + buf->start + buf->content_length, input,
+                    input_len - overflow );
+        memcpy( buf->buffer, input + input_len - overflow, overflow );
+
+    }
+    else
+    {
+        /* The buffer has come full circle and free space is in the middle */
+        memcpy( buf->buffer + buf->start + buf->content_length - buf->capacity,
+                input, input_len );
+    }
+
+    buf->content_length += input_len;
+    return input_len;
+}
+
+/*
+ * Gets \p output_len bytes from the \p output buffer into the ring buffer
+ * \p buf.
+ *
+ * \p buf must have been initialized and set up by calling
+ * `mbedtls_test_buffer_init()` and `mbedtls_test_buffer_setup()`.
+ *
+ * \retval  \p output_len, if the data is available.
+ * \retval  0 <= value < \p output_len, if the data is not available.
+ * \retval  -1, if \buf is NULL, it hasn't been set up or \p output_len is not
+ *          zero and \p output is NULL
+ */
+int mbedtls_test_buffer_get( mbedtls_test_buffer *buf,
+                             unsigned char* output, size_t output_len )
+{
+    size_t overflow = 0;
+
+    if( ( buf == NULL ) || ( buf->buffer == NULL ) )
+        return -1;
+
+    if( output == NULL )
+    {
+        return ( output_len == 0 ) ? 0 : -1;
+    }
+
+    if( buf->content_length < output_len )
+        output_len = buf->content_length;
+
+    /* Calculate the number of bytes that need to be drawn from lower memory
+     * address */
+    if( buf->start + output_len > buf->capacity )
+    {
+        overflow = ( buf->start + output_len ) % buf->capacity;
+    }
+
+    memcpy( output, buf->buffer + buf->start, output_len - overflow );
+    memcpy( output + output_len - overflow, buf->buffer, overflow );
+    buf->content_length -= output_len;
+    buf->start = ( buf->start + output_len ) % buf->capacity;
+
+    return output_len;
+}
+
+/*
+ * Context for the I/O callbacks simulating network connection.
+ */
+
+#define MBEDTLS_MOCK_SOCKET_CONNECTED 1
+
+typedef struct mbedtls_mock_socket
+{
+    int status;
+    mbedtls_test_buffer *input;
+    mbedtls_test_buffer *output;
+    struct mbedtls_mock_socket *peer;
+} mbedtls_mock_socket;
+
+/*
+ * Setup and teardown functions for mock sockets.
+ */
+void mbedtls_mock_socket_init( mbedtls_mock_socket *socket )
+{
+    memset( socket, 0, sizeof( *socket ) );
+}
+
+/*
+ * Closes the socket \p socket.
+ *
+ * \p socket must have been previously initialized by calling
+ * mbedtls_mock_socket_init().
+ *
+ * This function frees all allocated resources and both sockets are aware of the
+ * new connection state.
+ *
+ * That is, this function does not simulate half-open TCP connections and the
+ * phenomenon that when closing a UDP connection the peer is not aware of the
+ * connection having been closed.
+ */
+void mbedtls_mock_socket_close( mbedtls_mock_socket* socket )
+{
+    if( socket == NULL )
+        return;
+
+    if( socket->input != NULL )
+    {
+        mbedtls_test_buffer_free( socket->input );
+        mbedtls_free( socket->input );
+    }
+
+    if( socket->output != NULL )
+    {
+        mbedtls_test_buffer_free( socket->output );
+        mbedtls_free( socket->output );
+    }
+
+    if( socket->peer != NULL )
+        memset( socket->peer, 0, sizeof( *socket->peer ) );
+
+    memset( socket, 0, sizeof( *socket ) );
+}
+
+/*
+ * Establishes a connection between \p peer1 and \p peer2.
+ *
+ * \p peer1 and \p peer2 must have been previously initialized by calling
+ * mbedtls_mock_socket_init().
+ *
+ * The capacites of the internal buffers are set to \p bufsize. Setting this to
+ * the correct value allows for simulation of MTU, sanity testing the mock
+ * implementation and mocking TCP connections with lower memory cost.
+ */
+int mbedtls_mock_socket_connect( mbedtls_mock_socket* peer1,
+                                 mbedtls_mock_socket* peer2,
+                                 size_t bufsize )
+{
+    int ret = -1;
+
+    peer1->output =
+        (mbedtls_test_buffer*) mbedtls_calloc( 1, sizeof(mbedtls_test_buffer) );
+    if( peer1->output == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
+    mbedtls_test_buffer_init( peer1->output );
+    if( 0 != ( ret = mbedtls_test_buffer_setup( peer1->output, bufsize ) ) )
+    {
+        goto exit;
+    }
+
+    peer2->output =
+        (mbedtls_test_buffer*) mbedtls_calloc( 1, sizeof(mbedtls_test_buffer) );
+    if( peer2->output == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
+    mbedtls_test_buffer_init( peer2->output );
+    if( 0 != ( ret = mbedtls_test_buffer_setup( peer2->output, bufsize ) ) )
+    {
+        goto exit;
+    }
+
+    peer1->peer = peer2;
+    peer2->peer = peer1;
+    peer1->input = peer2->output;
+    peer2->input = peer1->output;
+
+    peer1->status = peer2->status = MBEDTLS_MOCK_SOCKET_CONNECTED;
+    ret = 0;
+
+exit:
+
+    if( ret != 0 )
+    {
+        mbedtls_mock_socket_close( peer1 );
+        mbedtls_mock_socket_close( peer2 );
+    }
+
+    return ret;
+}
+
+/*
+ * Callbacks for simulating blocking I/O over connection-oriented transport.
+ */
+
+int mbedtls_mock_tcp_send_b( void *ctx, const unsigned char *buf, size_t len )
+{
+    mbedtls_mock_socket *socket = (mbedtls_mock_socket*) ctx;
+
+    if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
+        return -1;
+
+    return mbedtls_test_buffer_put( socket->output, buf, len );
+}
+
+int mbedtls_mock_tcp_recv_b( void *ctx, unsigned char *buf, size_t len )
+{
+    mbedtls_mock_socket *socket = (mbedtls_mock_socket*) ctx;
+
+    if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
+        return -1;
+
+    return mbedtls_test_buffer_get( socket->input, buf, len );
+}
+
+/*
+ * Callbacks for simulating non-blocking I/O over connection-oriented transport.
+ */
+
+int mbedtls_mock_tcp_send_nb( void *ctx, const unsigned char *buf, size_t len )
+{
+    mbedtls_mock_socket *socket = (mbedtls_mock_socket*) ctx;
+
+    if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
+        return -1;
+
+    if( socket->output->capacity == socket->output->content_length )
+    {
+        return MBEDTLS_ERR_SSL_WANT_WRITE;
+    }
+
+    return mbedtls_test_buffer_put( socket->output, buf, len );
+}
+
+int mbedtls_mock_tcp_recv_nb( void *ctx, unsigned char *buf, size_t len )
+{
+    mbedtls_mock_socket *socket = (mbedtls_mock_socket*) ctx;
+
+    if( socket == NULL || socket->status != MBEDTLS_MOCK_SOCKET_CONNECTED )
+        return -1;
+
+    if( socket->input->content_length == 0)
+    {
+        return MBEDTLS_ERR_SSL_WANT_READ;
+    }
+
+    return mbedtls_test_buffer_get( socket->input, buf, len );
+}
+
 /*
  * Helper function setting up inverse record transformations
  * using given cipher, hash, EtM mode, authentication tag length,
@@ -361,6 +686,477 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE */
+void test_callback_buffer_sanity()
+{
+    enum { MSGLEN = 10 };
+    mbedtls_test_buffer buf;
+    unsigned char input[MSGLEN];
+    unsigned char output[MSGLEN];
+
+    memset( input, 0, sizeof(input) );
+
+    /* Make sure calling put and get on NULL buffer results in error. */
+    TEST_ASSERT( mbedtls_test_buffer_put( NULL, input, sizeof( input ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( NULL, output, sizeof( output ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( NULL, NULL, sizeof( input ) ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( NULL, NULL, sizeof( output ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( NULL, NULL, 0 ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( NULL, NULL, 0 ) == -1 );
+
+    /* Make sure calling put and get on a buffer that hasn't been set up results
+     * in eror. */
+    mbedtls_test_buffer_init( &buf );
+
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, input, sizeof( input ) ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, output, sizeof( output ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, NULL, sizeof( input ) ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, NULL, sizeof( output ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, NULL, 0 ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, NULL, 0 ) == -1 );
+
+    /* Make sure calling put end get on NULL input and output only results in
+     * error if the length is not zero. */
+
+    TEST_ASSERT( mbedtls_test_buffer_setup( &buf, sizeof( input ) ) == 0 );
+
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, NULL, sizeof( input ) ) == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, NULL, sizeof( output ) )
+                    == -1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, NULL, 0 ) == 0 );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, NULL, 0 ) == 0 );
+
+    /* Make sure calling put several times in the row is safe */
+
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, input, sizeof( input ) )
+                                          == sizeof( input ) );
+    TEST_ASSERT( mbedtls_test_buffer_get( &buf, output, 2 ) == 2 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, input, 1 ) == 1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, input, 2 ) == 1 );
+    TEST_ASSERT( mbedtls_test_buffer_put( &buf, input, 2 ) == 0 );
+
+
+exit:
+
+    mbedtls_test_buffer_free( &buf );
+}
+/* END_CASE */
+
+/*
+ * Test if the implementation of `mbedtls_test_buffer` related functions is
+ * correct and works as expected.
+ *
+ * That is
+ *  - If we try to put in \p put1 bytes then we can put in \p put1_ret bytes.
+ *  - Afterwards if we try to get \p get1 bytes then we can get \get1_ret bytes.
+ *  - Next, if we try to put in \p put1 bytes then we can put in \p put1_ret
+ *    bytes.
+ *  - Afterwards if we try to get \p get1 bytes then we can get \get1_ret bytes.
+ *  - All of the bytes we got match the bytes we put in in a FIFO manner.
+ */
+
+/* BEGIN_CASE */
+void test_callback_buffer( int size, int put1, int put1_ret,
+                           int get1, int get1_ret, int put2, int put2_ret,
+                           int get2, int get2_ret )
+{
+    enum { ROUNDS = 2 };
+    size_t put[ROUNDS];
+    int put_ret[ROUNDS];
+    size_t get[ROUNDS];
+    int get_ret[ROUNDS];
+    mbedtls_test_buffer buf;
+    unsigned char* input = NULL;
+    size_t input_len;
+    unsigned char* output = NULL;
+    size_t output_len;
+    size_t i, j, written, read;
+
+    mbedtls_test_buffer_init( &buf );
+    TEST_ASSERT( mbedtls_test_buffer_setup( &buf, size ) == 0 );
+
+    /* Check the sanity of input parameters and initialise local variables. That
+     * is, ensure that the amount of data is not negative and that we are not
+     * expecting more to put or get than we actually asked for. */
+    TEST_ASSERT( put1 >= 0 );
+    put[0] = put1;
+    put_ret[0] = put1_ret;
+    TEST_ASSERT( put1_ret <= put1 );
+    TEST_ASSERT( put2 >= 0 );
+    put[1] = put2;
+    put_ret[1] = put2_ret;
+    TEST_ASSERT( put2_ret <= put2 );
+
+    TEST_ASSERT( get1 >= 0 );
+    get[0] = get1;
+    get_ret[0] = get1_ret;
+    TEST_ASSERT( get1_ret <= get1 );
+    TEST_ASSERT( get2 >= 0 );
+    get[1] = get2;
+    get_ret[1] = get2_ret;
+    TEST_ASSERT( get2_ret <= get2 );
+
+    input_len = 0;
+    /* Calculate actual input and output lengths */
+    for( j = 0; j < ROUNDS; j++ )
+    {
+        if( put_ret[j] > 0 )
+        {
+            input_len += put_ret[j];
+        }
+    }
+    /* In order to always have a valid pointer we always allocate at least 1
+     * byte. */
+    if( input_len == 0 )
+        input_len = 1;
+    ASSERT_ALLOC( input, input_len );
+
+    output_len = 0;
+    for( j = 0; j < ROUNDS; j++ )
+    {
+        if( get_ret[j] > 0 )
+        {
+            output_len += get_ret[j];
+        }
+    }
+    TEST_ASSERT( output_len <= input_len );
+    /* In order to always have a valid pointer we always allocate at least 1
+     * byte. */
+    if( output_len == 0 )
+        output_len = 1;
+    ASSERT_ALLOC( output, output_len );
+
+    /* Fill up the buffer with structured data so that unwanted changes
+     * can be detected */
+    for( i = 0; i < input_len; i++ )
+    {
+        input[i] = i & 0xFF;
+    }
+
+    written = read = 0;
+    for( j = 0; j < ROUNDS; j++ )
+    {
+        TEST_ASSERT( put_ret[j] == mbedtls_test_buffer_put( &buf,
+                                        input + written, put[j] ) );
+        written += put_ret[j];
+        TEST_ASSERT( get_ret[j] == mbedtls_test_buffer_get( &buf,
+                                        output + read, get[j] ) );
+        read += get_ret[j];
+        TEST_ASSERT( read <= written );
+        if( get_ret[j] > 0 )
+        {
+            TEST_ASSERT( memcmp( output + read - get_ret[j],
+                                 input + read - get_ret[j], get_ret[j] )
+                         == 0 );
+        }
+    }
+
+exit:
+
+    mbedtls_free( input );
+    mbedtls_free( output );
+    mbedtls_test_buffer_free( &buf );
+}
+/* END_CASE */
+
+/*
+ * Test if the implementation of `mbedtls_mock_socket` related I/O functions is
+ * correct and works as expected on unconnected sockets.
+ */
+
+/* BEGIN_CASE */
+void ssl_mock_sanity( )
+{
+    enum { MSGLEN = 105 };
+    unsigned char message[MSGLEN];
+    unsigned char received[MSGLEN];
+    mbedtls_mock_socket socket;
+
+    mbedtls_mock_socket_init( &socket );
+    TEST_ASSERT( mbedtls_mock_tcp_send_b( &socket, message, MSGLEN ) < 0 );
+    mbedtls_mock_socket_close( &socket );
+    mbedtls_mock_socket_init( &socket );
+    TEST_ASSERT( mbedtls_mock_tcp_recv_b( &socket, received, MSGLEN ) < 0 );
+    mbedtls_mock_socket_close( &socket );
+
+    mbedtls_mock_socket_init( &socket );
+    TEST_ASSERT( mbedtls_mock_tcp_send_nb( &socket, message, MSGLEN ) < 0 );
+    mbedtls_mock_socket_close( &socket );
+    mbedtls_mock_socket_init( &socket );
+    TEST_ASSERT( mbedtls_mock_tcp_recv_nb( &socket, received, MSGLEN ) < 0 );
+    mbedtls_mock_socket_close( &socket );
+
+exit:
+
+    mbedtls_mock_socket_close( &socket );
+}
+/* END_CASE */
+
+/*
+ * Test if the implementation of `mbedtls_mock_socket` related functions can
+ * send a single message from the client to the server.
+ */
+
+/* BEGIN_CASE */
+void ssl_mock_tcp( int blocking )
+{
+    enum { MSGLEN = 105 };
+    enum { BUFLEN = MSGLEN / 5 };
+    unsigned char message[MSGLEN];
+    unsigned char received[MSGLEN];
+    mbedtls_mock_socket client;
+    mbedtls_mock_socket server;
+    size_t written, read;
+    int send_ret, recv_ret;
+    mbedtls_ssl_send_t *send;
+    mbedtls_ssl_recv_t *recv;
+    unsigned i;
+
+    if( blocking == 0 )
+    {
+        send = mbedtls_mock_tcp_send_nb;
+        recv = mbedtls_mock_tcp_recv_nb;
+    }
+    else
+    {
+        send = mbedtls_mock_tcp_send_b;
+        recv = mbedtls_mock_tcp_recv_b;
+    }
+
+    mbedtls_mock_socket_init( &client );
+    mbedtls_mock_socket_init( &server );
+
+    /* Fill up the buffer with structured data so that unwanted changes
+     * can be detected */
+    for( i = 0; i < MSGLEN; i++ )
+    {
+        message[i] = i & 0xFF;
+    }
+
+    /* Make sure that sending a message takes a few  iterations. */
+    TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) );
+
+    /* Send the message to the server */
+    send_ret = recv_ret = 1;
+    written = read = 0;
+    while( send_ret != 0 || recv_ret != 0 )
+    {
+        send_ret = send( &client, message + written, MSGLEN - written );
+
+        TEST_ASSERT( send_ret >= 0 );
+        TEST_ASSERT( send_ret <= BUFLEN );
+        written += send_ret;
+
+        /* If the buffer is full we can test blocking and non-blocking send */
+        if ( send_ret == BUFLEN )
+        {
+            int blocking_ret = send( &client, message , 1 );
+            if ( blocking )
+            {
+                TEST_ASSERT( blocking_ret == 0 );
+            }
+            else
+            {
+                TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE );
+            }
+        }
+
+        recv_ret = recv( &server, received + read, MSGLEN - read );
+
+        /* The result depends on whether any data was sent */
+        if ( send_ret > 0 )
+        {
+            TEST_ASSERT( recv_ret > 0 );
+            TEST_ASSERT( recv_ret <= BUFLEN );
+            read += recv_ret;
+        }
+        else if( blocking )
+        {
+            TEST_ASSERT( recv_ret == 0 );
+        }
+        else
+        {
+            TEST_ASSERT( recv_ret == MBEDTLS_ERR_SSL_WANT_READ );
+            recv_ret = 0;
+        }
+
+        /* If the buffer is empty we can test blocking and non-blocking read */
+        if ( recv_ret == BUFLEN )
+        {
+            int blocking_ret = recv( &server, received, 1 );
+            if ( blocking )
+            {
+                TEST_ASSERT( blocking_ret == 0 );
+            }
+            else
+            {
+                TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_READ );
+            }
+        }
+    }
+    TEST_ASSERT( memcmp( message, received, MSGLEN ) == 0 );
+
+exit:
+
+    mbedtls_mock_socket_close( &client );
+    mbedtls_mock_socket_close( &server );
+}
+/* END_CASE */
+
+/*
+ * Test if the implementation of `mbedtls_mock_socket` related functions can
+ * send messages in both direction at the same time (with the I/O calls
+ * interleaving).
+ */
+
+/* BEGIN_CASE */
+void ssl_mock_tcp_interleaving( int blocking )
+{
+    enum { ROUNDS = 2 };
+    enum { MSGLEN = 105 };
+    enum { BUFLEN = MSGLEN / 5 };
+    unsigned char message[ROUNDS][MSGLEN];
+    unsigned char received[ROUNDS][MSGLEN];
+    mbedtls_mock_socket client;
+    mbedtls_mock_socket server;
+    size_t written[ROUNDS];
+    size_t read[ROUNDS];
+    int send_ret[ROUNDS];
+    int recv_ret[ROUNDS];
+    unsigned i, j, progress;
+    mbedtls_ssl_send_t *send;
+    mbedtls_ssl_recv_t *recv;
+
+    if( blocking == 0 )
+    {
+        send = mbedtls_mock_tcp_send_nb;
+        recv = mbedtls_mock_tcp_recv_nb;
+    }
+    else
+    {
+        send = mbedtls_mock_tcp_send_b;
+        recv = mbedtls_mock_tcp_recv_b;
+    }
+
+    mbedtls_mock_socket_init( &client );
+    mbedtls_mock_socket_init( &server );
+
+    /* Fill up the buffers with structured data so that unwanted changes
+     * can be detected */
+    for( i = 0; i < ROUNDS; i++ )
+    {
+        for( j = 0; j < MSGLEN; j++ )
+        {
+            message[i][j] = ( i * MSGLEN + j ) & 0xFF;
+        }
+    }
+
+    /* Make sure that sending a message takes a few  iterations. */
+    TEST_ASSERT( 0 == mbedtls_mock_socket_connect( &client, &server, BUFLEN ) );
+
+    /* Send the message from both sides, interleaving. */
+    progress = 1;
+    for( i = 0; i < ROUNDS; i++ )
+    {
+        written[i] = 0;
+        read[i] = 0;
+    }
+    /* This loop does not stop as long as there was a successful write or read
+     * of at least one byte on either side. */
+    while( progress != 0 )
+    {
+        mbedtls_mock_socket *socket;
+
+        for( i = 0; i < ROUNDS; i++ )
+        {
+            /* First sending is from the client */
+            socket = ( i % 2 == 0 ) ? ( &client ) : ( &server );
+
+            send_ret[i] = send( socket, message[i] + written[i],
+                                               MSGLEN - written[i] );
+            TEST_ASSERT( send_ret[i] >= 0 );
+            TEST_ASSERT( send_ret[i] <= BUFLEN );
+            written[i] += send_ret[i];
+
+            /* If the buffer is full we can test blocking and non-blocking
+             * send */
+            if ( send_ret[i] == BUFLEN )
+            {
+                int blocking_ret = send( socket, message[i] , 1 );
+                if ( blocking )
+                {
+                    TEST_ASSERT( blocking_ret == 0 );
+                }
+                else
+                {
+                    TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_WRITE );
+                }
+            }
+        }
+
+        for( i = 0; i < ROUNDS; i++ )
+        {
+            /* First receiving is from the server */
+            socket = ( i % 2 == 0 ) ? ( &server ) : ( &client );
+
+            recv_ret[i] = recv( socket, received[i] + read[i],
+                                               MSGLEN - read[i] );
+
+            /* The result depends on whether any data was sent */
+            if ( send_ret[i] > 0 )
+            {
+                TEST_ASSERT( recv_ret[i] > 0 );
+                TEST_ASSERT( recv_ret[i] <= BUFLEN );
+                read[i] += recv_ret[i];
+            }
+            else if( blocking )
+            {
+                TEST_ASSERT( recv_ret[i] == 0 );
+            }
+            else
+            {
+                TEST_ASSERT( recv_ret[i] == MBEDTLS_ERR_SSL_WANT_READ );
+                recv_ret[i] = 0;
+            }
+
+            /* If the buffer is empty we can test blocking and non-blocking
+             * read */
+            if ( recv_ret[i] == BUFLEN )
+            {
+                int blocking_ret = recv( socket, received[i], 1 );
+                if ( blocking )
+                {
+                    TEST_ASSERT( blocking_ret == 0 );
+                }
+                else
+                {
+                    TEST_ASSERT( blocking_ret == MBEDTLS_ERR_SSL_WANT_READ );
+                }
+            }
+        }
+
+        progress = 0;
+        for( i = 0; i < ROUNDS; i++ )
+        {
+            progress += send_ret[i] + recv_ret[i];
+        }
+    }
+
+    for( i = 0; i < ROUNDS; i++ )
+        TEST_ASSERT( memcmp( message[i], received[i], MSGLEN ) == 0 );
+
+exit:
+
+    mbedtls_mock_socket_close( &client );
+    mbedtls_mock_socket_close( &server );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 void ssl_dtls_replay( data_t * prevs, data_t * new, int ret )
 {
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index b6dca23..ff0612b 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.19.1"
+check_compiletime_version:"2.20.0"
 
 Check runtime library version
-check_runtime_version:"2.19.1"
+check_runtime_version:"2.20.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 45ae103..2903363 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -176,6 +176,7 @@
     <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />

     <ClInclude Include="..\..\crypto\include\psa\crypto.h" />

     <ClInclude Include="..\..\crypto\include\psa\crypto_accel_driver.h" />

+    <ClInclude Include="..\..\crypto\include\psa\crypto_compat.h" />

     <ClInclude Include="..\..\crypto\include\psa\crypto_driver_common.h" />

     <ClInclude Include="..\..\crypto\include\psa\crypto_entropy_driver.h" />

     <ClInclude Include="..\..\crypto\include\psa\crypto_extra.h" />