Merge pull request #311 from jcowgill/spelling-fix

Fix minor spelling mistake in programs/pkey/gen_key.c
diff --git a/ChangeLog b/ChangeLog
index d3636f0..aa96b18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,76 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
+= mbed TLS 2.1.2 released 2015-10-06
+
+Security
+   * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer
+     overflow of the hostname or session ticket. Found by Guido Vranken,
+     Intelworks.
+   * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than
+     once in the same handhake and mbedtls_ssl_conf_psk() was used.
+     Found and patch provided by Guido Vranken, Intelworks. Cannot be forced
+     remotely.
+   * Fix stack buffer overflow in pkcs12 decryption (used by
+     mbedtls_pk_parse_key(file)() when the password is > 129 bytes.
+     Found by Guido Vranken, Intelworks. Not triggerable remotely.
+   * Fix potential buffer overflow in mbedtls_mpi_read_string().
+     Found by Guido Vranken, Intelworks. Not exploitable remotely in the context
+     of TLS, but might be in other uses. On 32 bit machines, requires reading a
+     string of close to or larger than 1GB to exploit; on 64 bit machines, would
+     require reading a string of close to or larger than 2^62 bytes.
+   * Fix potential random memory allocation in mbedtls_pem_read_buffer()
+     on crafted PEM input data. Found and fix provided by Guido Vranken,
+     Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you
+     accept PEM data from an untrusted source.
+   * Fix possible heap buffer overflow in base64_encoded() when the input
+     buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken,
+     Intelworks. Not trigerrable remotely in TLS.
+   * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on
+     the same mbedtls_ssl_config object and memory allocation fails. Found by
+     Guido Vranken, Intelworks. Cannot be forced remotely.
+   * Fix potential heap buffer overflow in servers that perform client
+     authentication against a crafted CA cert. Cannot be triggered remotely
+     unless you allow third parties to pick trust CAs for client auth.
+     Found by Guido Vranken, Intelworks.
+
+Bugfix
+   * Fix compile error in net.c with musl libc. Found and patch provided by
+     zhasha (#278).
+   * Fix macroization of 'inline' keyword when building as C++. (#279)
+
+Changes
+   * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure
+     domain names are compliant with RFC 1035.
+   * Fixed paths for check_config.h in example config files. (Found by bachp)
+     (#291)
+
+= mbed TLS 2.1.1 released 2015-09-17
+
+Security
+   * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5
+     signatures. (Found by Florian Weimer, Red Hat.)
+     https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/
+   * Fix possible client-side NULL pointer dereference (read) when the client
+     tries to continue the handshake after it failed (a misuse of the API).
+     (Found and patch provided by Fabian Foerg, Gotham Digital Science using
+     afl-fuzz.)
+
+Bugfix
+   * Fix warning when using a 64bit platform. (found by embedthis) (#275)
+   * Fix off-by-one error in parsing Supported Point Format extension that
+     caused some handshakes to fail.
+
+Changes
+   * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow
+     use of mbedtls_x509_crt_profile_next. (found by NWilson)
+   * When a client initiates a reconnect from the same port as a live
+     connection, if cookie verification is available
+     (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie
+     callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be
+     detected and mbedtls_ssl_read() will return
+     MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new
+     handshake with the same context. (See RFC 6347 section 4.2.8.)
+
 = mbed TLS 2.1.0 released 2015-09-04
 
 Features
@@ -87,7 +158,7 @@
      mbedtls_gcm_init() -> mbedtls_gcm_setkey()
      mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)()
      mbedtls_ctr_drbg_init()  -> mbedtls_ctr_drbg_seed()
-     Note that for mbetls_ssl_setup(), you need to be done setting up the
+     Note that for mbedtls_ssl_setup(), you need to be done setting up the
      ssl_config structure before calling it.
    * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(),
      ssl_set_session() and ssl_set_client_transport_id(), plus
diff --git a/README.md b/README.md
index 79943d1..bcc0a32 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@
 
 ### Yotta
 
-[yotta](http://yottabuild.org) is a package manager and build system developped by mbed; it is the build system of mbed OS. To install it on your platform, please follow the yotta [installation instructions](http://docs.yottabuild.org/#installing).
+[yotta](http://yottabuild.org) is a package manager and build system developed by mbed; it is the build system of mbed OS. To install it on your platform, please follow the yotta [installation instructions](http://docs.yottabuild.org/#installing).
 
 Once yotta is installed, you can use it to download the latest version of mbed TLS form the yotta registry with:
 
@@ -64,7 +64,7 @@
 
     make check
 
-The tests need Perl to be built and run. If you don't have Perl installed, you can skip buiding the tests with:
+The tests need Perl to be built and run. If you don't have Perl installed, you can skip building the tests with:
 
     make no_test
 
@@ -122,7 +122,7 @@
 
     cmake -LH
 
-Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first, eg (using GNU find):
+Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first, e.g. (using GNU find):
 
     find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
     CC=gcc CFLAGS='-fstack-protector-strong -Wa,--noexecstack' cmake .
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index bd37091..aee10b8 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -80,6 +80,6 @@
  */
 #define MBEDTLS_SSL_MAX_CONTENT_LEN             512
 
-#include "check_config.h"
+#include "mbedtls/check_config.h"
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/configs/config-picocoin.h b/configs/config-picocoin.h
index 4269872..26b24a9 100644
--- a/configs/config-picocoin.h
+++ b/configs/config-picocoin.h
@@ -66,6 +66,6 @@
 #define MBEDTLS_SHA1_C
 #define MBEDTLS_SHA256_C
 
-#include "check_config.h"
+#include "mbedtls/check_config.h"
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index ca7cd1d..16320da 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -21,7 +21,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.1.0 source code documentation
+ * @mainpage mbed TLS v2.1.2 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 6ca97c1..27b5d4b 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.1.0"
+PROJECT_NAME           = "mbed TLS v2.1.2"
 
 # 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/base64.h b/include/mbedtls/base64.h
index 28a3a4c..352c652 100644
--- a/include/mbedtls/base64.h
+++ b/include/mbedtls/base64.h
@@ -44,6 +44,9 @@
  * \return         0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL.
  *                 *olen is always updated to reflect the amount
  *                 of data that has (or would have) been written.
+ *                 If that length cannot be represented, then no data is
+ *                 written to the buffer and *olen is set to the maximum
+ *                 length representable as a size_t.
  *
  * \note           Call this function with dlen = 0 to obtain the
  *                 required buffer size in *olen
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index cb707e9..8dadbe1 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -421,6 +421,11 @@
 #error "MBEDTLS_SSL_DTLS_HELLO_VERIFY  defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \
+    !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE  defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) &&                              \
     ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
 #error "MBEDTLS_SSL_DTLS_ANTI_REPLAY  defined, but not all prerequisites"
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 87d9c79..70000f5 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -46,7 +46,8 @@
 #define MBEDTLS_CIPHER_MODE_STREAM
 #endif
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 66657da..68153ef 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1135,6 +1135,22 @@
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
 
 /**
+ * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+ *
+ * Enable server-side support for clients that reconnect from the same port.
+ *
+ * Some clients unexpectedly close the connection and try to reconnect using the
+ * same source port. This needs special support from the server to handle the
+ * new connection securely, as described in section 4.2.8 of RFC 6347. This
+ * flag enables that support.
+ *
+ * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Comment this to disable support for clients reusing the source port.
+ */
+#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+
+/**
  * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
  *
  * Enable support for a limit of records with bad MAC.
@@ -1230,6 +1246,8 @@
  * If set, the X509 parser will not break-off when parsing an X509 certificate
  * and encountering an unknown critical extension.
  *
+ * \warning Depending on your PKI use, enabling this can be a security risk!
+ *
  * Uncomment to prevent an error.
  */
 //#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index a049330..059d3c5 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -111,7 +111,7 @@
 
 /**
  * \brief               CTR_DRBG context initialization
- *                      Makes the context ready for mbetls_ctr_drbg_seed() or
+ *                      Makes the context ready for mbedtls_ctr_drbg_seed() or
  *                      mbedtls_ctr_drbg_free().
  *
  * \param ctx           CTR_DRBG context to be initialized
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 4ffc646..e010558 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -98,7 +98,7 @@
 
 /**
  * \brief               HMAC_DRBG context initialization
- *                      Makes the context ready for mbetls_hmac_drbg_seed(),
+ *                      Makes the context ready for mbedtls_hmac_drbg_seed(),
  *                      mbedtls_hmac_drbg_seed_buf() or
  *                      mbedtls_hmac_drbg_free().
  *
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 1834b59..77c2c6f 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -27,10 +27,6 @@
 
 #include <stddef.h>
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
-#define inline __inline
-#endif
-
 #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
 #define MBEDTLS_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
 #define MBEDTLS_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index acd9068..e5e78fb 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -44,6 +44,11 @@
 #include "ecdsa.h"
 #endif
 
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
 #define MBEDTLS_ERR_PK_ALLOC_FAILED        -0x3F80  /**< Memory allocation failed. */
 #define MBEDTLS_ERR_PK_TYPE_MISMATCH       -0x3F00  /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
 #define MBEDTLS_ERR_PK_BAD_INPUT_DATA      -0x3E80  /**< Bad input parameters to function. */
@@ -59,7 +64,6 @@
 #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
 #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH    -0x3900  /**< The signature is valid but its length is less than expected. */
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/mbedtls/pkcs11.h b/include/mbedtls/pkcs11.h
index aa549fd..2e88928 100644
--- a/include/mbedtls/pkcs11.h
+++ b/include/mbedtls/pkcs11.h
@@ -37,7 +37,8 @@
 
 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
@@ -54,7 +55,7 @@
 } mbedtls_pkcs11_context;
 
 /**
- * Initialize a mbetls_pkcs11_context.
+ * Initialize a mbedtls_pkcs11_context.
  * (Just making memory references valid.)
  */
 void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx );
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index bd88918..a017ec0 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -125,6 +125,7 @@
 #define MBEDTLS_ERR_SSL_WANT_READ                         -0x6900  /**< Connection requires a read call. */
 #define MBEDTLS_ERR_SSL_WANT_WRITE                        -0x6880  /**< Connection requires a write call. */
 #define MBEDTLS_ERR_SSL_TIMEOUT                           -0x6800  /**< The operation timed out. */
+#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT                  -0x6780  /**< The client initiated a reconnect from the same port. */
 
 /*
  * Various constants
@@ -138,6 +139,8 @@
 #define MBEDTLS_SSL_TRANSPORT_STREAM            0   /*!< TLS      */
 #define MBEDTLS_SSL_TRANSPORT_DATAGRAM          1   /*!< DTLS     */
 
+#define MBEDTLS_SSL_MAX_HOST_NAME_LEN           255 /*!< Maximum host name defined in RFC 1035 */
+
 /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c
  * NONE must be zero so that memset()ing structure to zero works */
 #define MBEDTLS_SSL_MAX_FRAG_LEN_NONE           0   /*!< don't use this extension   */
@@ -839,7 +842,7 @@
 
 /**
  * \brief          Initialize an SSL context
- *                 Just makes the context ready for mbetls_ssl_setup() or
+ *                 Just makes the context ready for mbedtls_ssl_setup() or
  *                 mbedtls_ssl_free()
  *
  * \param ssl      SSL context
@@ -1169,6 +1172,11 @@
  *                  the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected
  *                  on the first handshake attempt when this is enabled.
  *
+ * \note            This is also necessary to handle client reconnection from
+ *                  the same port as described in RFC 6347 section 4.2.8 (only
+ *                  the variant with cookies is supported currently). See
+ *                  comments on \c mbedtls_ssl_read() for details.
+ *
  * \param conf              SSL configuration
  * \param f_cookie_write    Cookie write callback
  * \param f_cookie_check    Cookie check callback
@@ -1381,7 +1389,7 @@
  * \param profile  Profile to use
  */
 void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
-                                    mbedtls_x509_crt_profile *profile );
+                                    const mbedtls_x509_crt_profile *profile );
 
 /**
  * \brief          Set the data required to verify peer certificate
@@ -2089,29 +2097,35 @@
  *
  * \param ssl      SSL context
  *
- * \return         0 if successful, MBEDTLS_ERR_SSL_WANT_READ,
- *                 MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code.
+ * \return         0 if successful, or
+ *                 MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
+ *                 MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
+ *                 a specific SSL error code.
  *
- * \note           If this function returns non-zero, then the ssl context
+ * \note           If this function returns something other than 0 or
+ *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
  *                 becomes unusable, and you should either free it or call
  *                 \c mbedtls_ssl_session_reset() on it before re-using it.
- *                 If DTLS is in use, then you may choose to handle
+ *
+ * \note           If DTLS is in use, then you may choose to handle
  *                 MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
- *                 purposes, but you still need to reset/free the context.
+ *                 purposes, as it is an expected return value rather than an
+ *                 actual error, but you still need to reset/free the context.
  */
 int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
 
 /**
  * \brief          Perform a single step of the SSL handshake
  *
- *                 Note: the state of the context (ssl->state) will be at
+ * \note           The state of the context (ssl->state) will be at
  *                 the following state after execution of this function.
  *                 Do not call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
  *
  * \param ssl      SSL context
  *
- * \return         0 if successful, MBEDTLS_ERR_SSL_WANT_READ,
- *                 MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code.
+ * \return         0 if successful, or
+ *                 MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
+ *                 a specific SSL error code.
  */
 int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
 
@@ -2138,7 +2152,23 @@
  *
  * \return         the number of bytes read, or
  *                 0 for EOF, or
- *                 a negative error code.
+ *                 MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
+ *                 MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or
+ *                 another negative error code.
+ *
+ * \note           When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ *                 (which can only happen server-side), it means that a client
+ *                 is initiating a new connection using the same source port.
+ *                 You can either treat that as a connection close and wait
+ *                 for the client to resend a ClientHello, or directly
+ *                 continue with \c mbedtls_ssl_handshake() with the same
+ *                 context (as it has beeen reset internally). Either way, you
+ *                 should make sure this is seen by the application as a new
+ *                 connection: application state, if any, should be reset, and
+ *                 most importantly the identity of the client must be checked
+ *                 again. WARNING: not validating the identity of the client
+ *                 again, or not transmitting the new identity to the
+ *                 application layer, would allow authentication bypass!
  */
 int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len );
 
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 73279a5..78c748c 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -41,7 +41,8 @@
 #include "sha512.h"
 #endif
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index cc8754c..ae7a713 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -92,7 +92,7 @@
  *                 (See \c mbedtls_timing_get_delay().)
  *
  * \param data     Pointer to timing data
- *                 Must point to a valid \c mbetls_timing_delay_context struct.
+ *                 Must point to a valid \c mbedtls_timing_delay_context struct.
  * \param int_ms   First (intermediate) delay in milliseconds.
  * \param fin_ms   Second (final) delay in milliseconds.
  *                 Pass 0 to cancel the current delay.
@@ -104,7 +104,7 @@
  *                 (Memory helper: number of delays passed.)
  *
  * \param data     Pointer to timing data
- *                 Must point to a valid \c mbetls_timing_delay_context struct.
+ *                 Must point to a valid \c mbedtls_timing_delay_context struct.
  *
  * \return         -1 if cancelled (fin_ms = 0)
  *                  0 if none of the delays are passed,
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index da76e76..8bc2708 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -39,16 +39,16 @@
  */
 #define MBEDTLS_VERSION_MAJOR  2
 #define MBEDTLS_VERSION_MINOR  1
-#define MBEDTLS_VERSION_PATCH  0
+#define MBEDTLS_VERSION_PATCH  2
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02010000
-#define MBEDTLS_VERSION_STRING         "2.1.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.1.0"
+#define MBEDTLS_VERSION_NUMBER         0x02010200
+#define MBEDTLS_VERSION_STRING         "2.1.2"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.1.2"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index c458117..da66040 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -138,15 +138,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.0 SOVERSION 0)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.2 SOVERSION 0)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.1.0 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.1.2 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.1.0 SOVERSION 10)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.1.2 SOVERSION 10)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/base64.c b/library/base64.c
index 16c254d..3432e5f 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -69,6 +69,8 @@
      49,  50,  51, 127, 127, 127, 127, 127
 };
 
+#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
 /*
  * Encode a buffer into base64 format
  */
@@ -85,15 +87,16 @@
         return( 0 );
     }
 
-    n = ( slen << 3 ) / 6;
+    n = slen / 3 + ( slen % 3 != 0 );
 
-    switch( ( slen << 3 ) - ( n * 6 ) )
+    if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
     {
-        case  2: n += 3; break;
-        case  4: n += 2; break;
-        default: break;
+        *olen = BASE64_SIZE_T_MAX;
+        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
+    n *= 4;
+
     if( dlen < n + 1 )
     {
         *olen = n + 1;
@@ -184,7 +187,10 @@
     }
 
     if( n == 0 )
+    {
+        *olen = 0;
         return( 0 );
+    }
 
     n = ( ( n * 6 ) + 7 ) >> 3;
     n -= j;
diff --git a/library/bignum.c b/library/bignum.c
index 15cbf73..628a6ee 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -58,11 +58,14 @@
 #define biL    (ciL << 3)               /* bits  in limb  */
 #define biH    (ciL << 2)               /* half limb size */
 
+#define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
 /*
  * Convert between bits/chars and number of limbs
+ * Divide first in order to avoid potential overflows
  */
-#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
-#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+#define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
+#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
 
 /*
  * Initialize one MPI
@@ -409,6 +412,9 @@
 
     if( radix == 16 )
     {
+        if( slen > MPI_SIZE_T_MAX >> 2 )
+            return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
         n = BITS_TO_LIMBS( slen << 2 );
 
         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
diff --git a/library/debug.c b/library/debug.c
index 070f63a..4752ab1 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -42,7 +42,8 @@
 #define mbedtls_snprintf    snprintf
 #endif
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
diff --git a/library/ecp.c b/library/ecp.c
index 858540b..64a47ab 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -62,7 +62,8 @@
 #define mbedtls_free       free
 #endif
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 68323c5..9a6e8eb 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -31,7 +31,8 @@
 
 #include <string.h>
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline)
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
 #define inline __inline
 #endif
 
diff --git a/library/error.c b/library/error.c
index a7de110..a1cf83a 100644
--- a/library/error.c
+++ b/library/error.c
@@ -428,6 +428,8 @@
             mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" );
         if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) )
             mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" );
+        if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) )
+            mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" );
 #endif /* MBEDTLS_SSL_TLS_C */
 
 #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
diff --git a/library/net.c b/library/net.c
index b892df9..a77268c 100644
--- a/library/net.c
+++ b/library/net.c
@@ -292,7 +292,7 @@
     struct sockaddr_storage client_addr;
 
 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
-    defined(_SOCKLEN_T_DECLARED)
+    defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
     socklen_t n = (socklen_t) sizeof( client_addr );
     socklen_t type_len = (socklen_t) sizeof( type );
 #else
@@ -319,7 +319,7 @@
         /* UDP: wait for a message, but keep it in the queue */
         char buf[1] = { 0 };
 
-        ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
+        ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
                         (struct sockaddr *) &client_addr, &n );
 
 #if defined(_WIN32)
diff --git a/library/pem.c b/library/pem.c
index 541e870..1ee3966 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -316,6 +316,9 @@
           ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
     }
 
+    if( s1 == s2 )
+        return( MBEDTLS_ERR_PEM_INVALID_DATA );
+
     ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
 
     if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
diff --git a/library/pkcs12.c b/library/pkcs12.c
index f1777eb..7023b9d 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -86,6 +86,8 @@
     return( 0 );
 }
 
+#define PKCS12_MAX_PWDLEN 128
+
 static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
                                      const unsigned char *pwd,  size_t pwdlen,
                                      unsigned char *key, size_t keylen,
@@ -94,7 +96,10 @@
     int ret, iterations;
     mbedtls_asn1_buf salt;
     size_t i;
-    unsigned char unipwd[258];
+    unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
+
+    if( pwdlen > PKCS12_MAX_PWDLEN )
+        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
 
     memset( &salt, 0, sizeof(mbedtls_asn1_buf) );
     memset( &unipwd, 0, sizeof(unipwd) );
@@ -125,6 +130,8 @@
     return( 0 );
 }
 
+#undef PKCS12_MAX_PWDLEN
+
 int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
                              const unsigned char *pwd,  size_t pwdlen,
                              const unsigned char *data, size_t len,
diff --git a/library/rsa.c b/library/rsa.c
index f4ab6b2a..3883d09 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -51,6 +51,8 @@
 #else
 #include <stdio.h>
 #define mbedtls_printf printf
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
 #endif
 
 /*
@@ -1005,6 +1007,11 @@
     size_t nb_pad, olen, oid_size = 0;
     unsigned char *p = sig;
     const char *oid = NULL;
+    unsigned char *sig_try = NULL, *verif = NULL;
+    size_t i;
+    unsigned char diff;
+    volatile unsigned char diff_no_optimize;
+    int ret;
 
     if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1067,9 +1074,39 @@
         memcpy( p, hash, hashlen );
     }
 
-    return( ( mode == MBEDTLS_RSA_PUBLIC )
-            ? mbedtls_rsa_public(  ctx, sig, sig )
-            : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
+    if( mode == MBEDTLS_RSA_PUBLIC )
+        return( mbedtls_rsa_public(  ctx, sig, sig ) );
+
+    /*
+     * In order to prevent Lenstra's attack, make the signature in a
+     * temporary buffer and check it before returning it.
+     */
+    sig_try = mbedtls_calloc( 1, ctx->len );
+    verif   = mbedtls_calloc( 1, ctx->len );
+    if( sig_try == NULL || verif == NULL )
+        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+    MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
+    MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
+
+    /* Compare in constant time just in case */
+    for( diff = 0, i = 0; i < ctx->len; i++ )
+        diff |= verif[i] ^ sig[i];
+    diff_no_optimize = diff;
+
+    if( diff_no_optimize != 0 )
+    {
+        ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
+        goto cleanup;
+    }
+
+    memcpy( sig, sig_try, ctx->len );
+
+cleanup:
+    mbedtls_free( sig_try );
+    mbedtls_free( verif );
+
+    return( ret );
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 5a9c432..32eae0f 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -60,6 +60,7 @@
                                     size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
     size_t hostname_len;
 
     *olen = 0;
@@ -72,6 +73,12 @@
 
     hostname_len = strlen( ssl->hostname );
 
+    if( end < p || (size_t)( end - p ) < hostname_len + 9 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     /*
      * struct {
      *     NameType name_type;
@@ -115,6 +122,7 @@
                                          size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
 
     *olen = 0;
 
@@ -123,6 +131,12 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     /*
      * Secure renegotiation
      */
@@ -149,6 +163,7 @@
                                                 size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
     size_t sig_alg_len = 0;
     const int *md;
 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
@@ -162,9 +177,27 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
 
+    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
+    {
+#if defined(MBEDTLS_ECDSA_C)
+        sig_alg_len += 2;
+#endif
+#if defined(MBEDTLS_RSA_C)
+        sig_alg_len += 2;
+#endif
+    }
+
+    if( end < p || (size_t)( end - p ) < sig_alg_len + 6 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     /*
      * Prepare signature_algorithms extension (TLS 1.2)
      */
+    sig_alg_len = 0;
+
     for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
     {
 #if defined(MBEDTLS_ECDSA_C)
@@ -214,6 +247,7 @@
                                                      size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
     unsigned char *elliptic_curve_list = p + 6;
     size_t elliptic_curve_len = 0;
     const mbedtls_ecp_curve_info *info;
@@ -235,6 +269,25 @@
     for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
     {
 #endif
+        elliptic_curve_len += 2;
+    }
+
+    if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
+    elliptic_curve_len = 0;
+
+#if defined(MBEDTLS_ECP_C)
+    for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
+    {
+        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
+#else
+    for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
+    {
+#endif
 
         elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
         elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
@@ -260,12 +313,18 @@
                                                    size_t *olen )
 {
     unsigned char *p = buf;
-    ((void) ssl);
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
 
     *olen = 0;
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 6 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
 
@@ -285,14 +344,22 @@
                                                size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+
+    *olen = 0;
 
     if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 5 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
 
@@ -310,15 +377,23 @@
                                           unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+
+    *olen = 0;
 
     if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
     {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 4 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
 
@@ -334,17 +409,25 @@
                                        unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+
+    *olen = 0;
 
     if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
         ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
     {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
                         "extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 4 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
 
@@ -360,17 +443,25 @@
                                        unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+
+    *olen = 0;
 
     if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
         ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
     {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret "
                         "extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 4 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
 
@@ -386,16 +477,24 @@
                                           unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
     size_t tlen = ssl->session_negotiate->ticket_len;
 
+    *olen = 0;
+
     if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED )
     {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) );
 
+    if( end < p || (size_t)( end - p ) < 4 + tlen )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET      ) & 0xFF );
 
@@ -404,8 +503,7 @@
 
     *olen = 4;
 
-    if( ssl->session_negotiate->ticket == NULL ||
-        ssl->session_negotiate->ticket_len == 0 )
+    if( ssl->session_negotiate->ticket == NULL || tlen == 0 )
     {
         return;
     }
@@ -423,16 +521,28 @@
                                 unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    size_t alpnlen = 0;
     const char **cur;
 
+    *olen = 0;
+
     if( ssl->conf->alpn_list == NULL )
     {
-        *olen = 0;
         return;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
 
+    for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
+        alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1;
+
+    if( end < p || (size_t)( end - p ) < 6 + alpnlen )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN      ) & 0xFF );
 
@@ -799,13 +909,13 @@
     ext_len += olen;
 #endif
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
+#if defined(MBEDTLS_SSL_ALPN)
+    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
 #endif
 
-#if defined(MBEDTLS_SSL_ALPN)
-    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
 #endif
 
@@ -1771,6 +1881,12 @@
 
     ssl->handshake->pmslen = 48;
 
+    if( ssl->session_negotiate->peer_cert == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
+        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
     /*
      * Now write it out, encrypted
      */
@@ -1873,6 +1989,12 @@
     int ret;
     const mbedtls_ecp_keypair *peer_key;
 
+    if( ssl->session_negotiate->peer_cert == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
+        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
     if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
                      MBEDTLS_PK_ECKEY ) )
     {
@@ -2182,6 +2304,12 @@
         MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
             (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
 
+        if( ssl->session_negotiate->peer_cert == NULL )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
+            return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+
         /*
          * Verify signature
          */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index ca1e7b8..1bda53c 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -299,7 +299,7 @@
         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
 
-    p = buf + 2;
+    p = buf + 1;
     while( list_size > 0 )
     {
         if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
@@ -2351,6 +2351,7 @@
     size_t dn_size, total_dn_size; /* excluding length bytes */
     size_t ct_len, sa_len; /* including length bytes */
     unsigned char *buf, *p;
+    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
     const mbedtls_x509_crt *crt;
     int authmode;
 
@@ -2471,10 +2472,14 @@
     total_dn_size = 0;
     while( crt != NULL && crt->version != 0 )
     {
-        if( p - buf > 4096 )
-            break;
-
         dn_size = crt->subject_raw.len;
+
+        if( end < p || (size_t)( end - p ) < 2 + dn_size )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
+            break;
+        }
+
         *p++ = (unsigned char)( dn_size >> 8 );
         *p++ = (unsigned char)( dn_size      );
         memcpy( p, crt->subject_raw.p, dn_size );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 14ee521..9142be8 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3250,6 +3250,196 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+/* Forward declaration */
+static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
+
+/*
+ * Without any SSL context, check if a datagram looks like a ClientHello with
+ * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
+ * Both input and output include full DTLS headers.
+ *
+ * - if cookie is valid, return 0
+ * - if ClientHello looks superficially valid but cookie is not,
+ *   fill obuf and set olen, then
+ *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
+ * - otherwise return a specific error code
+ */
+static int ssl_check_dtls_clihlo_cookie(
+                           mbedtls_ssl_cookie_write_t *f_cookie_write,
+                           mbedtls_ssl_cookie_check_t *f_cookie_check,
+                           void *p_cookie,
+                           const unsigned char *cli_id, size_t cli_id_len,
+                           const unsigned char *in, size_t in_len,
+                           unsigned char *obuf, size_t buf_len, size_t *olen )
+{
+    size_t sid_len, cookie_len;
+    unsigned char *p;
+
+    if( f_cookie_write == NULL || f_cookie_check == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    /*
+     * Structure of ClientHello with record and handshake headers,
+     * and expected values. We don't need to check a lot, more checks will be
+     * done when actually parsing the ClientHello - skipping those checks
+     * avoids code duplication and does not make cookie forging any easier.
+     *
+     *  0-0  ContentType type;                  copied, must be handshake
+     *  1-2  ProtocolVersion version;           copied
+     *  3-4  uint16 epoch;                      copied, must be 0
+     *  5-10 uint48 sequence_number;            copied
+     * 11-12 uint16 length;                     (ignored)
+     *
+     * 13-13 HandshakeType msg_type;            (ignored)
+     * 14-16 uint24 length;                     (ignored)
+     * 17-18 uint16 message_seq;                copied
+     * 19-21 uint24 fragment_offset;            copied, must be 0
+     * 22-24 uint24 fragment_length;            (ignored)
+     *
+     * 25-26 ProtocolVersion client_version;    (ignored)
+     * 27-58 Random random;                     (ignored)
+     * 59-xx SessionID session_id;              1 byte len + sid_len content
+     * 60+   opaque cookie<0..2^8-1>;           1 byte len + content
+     *       ...
+     *
+     * Minimum length is 61 bytes.
+     */
+    if( in_len < 61 ||
+        in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
+        in[3] != 0 || in[4] != 0 ||
+        in[19] != 0 || in[20] != 0 || in[21] != 0 )
+    {
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    sid_len = in[59];
+    if( sid_len > in_len - 61 )
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    cookie_len = in[60 + sid_len];
+    if( cookie_len > in_len - 60 )
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
+                        cli_id, cli_id_len ) == 0 )
+    {
+        /* Valid cookie */
+        return( 0 );
+    }
+
+    /*
+     * If we get here, we've got an invalid cookie, let's prepare HVR.
+     *
+     *  0-0  ContentType type;                  copied
+     *  1-2  ProtocolVersion version;           copied
+     *  3-4  uint16 epoch;                      copied
+     *  5-10 uint48 sequence_number;            copied
+     * 11-12 uint16 length;                     olen - 13
+     *
+     * 13-13 HandshakeType msg_type;            hello_verify_request
+     * 14-16 uint24 length;                     olen - 25
+     * 17-18 uint16 message_seq;                copied
+     * 19-21 uint24 fragment_offset;            copied
+     * 22-24 uint24 fragment_length;            olen - 25
+     *
+     * 25-26 ProtocolVersion server_version;    0xfe 0xff
+     * 27-27 opaque cookie<0..2^8-1>;           cookie_len = olen - 27, cookie
+     *
+     * Minimum length is 28.
+     */
+    if( buf_len < 28 )
+        return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+
+    /* Copy most fields and adapt others */
+    memcpy( obuf, in, 25 );
+    obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
+    obuf[25] = 0xfe;
+    obuf[26] = 0xff;
+
+    /* Generate and write actual cookie */
+    p = obuf + 28;
+    if( f_cookie_write( p_cookie,
+                        &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
+    {
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    *olen = p - obuf;
+
+    /* Go back and fill length fields */
+    obuf[27] = (unsigned char)( *olen - 28 );
+
+    obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
+    obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >>  8 );
+    obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 )       );
+
+    obuf[11] = (unsigned char)( ( *olen - 13 ) >>  8 );
+    obuf[12] = (unsigned char)( ( *olen - 13 )       );
+
+    return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
+}
+
+/*
+ * Handle possible client reconnect with the same UDP quadruplet
+ * (RFC 6347 Section 4.2.8).
+ *
+ * Called by ssl_parse_record_header() in case we receive an epoch 0 record
+ * that looks like a ClientHello.
+ *
+ * - if the input looks like a ClientHello without cookies,
+ *   send back HelloVerifyRequest, then
+ *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
+ * - if the input looks like a ClientHello with a valid cookie,
+ *   reset the session of the current context, and
+ *   return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ * - if anything goes wrong, return a specific error code
+ *
+ * mbedtls_ssl_read_record() will ignore the record if anything else than
+ * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function
+ * cannot not return 0.
+ */
+static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
+{
+    int ret;
+    size_t len;
+
+    ret = ssl_check_dtls_clihlo_cookie(
+            ssl->conf->f_cookie_write,
+            ssl->conf->f_cookie_check,
+            ssl->conf->p_cookie,
+            ssl->cli_id, ssl->cli_id_len,
+            ssl->in_buf, ssl->in_left,
+            ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len );
+
+    MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
+
+    if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
+    {
+        /* Dont check write errors as we can't do anything here.
+         * If the error is permanent we'll catch it later,
+         * if it's not, then hopefully it'll work next time. */
+        (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
+
+        return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
+    }
+
+    if( ret == 0 )
+    {
+        /* Got a valid cookie, partially reset context */
+        if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
+            return( ret );
+        }
+
+        return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
+    }
+
+    return( ret );
+}
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+
 /*
  * ContentType type;
  * ProtocolVersion version;
@@ -3341,13 +3531,36 @@
         if( rec_epoch != ssl->in_epoch )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
-                                "expected %d, received %d",
-                                 ssl->in_epoch, rec_epoch ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+                                        "expected %d, received %d",
+                                        ssl->in_epoch, rec_epoch ) );
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+            /*
+             * Check for an epoch 0 ClientHello. We can't use in_msg here to
+             * access the first byte of record content (handshake type), as we
+             * have an active transform (possibly iv_len != 0), so use the
+             * fact that the record header len is 13 instead.
+             */
+            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+                ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+                rec_epoch == 0 &&
+                ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+                ssl->in_left > 13 &&
+                ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
+                                            "from the same port" ) );
+                return( ssl_handle_possible_reconnect( ssl ) );
+            }
+            else
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+                return( MBEDTLS_ERR_SSL_INVALID_RECORD );
         }
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-        if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
+        /* Replay detection only works for the current epoch */
+        if( rec_epoch == ssl->in_epoch &&
+            mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3528,7 +3741,8 @@
     if( ( ret = ssl_parse_record_header( ssl ) ) != 0 )
     {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+            ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
         {
             /* Ignore bad record and get next one; drop the whole datagram
              * since current header cannot be trusted to find the next record
@@ -5123,8 +5337,11 @@
 /*
  * Reset an initialized and used SSL context for re-use while retaining
  * all application-set variables, function pointers and data.
+ *
+ * If partial is non-zero, keep data in the input buffer and client ID.
+ * (Use when a DTLS client reconnects from the same port.)
  */
-int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
+static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
 {
     int ret;
 
@@ -5148,7 +5365,8 @@
     ssl->in_msg = ssl->in_buf + 13;
     ssl->in_msgtype = 0;
     ssl->in_msglen = 0;
-    ssl->in_left = 0;
+    if( partial == 0 )
+        ssl->in_left = 0;
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     ssl->next_record_offset = 0;
     ssl->in_epoch = 0;
@@ -5174,7 +5392,8 @@
     ssl->transform_out = NULL;
 
     memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
-    memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
+    if( partial == 0 )
+        memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_reset != NULL )
@@ -5207,9 +5426,12 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
-    mbedtls_free( ssl->cli_id );
-    ssl->cli_id = NULL;
-    ssl->cli_id_len = 0;
+    if( partial == 0 )
+    {
+        mbedtls_free( ssl->cli_id );
+        ssl->cli_id = NULL;
+        ssl->cli_id_len = 0;
+    }
 #endif
 
     if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
@@ -5219,6 +5441,15 @@
 }
 
 /*
+ * Reset an initialized and used SSL context for re-use while retaining
+ * all application-set variables, function pointers and data.
+ */
+int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
+{
+    return( ssl_session_reset_int( ssl, 0 ) );
+}
+
+/*
  * SSL set accessors
  */
 void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint )
@@ -5372,7 +5603,7 @@
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
-                                    mbedtls_x509_crt_profile *profile )
+                                    const mbedtls_x509_crt_profile *profile )
 {
     conf->cert_profile = profile;
 }
@@ -5476,7 +5707,9 @@
         ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL )
     {
         mbedtls_free( conf->psk );
+        mbedtls_free( conf->psk_identity );
         conf->psk = NULL;
+        conf->psk_identity = NULL;
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
     }
 
@@ -5499,7 +5732,7 @@
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
     if( ssl->handshake->psk != NULL )
-        mbedtls_free( ssl->conf->psk );
+        mbedtls_free( ssl->handshake->psk );
 
     if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
     {
@@ -5602,6 +5835,9 @@
     if( hostname_len + 1 == 0 )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
+    if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
     ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 );
 
     if( ssl->hostname == NULL )
@@ -6762,7 +6998,7 @@
 #endif
 
 /*
- * Load default in mbetls_ssl_config
+ * Load default in mbedtls_ssl_config
  */
 int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
                                  int endpoint, int transport, int preset )
diff --git a/library/version_features.c b/library/version_features.c
index c2f30f2..196b93c 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -369,6 +369,9 @@
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
     "MBEDTLS_SSL_DTLS_HELLO_VERIFY",
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
+    "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE",
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */
 #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
     "MBEDTLS_SSL_DTLS_BADMAC_LIMIT",
 #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 606fc93..322e8af 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -40,7 +40,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
-           "MBEDTLS_SHA256_C and/or MBEDLTS_MD_C and/or "
+           "MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or "
            "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or "
            "MBEDTLS_CTR_DRBG_C not defined.\n");
     return( 0 );
diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
index 469ad9f..e897c65 100644
--- a/programs/pkey/rsa_sign.c
+++ b/programs/pkey/rsa_sign.c
@@ -40,7 +40,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
-            "MBEDLTS_MD_C and/or "
+            "MBEDTLS_MD_C and/or "
             "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
     return( 0 );
 }
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
index 9d48a18..ade36dc 100644
--- a/programs/pkey/rsa_verify.c
+++ b/programs/pkey/rsa_verify.c
@@ -39,7 +39,7 @@
 int main( void )
 {
     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or "
-            "MBEDLTS_MD_C and/or "
+            "MBEDTLS_MD_C and/or "
             "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n");
     return( 0 );
 }
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 99c2d2a..c090db9 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -90,6 +90,7 @@
 #define DFL_DHMLEN              -1
 #define DFL_RECONNECT           0
 #define DFL_RECO_DELAY          0
+#define DFL_RECONNECT_HARD      0
 #define DFL_TICKETS             MBEDTLS_SSL_SESSION_TICKETS_ENABLED
 #define DFL_ALPN_STRING         NULL
 #define DFL_TRANSPORT           MBEDTLS_SSL_TRANSPORT_STREAM
@@ -222,7 +223,7 @@
     "    debug_level=%%d      default: 0 (disabled)\n"      \
     "    nbio=%%d             default: 0 (blocking I/O)\n"  \
     "                        options: 1 (non-blocking), 2 (added delays)\n" \
-    "    read_timeout=%%d     default: 0 (no timeout)\n"    \
+    "    read_timeout=%%d     default: 0 ms (no timeout)\n"    \
     "    max_resend=%%d       default: 0 (no resend on timeout)\n" \
     "\n"                                                    \
     USAGE_DTLS                                              \
@@ -238,6 +239,7 @@
     "    exchanges=%%d        default: 1\n"                 \
     "    reconnect=%%d        default: 0 (disabled)\n"      \
     "    reco_delay=%%d       default: 0 seconds\n"         \
+    "    reconnect_hard=%%d   default: 0 (disabled)\n"      \
     USAGE_TICKETS                                           \
     USAGE_MAX_FRAG_LEN                                      \
     USAGE_TRUNC_HMAC                                        \
@@ -293,6 +295,7 @@
     int dhmlen;                 /* minimum DHM params len in bits           */
     int reconnect;              /* attempt to resume session                */
     int reco_delay;             /* delay in seconds before resuming session */
+    int reconnect_hard;         /* unexpectedly reconnect from the same port */
     int tickets;                /* enable / disable session tickets         */
     const char *alpn_string;    /* ALPN supported protocols                 */
     int transport;              /* TLS or DTLS?                             */
@@ -481,6 +484,7 @@
     opt.dhmlen              = DFL_DHMLEN;
     opt.reconnect           = DFL_RECONNECT;
     opt.reco_delay          = DFL_RECO_DELAY;
+    opt.reconnect_hard      = DFL_RECONNECT_HARD;
     opt.tickets             = DFL_TICKETS;
     opt.alpn_string         = DFL_ALPN_STRING;
     opt.transport           = DFL_TRANSPORT;
@@ -603,6 +607,12 @@
             if( opt.reco_delay < 0 )
                 goto usage;
         }
+        else if( strcmp( p, "reconnect_hard" ) == 0 )
+        {
+            opt.reconnect_hard = atoi( q );
+            if( opt.reconnect_hard < 0 || opt.reconnect_hard > 1 )
+                goto usage;
+        }
         else if( strcmp( p, "tickets" ) == 0 )
         {
             opt.tickets = atoi( q );
@@ -1479,7 +1489,38 @@
     }
 
     /*
-     * 7b. Continue doing data exchanges?
+     * 7b. Simulate hard reset and reconnect from same port?
+     */
+    if( opt.reconnect_hard != 0 )
+    {
+        opt.reconnect_hard = 0;
+
+        mbedtls_printf( "  . Restarting connection from same port..." );
+        fflush( stdout );
+
+        if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
+        {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
+            goto exit;
+        }
+
+        while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
+        {
+            if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
+                goto exit;
+            }
+        }
+
+        mbedtls_printf( " ok\n" );
+
+        goto send_request;
+    }
+
+    /*
+     * 7c. Continue doing data exchanges?
      */
     if( --opt.exchanges > 0 )
         goto send_request;
@@ -1489,6 +1530,7 @@
      */
 close_notify:
     mbedtls_printf( "  . Closing the connection..." );
+    fflush( stdout );
 
     /* No error checking, the connection might be closed already */
     do ret = mbedtls_ssl_close_notify( &ssl );
@@ -1513,7 +1555,6 @@
 #endif
 
         mbedtls_printf( "  . Reconnecting with saved session..." );
-        fflush( stdout );
 
         if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
         {
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index f169291..bd4d1d1 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -301,7 +301,7 @@
     "    debug_level=%%d      default: 0 (disabled)\n"      \
     "    nbio=%%d             default: 0 (blocking I/O)\n"  \
     "                        options: 1 (non-blocking), 2 (added delays)\n" \
-    "    read_timeout=%%d     default: 0 (no timeout)\n"    \
+    "    read_timeout=%%d     default: 0 ms (no timeout)\n"    \
     "\n"                                                    \
     USAGE_DTLS                                              \
     USAGE_COOKIES                                           \
@@ -1838,6 +1838,12 @@
     }
 #endif
 
+    if( ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
+    {
+        mbedtls_printf( "  ! Client initiated reconnection from same port\n" );
+        goto handshake;
+    }
+
 #ifdef MBEDTLS_ERROR_C
     if( ret != 0 )
     {
@@ -1903,6 +1909,7 @@
     /*
      * 4. Handshake
      */
+handshake:
     mbedtls_printf( "  . Performing the SSL/TLS handshake..." );
     fflush( stdout );
 
diff --git a/scripts/memory.sh b/scripts/memory.sh
index 0738e7d..3dad289 100755
--- a/scripts/memory.sh
+++ b/scripts/memory.sh
@@ -52,6 +52,8 @@
         scripts/config.pl unset $FLAG
     done
 
+    grep -F SSL_MAX_CONTENT_LEN $CONFIG_H || echo 'SSL_MAX_CONTENT_LEN=16384'
+
     printf "    Executable size... "
 
     make clean
diff --git a/tests/scripts/yotta-build.sh b/tests/scripts/yotta-build.sh
index 59cedf4..2648d3e 100755
--- a/tests/scripts/yotta-build.sh
+++ b/tests/scripts/yotta-build.sh
@@ -6,7 +6,7 @@
 
 yotta/create-module.sh
 cd yotta/module
-# yt update # needs network
+yt update || true # needs network
 
 yotta_build()
 {
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 77db588..e494413 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2867,6 +2867,40 @@
             -s "hello verification requested" \
             -S "SSL - The requested feature is not available"
 
+# Tests for client reconnecting from the same port with DTLS
+
+not_with_valgrind # spurious resend
+run_test    "DTLS client reconnect from same port: reference" \
+            "$P_SRV dtls=1 exchanges=2 read_timeout=1000" \
+            "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000" \
+            0 \
+            -C "resend" \
+            -S "The operation timed out" \
+            -S "Client initiated reconnection from same port"
+
+not_with_valgrind # spurious resend
+run_test    "DTLS client reconnect from same port: reconnect" \
+            "$P_SRV dtls=1 exchanges=2 read_timeout=1000" \
+            "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \
+            0 \
+            -C "resend" \
+            -S "The operation timed out" \
+            -s "Client initiated reconnection from same port"
+
+run_test    "DTLS client reconnect from same port: reconnect, nbio" \
+            "$P_SRV dtls=1 exchanges=2 read_timeout=1000 nbio=2" \
+            "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \
+            0 \
+            -S "The operation timed out" \
+            -s "Client initiated reconnection from same port"
+
+run_test    "DTLS client reconnect from same port: no cookies" \
+            "$P_SRV dtls=1 exchanges=2 read_timeout=1000 cookies=0" \
+            "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-8000 reconnect_hard=1" \
+            0 \
+            -s "The operation timed out" \
+            -S "Client initiated reconnection from same port"
+
 # Tests for various cases of client authentication with DTLS
 # (focused on handshake flows and message parsing)
 
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 3b66da1..da99ffa 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -1,23 +1,41 @@
-Test case mbedtls_base64_encode #1
-mbedtls_base64_encode:"":"":1000:0
+Test case mbedtls_base64_encode #1 buffer just right
+mbedtls_base64_encode:"":"":0:0
 
-Test case mbedtls_base64_encode #2
-mbedtls_base64_encode:"f":"Zg==":1000:0
+Test case mbedtls_base64_encode #2 buffer just right
+mbedtls_base64_encode:"f":"Zg==":5:0
 
-Test case mbedtls_base64_encode #3
-mbedtls_base64_encode:"fo":"Zm8=":1000:0
+Test case mbedtls_base64_encode #2 buffer too small
+mbedtls_base64_encode:"f":"Zg==":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
-Test case mbedtls_base64_encode #4
-mbedtls_base64_encode:"foo":"Zm9v":1000:0
+Test case mbedtls_base64_encode #3 buffer just right
+mbedtls_base64_encode:"fo":"Zm8=":5:0
 
-Test case mbedtls_base64_encode #5
-mbedtls_base64_encode:"foob":"Zm9vYg==":1000:0
+Test case mbedtls_base64_encode #3 buffer too small
+mbedtls_base64_encode:"fo":"Zm8=":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
-Test case mbedtls_base64_encode #6
-mbedtls_base64_encode:"fooba":"Zm9vYmE=":1000:0
+Test case mbedtls_base64_encode #4 buffer just right
+mbedtls_base64_encode:"foo":"Zm9v":5:0
 
-Test case mbedtls_base64_encode #7
-mbedtls_base64_encode:"foobar":"Zm9vYmFy":1000:0
+Test case mbedtls_base64_encode #4 buffer too small
+mbedtls_base64_encode:"foo":"Zm9v":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #5 buffer just right
+mbedtls_base64_encode:"foob":"Zm9vYg==":9:0
+
+Test case mbedtls_base64_encode #5 buffer too small
+mbedtls_base64_encode:"foob":"Zm9vYg==":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #6 buffer just right
+mbedtls_base64_encode:"fooba":"Zm9vYmE=":9:0
+
+Test case mbedtls_base64_encode #6 buffer too small
+mbedtls_base64_encode:"fooba":"Zm9vYmE=":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #7 buffer just right
+mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0
+
+Test case mbedtls_base64_encode #7 buffer too small
+mbedtls_base64_encode:"foobar":"Zm9vYmFy":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
 Test case mbedtls_base64_decode #1
 mbedtls_base64_decode:"":"":0
@@ -40,12 +58,6 @@
 Test case mbedtls_base64_decode #7
 mbedtls_base64_decode:"Zm9vYmFy":"foobar":0
 
-Base64 encode (buffer size just right)
-mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0
-
-Base64 encode (buffer size too small)
-mbedtls_base64_encode:"foobar":"":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
-
 Base64 decode (Illegal character)
 mbedtls_base64_decode:"zm#=":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 29ea2d2..a2955c6 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.1.0"
+check_compiletime_version:"2.1.2"
 
 Check runtime library version
-check_runtime_version:"2.1.0"
+check_runtime_version:"2.1.2"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/yotta/data/example-authcrypt/main.cpp b/yotta/data/example-authcrypt/main.cpp
index 2f49aa9..257a1ad 100644
--- a/yotta/data/example-authcrypt/main.cpp
+++ b/yotta/data/example-authcrypt/main.cpp
@@ -187,7 +187,7 @@
 }
 
 void app_start(int, char*[]) {
-    minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
 }
 
 #else
diff --git a/yotta/data/example-benchmark/main.cpp b/yotta/data/example-benchmark/main.cpp
index 6ac2a29..1a6c7ae 100644
--- a/yotta/data/example-benchmark/main.cpp
+++ b/yotta/data/example-benchmark/main.cpp
@@ -947,7 +947,7 @@
 }
 
 void app_start(int, char*[]) {
-    minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
 }
 
 #endif /* TARGET_LIKE_MBED */
diff --git a/yotta/data/example-hashing/main.cpp b/yotta/data/example-hashing/main.cpp
index 4ef3665..7603cbe 100644
--- a/yotta/data/example-hashing/main.cpp
+++ b/yotta/data/example-hashing/main.cpp
@@ -167,7 +167,7 @@
 }
 
 void app_start(int, char*[]) {
-    minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
 }
 
 #else
diff --git a/yotta/data/example-selftest/main.cpp b/yotta/data/example-selftest/main.cpp
index 22fd466..046a548 100644
--- a/yotta/data/example-selftest/main.cpp
+++ b/yotta/data/example-selftest/main.cpp
@@ -258,7 +258,7 @@
 }
 
 void app_start(int, char*[]) {
-    minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
 }
 
 #else
diff --git a/yotta/data/example-tls-client/main.cpp b/yotta/data/example-tls-client/main.cpp
index 684f1c1..907cfb6 100644
--- a/yotta/data/example-tls-client/main.cpp
+++ b/yotta/data/example-tls-client/main.cpp
@@ -513,7 +513,7 @@
 
     printf("Client IP Address is %s\r\n", eth.getIPAddress());
 
-    mbed::FunctionPointer1<void, const char*> fp(hello, &HelloHTTPS::startTest);
+    mbed::util::FunctionPointer1<void, const char*> fp(hello, &HelloHTTPS::startTest);
     minar::Scheduler::postCallback(fp.bind(HTTPS_PATH));
 }
 
diff --git a/yotta/data/module.json b/yotta/data/module.json
index eaf07ba..1a65834 100644
--- a/yotta/data/module.json
+++ b/yotta/data/module.json
@@ -1,8 +1,7 @@
 {
     "name": "mbedtls",
-    "version": "2.1.0",
+    "version": "2.1.3",
     "description": "The mbed TLS crypto/SSL/TLS library",
-    "private": true,
     "licenses": [
         {
             "url": "https://spdx.org/licenses/Apache-2.0",
@@ -14,6 +13,6 @@
         "mbed": { "cmsis-core": "~0.2.3" }
     },
     "testTargetDependencies": {
-        "mbed": { "sockets": "~0.3.0" }
+        "mbed": { "sockets": "~0.5.0" }
     }
 }