Merge remote-tracking branch 'public/pr/1902' into development
diff --git a/ChangeLog b/ChangeLog
index 7bc6710..c420b96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,77 @@
 
 = mbed TLS x.x.x branch released xxxx-xx-xx
 
+Features
+   * Add support for temporarily suspending expensive ECC computations after
+     some configurable amount of operations, to be used in single-threaded
+     constrained systems where ECC is time consuming and blocking until
+     completion cannot be tolerated. This is enabled by
+     MBEDTLS_ECP_RESTARTABLE at compile time (disabled by default) and
+     configured by mbedtls_ecp_set_max_ops() at runtime. It applies to new
+     xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported
+     yet), and to existing functions in ECDH and SSL (currently only
+     implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2,
+     including client authentication).
+
 Bugfix
+   * Fix a bug in the update function for SSL ticket keys which previously
+     invalidated keys of a lifetime of less than a 1s. Fixes #1968.
+   * Fix failure in hmac_drbg in the benchmark sample application, when
+     MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095
+
+Changes
+   * Removed support for Yotta as a build tool.
+   * Add tests for session resumption in DTLS.
+   * Close a test gap in (D)TLS between the client side and the server side:
+     test the handling of large packets and small packets on the client side
+     in the same way as on the server side.
+   * Change the dtls_client and dtls_server samples to work by default over
+     IPv6 and optionally by a build option over IPv4.
+
+= mbed TLS 2.13.1 branch released 2018-09-06
+
+API Changes
+   * Extend the platform module with an abstraction mbedtls_platform_gmtime_r()
+     whose implementation should behave as a thread-safe version of gmtime().
+     This allows users to configure such an implementation at compile time when
+     the target system cannot be deduced automatically, by setting the option
+     MBEDTLS_PLATFORM_GMTIME_R_ALT. At this stage Mbed TLS is only able to
+     automatically select implementations for Windows and POSIX C libraries.
+
+Bugfix
+   * Fix build failures on platforms where only gmtime() is available but
+     neither gmtime_r() nor gmtime_s() are present. Fixes #1907.
+
+= mbed TLS 2.13.0 branch released 2018-08-31
+
+Security
+   * Fix an issue in the X.509 module which could lead to a buffer overread
+     during certificate extensions parsing. In case of receiving malformed
+     input (extensions length field equal to 0), an illegal read of one byte
+     beyond the input buffer is made. Found and analyzed by Nathan Crandall.
+
+Features
+   * Add support for fragmentation of outgoing DTLS handshake messages. This
+     is controlled by the maximum fragment length as set locally or negotiated
+     with the peer, as well as by a new per-connection MTU option, set using
+     mbedtls_ssl_set_mtu().
+   * Add support for auto-adjustment of MTU to a safe value during the
+     handshake when flights do not get through (RFC 6347, section 4.1.1.1,
+     last paragraph).
+   * Add support for packing multiple records within a single datagram,
+     enabled by default.
+   * Add support for buffering out-of-order handshake messages in DTLS.
+     The maximum amount of RAM used for this can be controlled by the
+     compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined
+     in mbedtls/config.h.
+
+API Changes
+   * Add function mbedtls_ssl_set_datagram_packing() to configure
+     the use of datagram packing (enabled by default).
+
+Bugfix
+   * Fix a potential memory leak in mbedtls_ssl_setup() function. An allocation
+     failure in the function could lead to other buffers being leaked.
    * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if
      MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890
    * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails.
@@ -10,9 +80,23 @@
    * Add ecc extensions only if an ecc based ciphersuite is used.
      This improves compliance to RFC 4492, and as a result, solves
      interoperability issues with BouncyCastle. Raised by milenamil in #1157.
-   * Replace printf with mbedtls_printf in aria. Found by TrinityTonic in #1908.
+   * Replace printf with mbedtls_printf in the ARIA module. Found by
+     TrinityTonic in #1908.
    * Fix potential use-after-free in mbedtls_ssl_get_max_frag_len()
      and mbedtls_ssl_get_record_expansion() after a session reset. Fixes #1941.
+   * Fix a bug that caused SSL/TLS clients to incorrectly abort the handshake
+     with TLS versions 1.1 and earlier when the server requested authentication
+     without providing a list of CAs. This was due to an overly strict bounds
+     check in parsing the CertificateRequest message,
+     introduced in Mbed TLS 2.12.0. Fixes #1954.
+   * Fix a miscalculation of the maximum record expansion in
+     mbedtls_ssl_get_record_expansion() in case of ChachaPoly ciphersuites,
+     or CBC ciphersuites in (D)TLS versions 1.1 or higher. Fixes #1913, #1914.
+   * Fix undefined shifts with negative values in certificates parsing
+     (found by Catena cyber using oss-fuzz)
+   * Fix memory leak and free without initialization in pk_encrypt
+     and pk_decrypt example programs. Reported by Brace Stout. Fixes #1128.
+   * Remove redundant else statement. Raised by irwir. Fixes #1776.
 
 Changes
    * Copy headers preserving timestamps when doing a "make install".
@@ -21,6 +105,10 @@
      Drozd. Fixes #1215 raised by randombit.
    * Improve compatibility with some alternative CCM implementations by using
      CCM test vectors from RAM.
+   * Add support for buffering of out-of-order handshake messages.
+   * Add warnings to the documentation of the HKDF module to reduce the risk
+     of misusing the mbedtls_hkdf_extract() and mbedtls_hkdf_expand()
+     functions. Fixes #1775. Reported by Brian J. Murray.
 
 = mbed TLS 2.12.0 branch released 2018-07-25
 
diff --git a/README.md b/README.md
index 6345848..d7a0e9d 100644
--- a/README.md
+++ b/README.md
@@ -11,47 +11,16 @@
 Compiling
 ---------
 
-There are currently four active build systems used within Mbed TLS releases:
+There are currently three active build systems used within Mbed TLS releases:
 
--   yotta
 -   GNU Make
 -   CMake
 -   Microsoft Visual Studio (Microsoft Visual Studio 2010 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.
 
-Yotta, as a build system, is slightly different from the other build systems:
-
--   it provides a minimalistic configuration file by default
--   depending on the yotta target, features of Mbed OS may be used in examples and tests
-
 The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls.
 
-### Yotta
-
-[yotta](http://yottabuild.org) is a package manager and build system developed by Mbed, and is the build system of Mbed OS 16.03. 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 from the yotta registry with:
-
-    yotta install mbedtls
-
-and build it with:
-
-    yotta build
-
-If, on the other hand, you already have a copy of Mbed TLS from a source other than the yotta registry, for example from cloning our GitHub repository, or from downloading a tarball of the standalone edition, then you'll first need to generate the yotta module by running:
-
-    yotta/create-module.sh
-
-This should be executed from the root Mbed TLS project directory. This will create the yotta module in the `yotta/module` directory within it. You can then change to that directory and build as usual:
-
-    cd yotta/module
-    yotta build
-
-In any case, you'll probably want to set the yotta target before building unless it has already been set globally. For more information on using yotta, please consult the [yotta documentation](http://docs.yottabuild.org/).
-
-For more details on the yotta/Mbed OS edition of Mbed TLS, including example programs, please consult the [Readme at the root of the yotta module](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/README.md).
-
 ### Make
 
 We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools.
@@ -78,7 +47,7 @@
 
 Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.
 
-Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so it you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overriden from the command line.
+Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overriden from the command line.
 
 Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
 
@@ -169,7 +138,7 @@
 Example programs
 ----------------
 
-We've included example programs for a lot of different features and uses in `programs/`. Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
+We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
 
 Tests
 -----
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index f695dd2..b9f9ec1 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.12.0 source code documentation
+ * @mainpage mbed TLS v2.13.1 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 317eb0d..8df061e 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.12.0"
+PROJECT_NAME           = "mbed TLS v2.13.1"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
@@ -664,7 +664,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ..
+INPUT                  = ../include input
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -696,7 +696,7 @@
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = ../configs ../yotta/module
+EXCLUDE                =
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
diff --git a/include/mbedtls/bn_mul.h b/include/mbedtls/bn_mul.h
index b587317..6679389 100644
--- a/include/mbedtls/bn_mul.h
+++ b/include/mbedtls/bn_mul.h
@@ -565,9 +565,8 @@
 #endif /* TriCore */
 
 /*
- * gcc -O0 by default uses r7 for the frame pointer, so it complains about our
- * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
- * passing that option is not easy when building with yotta.
+ * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
+ * our use of r7 below, unless -fomit-frame-pointer is passed.
  *
  * On the other hand, -fomit-frame-pointer is implied by any -Ox options with
  * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index dbcfb57..28e860b 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -137,12 +137,21 @@
 /**
  * \def MBEDTLS_HAVE_TIME_DATE
  *
- * System has time.h and time(), gmtime() and the clock is correct.
+ * System has time.h, time(), and an implementation for
+ * mbedtls_platform_gmtime_r() (see below).
  * The time needs to be correct (not necesarily very accurate, but at least
  * the date should be correct). This is used to verify the validity period of
  * X.509 certificates.
  *
  * Comment if your system does not have a correct clock.
+ *
+ * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
+ * behaves similarly to the gmtime_r() function from the C standard. Refer to
+ * the documentation for mbedtls_platform_gmtime_r() for more information.
+ *
+ * \note It is possible to configure an implementation for
+ * mbedtls_platform_gmtime_r() at compile-time by using the macro
+ * MBEDTLS_PLATFORM_GMTIME_R_ALT.
  */
 #define MBEDTLS_HAVE_TIME_DATE
 
@@ -669,6 +678,26 @@
 #define MBEDTLS_ECP_NIST_OPTIM
 
 /**
+ * \def MBEDTLS_ECP_RESTARTABLE
+ *
+ * Enable "non-blocking" ECC operations that can return early and be resumed.
+ *
+ * This allows various functions to pause by returning
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
+ * order to further progress and eventually complete their operation. This is
+ * controlled through mbedtls_ecp_set_max_ops() which limits the maximum
+ * number of ECC operations a function may perform before pausing; see
+ * mbedtls_ecp_set_max_ops() for more information.
+ *
+ * This is useful in non-threaded environments if you want to avoid blocking
+ * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
+ *
+ * Uncomment this macro to enable restartable ECC computations.
+ */
+//#define MBEDTLS_ECP_RESTARTABLE
+
+/**
  * \def MBEDTLS_ECDSA_DETERMINISTIC
  *
  * Enable deterministic ECDSA (RFC 6979).
@@ -3013,6 +3042,23 @@
  */
 //#define MBEDTLS_SSL_OUT_CONTENT_LEN             16384
 
+/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING
+ *
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ *
+ * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
+ * to account for a reassembled handshake message of maximum size,
+ * together with its reassembly bitmap.
+ *
+ * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)
+ * should be sufficient for all practical situations as it allows
+ * to reassembly a large handshake message (such as a certificate)
+ * while buffering multiple smaller handshake messages.
+ *
+ */
+//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING             32768
+
 //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
 //#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
 //#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
@@ -3086,25 +3132,33 @@
  */
 //#define MBEDTLS_PLATFORM_ZEROIZE_ALT
 
+/**
+ * Uncomment the macro to let Mbed TLS use your alternate implementation of
+ * mbedtls_platform_gmtime_r(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * gmtime() is not a thread-safe function as defined in the C standard. The
+ * library will try to use safer implementations of this function, such as
+ * gmtime_r() when available. However, if Mbed TLS cannot identify the target
+ * system, the implementation of mbedtls_platform_gmtime_r() will default to
+ * using the standard gmtime(). In this case, calls from the library to
+ * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
+ * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
+ * library are also guarded with this mutex to avoid race conditions. However,
+ * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
+ * unconditionally use the implementation for mbedtls_platform_gmtime_r()
+ * supplied at compile time.
+ */
+//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
+
 /* \} name SECTION: Customisation configuration options */
 
-/* Target and application specific configurations */
-//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h"
-
-#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
-#endif
-
-/*
+/* Target and application specific configurations
+ *
  * Allow user to override any previous default.
  *
- * Use two macro names for that, as:
- * - with yotta the prefix YOTTA_CFG_ is forced
- * - without yotta is looks weird to have a YOTTA prefix.
  */
-#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
-#elif defined(MBEDTLS_USER_CONFIG_FILE)
+#if defined(MBEDTLS_USER_CONFIG_FILE)
 #include MBEDTLS_USER_CONFIG_FILE
 #endif
 
diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h
index 95f3980..27f2ffc 100644
--- a/include/mbedtls/ecdh.h
+++ b/include/mbedtls/ecdh.h
@@ -50,6 +50,10 @@
 } mbedtls_ecdh_side;
 
 /**
+ *
+ * \warning         Performing multiple operations concurrently on the same
+ *                  ECDSA context is not supported; objects of this type
+ *                  should not be shared between multiple threads.
  * \brief           The ECDH context structure.
  */
 typedef struct mbedtls_ecdh_context
@@ -63,6 +67,10 @@
     mbedtls_ecp_point Vi;    /*!< The blinding value. */
     mbedtls_ecp_point Vf;    /*!< The unblinding value. */
     mbedtls_mpi _d;          /*!< The previous \p d. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    int restart_enabled;        /*!< The flag for restartable mode. */
+    mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
+#endif
 }
 mbedtls_ecdh_context;
 
@@ -83,9 +91,8 @@
  * \param p_rng     The RNG context.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX or
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX or
  *                  \c MBEDTLS_MPI_XXX error code on failure.
- *
  */
 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
                      int (*f_rng)(void *, unsigned char *, size_t),
@@ -112,7 +119,7 @@
  * \param p_rng     The RNG context.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX or
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX or
  *                  \c MBEDTLS_MPI_XXX error code on failure.
  */
 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
@@ -155,7 +162,9 @@
  * \param p_rng     The RNG context.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
  */
 int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
                       unsigned char *buf, size_t blen,
@@ -197,7 +206,7 @@
  *                  0: The key of the peer.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
  *
  */
 int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
@@ -220,7 +229,9 @@
  * \param p_rng     The RNG context.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
  */
 int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
                       unsigned char *buf, size_t blen,
@@ -266,13 +277,31 @@
  * \param p_rng     The RNG context.
  *
  * \return          \c 0 on success.
- * \return          An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
  */
 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
                       unsigned char *buf, size_t blen,
                       int (*f_rng)(void *, unsigned char *, size_t),
                       void *p_rng );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           This function enables restartable EC computations for this
+ *                  context.  (Default: disabled.)
+ *
+ * \see             \c mbedtls_ecp_set_max_ops()
+ *
+ * \note            It is not possible to safely disable restartable
+ *                  computations once enabled, except by free-ing the context,
+ *                  which cancels possible in-progress operations.
+ *
+ * \param ctx       The ECDH context.
+ */
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index ce1a03d..4057828 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -55,16 +55,66 @@
 /** The maximal size of an ECDSA signature in Bytes. */
 #define MBEDTLS_ECDSA_MAX_LEN  ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
 
-/**
- * \brief           The ECDSA context structure.
- */
-typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
+ * \brief           The ECDSA context structure.
+ *
+ * \warning         Performing multiple operations concurrently on the same
+ *                  ECDSA context is not supported; objects of this type
+ *                  should not be shared between multiple threads.
+ */
+typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief           Internal restart context for ecdsa_verify()
+ *
+ * \note            Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
+
+/**
+ * \brief           Internal restart context for ecdsa_sign()
+ *
+ * \note            Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/**
+ * \brief           Internal restart context for ecdsa_sign_det()
+ *
+ * \note            Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
+#endif
+
+/**
+ * \brief           General context for resuming ECDSA operations
+ */
+typedef struct
+{
+    mbedtls_ecp_restart_ctx ecp;        /*!<  base context for ECP restart and
+                                              shared administrative info    */
+    mbedtls_ecdsa_restart_ver_ctx *ver; /*!<  ecdsa_verify() sub-context    */
+    mbedtls_ecdsa_restart_sig_ctx *sig; /*!<  ecdsa_sign() sub-context      */
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+    mbedtls_ecdsa_restart_det_ctx *det; /*!<  ecdsa_sign_det() sub-context  */
+#endif
+} mbedtls_ecdsa_restart_ctx;
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_ecdsa_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+/**
  * \brief           This function computes the ECDSA signature of a
  *                  previously-hashed message.
  *
@@ -205,6 +255,40 @@
                            int (*f_rng)(void *, unsigned char *, size_t),
                            void *p_rng );
 
+/**
+ * \brief           This function computes the ECDSA signature and writes it
+ *                  to a buffer, in a restartable way.
+ *
+ * \see             \c mbedtls_ecdsa_write_signature()
+ *
+ * \note            This function is like \c mbedtls_ecdsa_write_signature()
+ *                  but it can return early and restart according to the limit
+ *                  set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx       The ECDSA context.
+ * \param md_alg    The message digest that was used to hash the message.
+ * \param hash      The message hash.
+ * \param hlen      The length of the hash.
+ * \param sig       The buffer that holds the signature.
+ * \param slen      The length of the signature written.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ * \param rs_ctx    The restart context (NULL disables restart).
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
+ *                  \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+                           mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hlen,
+                           unsigned char *sig, size_t *slen,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           mbedtls_ecdsa_restart_ctx *rs_ctx );
+
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
 #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
 #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -289,6 +373,37 @@
                           const unsigned char *sig, size_t slen );
 
 /**
+ * \brief           This function reads and verifies an ECDSA signature,
+ *                  in a restartable way.
+ *
+ * \see             \c mbedtls_ecdsa_read_signature()
+ *
+ * \note            This function is like \c mbedtls_ecdsa_read_signature()
+ *                  but it can return early and restart according to the limit
+ *                  set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx       The ECDSA context.
+ * \param hash      The message hash.
+ * \param hlen      The size of the hash.
+ * \param sig       The signature to read and verify.
+ * \param slen      The size of \p sig.
+ * \param rs_ctx    The restart context (NULL disables restart).
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
+ * \return          #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
+ *                  signature in \p sig, but its length is less than \p siglen.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return          Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
+ *                  error code on failure for any other reason.
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+                          const unsigned char *hash, size_t hlen,
+                          const unsigned char *sig, size_t slen,
+                          mbedtls_ecdsa_restart_ctx *rs_ctx );
+
+/**
  * \brief          This function generates an ECDSA keypair on the given curve.
  *
  * \see            ecp.h
@@ -332,6 +447,18 @@
  */
 void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Initialize a restart context
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx );
+
+/**
+ * \brief           Free the components of a restart context
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index ed1b9d7..5db8752 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -50,6 +50,7 @@
 #define MBEDTLS_ERR_ECP_INVALID_KEY                       -0x4C80  /**< Invalid private or public key. */
 #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< The buffer contains a valid signature followed by more data. */
 #define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED                   -0x4B80  /**< The ECP hardware accelerator failed. */
+#define MBEDTLS_ERR_ECP_IN_PROGRESS                       -0x4B00  /**< Operation in progress, call again with the same parameters to continue. */
 
 #ifdef __cplusplus
 extern "C" {
@@ -181,6 +182,70 @@
 }
 mbedtls_ecp_group;
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief           Internal restart context for multiplication
+ *
+ * \note            Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx;
+
+/**
+ * \brief           Internal restart context for ecp_muladd()
+ *
+ * \note            Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx;
+
+/**
+ * \brief           General context for resuming ECC operations
+ */
+typedef struct
+{
+    unsigned ops_done;                  /*!<  current ops count             */
+    unsigned depth;                     /*!<  call depth (0 = top-level)    */
+    mbedtls_ecp_restart_mul_ctx *rsm;   /*!<  ecp_mul_comb() sub-context    */
+    mbedtls_ecp_restart_muladd_ctx *ma; /*!<  ecp_muladd() sub-context      */
+} mbedtls_ecp_restart_ctx;
+
+/*
+ * Operation counts for restartable functions
+ */
+#define MBEDTLS_ECP_OPS_CHK   3 /*!< basic ops count for ecp_check_pubkey()  */
+#define MBEDTLS_ECP_OPS_DBL   8 /*!< basic ops count for ecp_double_jac()    */
+#define MBEDTLS_ECP_OPS_ADD  11 /*!< basic ops count for see ecp_add_mixed() */
+#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv()  */
+
+/**
+ * \brief           Internal; for restartable functions in other modules.
+ *                  Check and update basic ops budget.
+ *
+ * \param grp       Group structure
+ * \param rs_ctx    Restart context
+ * \param ops       Number of basic ops to do
+ *
+ * \return          \c 0 if doing \p ops basic ops is still allowed,
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise.
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+                              mbedtls_ecp_restart_ctx *rs_ctx,
+                              unsigned ops );
+
+/* Utility macro for checking and updating ops budget */
+#define MBEDTLS_ECP_BUDGET( ops )   \
+    MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \
+                                               (unsigned) (ops) ) );
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define MBEDTLS_ECP_BUDGET( ops )   /* no-op; for compatibility */
+
+/* We want to declare restartable versions of existing functions anyway */
+typedef void mbedtls_ecp_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 /**
  * \name SECTION: Module settings
  *
@@ -270,6 +335,75 @@
  */
 #define MBEDTLS_ECP_TLS_NAMED_CURVE    3   /**< The named_curve of ECCurveType. */
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Set the maximum number of basic operations done in a row.
+ *
+ *                  If more operations are needed to complete a computation,
+ *                  #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the
+ *                  function performing the computation. It is then the
+ *                  caller's responsibility to either call again with the same
+ *                  parameters until it returns 0 or an error code; or to free
+ *                  the restart context if the operation is to be aborted.
+ *
+ *                  It is strictly required that all input parameters and the
+ *                  restart context be the same on successive calls for the
+ *                  same operation, but output parameters need not be the
+ *                  same; they must not be used until the function finally
+ *                  returns 0.
+ *
+ *                  This only applies to functions whose documentation
+ *                  mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or
+ *                  #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the
+ *                  SSL module). For functions that accept a "restart context"
+ *                  argument, passing NULL disables restart and makes the
+ *                  function equivalent to the function with the same name
+ *                  with \c _restartable removed. For functions in the ECDH
+ *                  module, restart is disabled unless the function accepts
+ *                  an "ECDH context" argument and
+ *                  mbedtls_ecdh_enable_restart() was previously called on
+ *                  that context. For function in the SSL module, restart is
+ *                  only enabled for specific sides and key exchanges
+ *                  (currently only for clients and ECDHE-ECDSA).
+ *
+ * \param max_ops   Maximum number of basic operations done in a row.
+ *                  Default: 0 (unlimited).
+ *                  Lower (non-zero) values mean ECC functions will block for
+ *                  a lesser maximum amount of time.
+ *
+ * \note            A "basic operation" is defined as a rough equivalent of a
+ *                  multiplication in GF(p) for the NIST P-256 curve.
+ *                  As an indication, with default settings, a scalar
+ *                  multiplication (full run of \c mbedtls_ecp_mul()) is:
+ *                  - about 3300 basic operations for P-256
+ *                  - about 9400 basic operations for P-384
+ *
+ * \note            Very low values are not always respected: sometimes
+ *                  functions need to block for a minimum number of
+ *                  operations, and will do so even if max_ops is set to a
+ *                  lower value.  That minimum depends on the curve size, and
+ *                  can be made lower by decreasing the value of
+ *                  \c MBEDTLS_ECP_WINDOW_SIZE.  As an indication, here is the
+ *                  lowest effective value for various curves and values of
+ *                  that parameter (w for short):
+ *                          w=6     w=5     w=4     w=3     w=2
+ *                  P-256   208     208     160     136     124
+ *                  P-384   682     416     320     272     248
+ *                  P-521  1364     832     640     544     496
+ *
+ * \note            This setting is currently ignored by Curve25519.
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops );
+
+/**
+ * \brief           Check if restart is enabled (max_ops != 0)
+ *
+ * \return          \c 0 if \c max_ops == 0 (restart disabled)
+ * \return          \c 1 otherwise (restart enabled)
+ */
+int mbedtls_ecp_restart_is_enabled( void );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 /**
  * \brief           This function retrieves the information defined in
  *                  mbedtls_ecp_curve_info() for all supported curves in order
@@ -366,6 +500,18 @@
  */
 void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Initialize a restart context
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx );
+
+/**
+ * \brief           Free the components of a restart context
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 /**
  * \brief           This function copies the contents of point \p Q into
  *                  point \p P.
@@ -598,6 +744,36 @@
              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
 /**
+ * \brief           This function performs multiplication of a point by
+ *                  an integer: \p R = \p m * \p P in a restartable way.
+ *
+ * \see             mbedtls_ecp_mul()
+ *
+ * \note            This function does the same as \c mbedtls_ecp_mul(), but
+ *                  it can return early and restart according to the limit set
+ *                  with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp       The ECP group.
+ * \param R         The destination point.
+ * \param m         The integer by which to multiply.
+ * \param P         The point to multiply.
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG context.
+ * \param rs_ctx    The restart context (NULL disables restart).
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private
+ *                  key, or \p P is not a valid public key.
+ * \return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+             mbedtls_ecp_restart_ctx *rs_ctx );
+
+/**
  * \brief           This function performs multiplication and addition of two
  *                  points by integers: \p R = \p m * \p P + \p n * \p Q
  *
@@ -624,6 +800,39 @@
              const mbedtls_mpi *n, const mbedtls_ecp_point *Q );
 
 /**
+ * \brief           This function performs multiplication and addition of two
+ *                  points by integers: \p R = \p m * \p P + \p n * \p Q in a
+ *                  restartable way.
+ *
+ * \see             \c mbedtls_ecp_muladd()
+ *
+ * \note            This function works the same as \c mbedtls_ecp_muladd(),
+ *                  but it can return early and restart according to the limit
+ *                  set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp       The ECP group.
+ * \param R         The destination point.
+ * \param m         The integer by which to multiply \p P.
+ * \param P         The point to multiply by \p m.
+ * \param n         The integer by which to multiply \p Q.
+ * \param Q         The point to be multiplied by \p n.
+ * \param rs_ctx    The restart context (NULL disables restart).
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not
+ *                  valid private keys, or \p P or \p Q are not valid public
+ *                  keys.
+ * \return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_ecp_muladd_restartable(
+             mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+             const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+             mbedtls_ecp_restart_ctx *rs_ctx );
+
+/**
  * \brief           This function checks that a point is a valid public key
  *                  on this curve.
  *
@@ -666,6 +875,23 @@
 int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
 
 /**
+ * \brief           This function generates a private key.
+ *
+ * \param grp       The ECP group.
+ * \param d         The destination MPI (secret part).
+ * \param f_rng     The RNG function.
+ * \param p_rng     The RNG parameter.
+ *
+ * \return          \c 0 on success.
+ * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
+ *                  on failure.
+ */
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+                     mbedtls_mpi *d,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
+
+/**
  * \brief           This function generates a keypair with a configurable base
  *                  point.
  *
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 6b82d4f..39cd67f 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -80,6 +80,7 @@
  * CHACHA20  3                  0x0051-0x0055
  * POLY1305  3                  0x0057-0x005B
  * CHACHAPOLY 2 0x0054-0x0056
+ * PLATFORM  1  0x0070-0x0070
  *
  * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
@@ -90,12 +91,12 @@
  * DHM       3   11
  * PK        3   15 (Started from top)
  * RSA       4   11
- * ECP       4   9 (Started from top)
+ * ECP       4   10 (Started from top)
  * MD        5   5
  * HKDF      5   1 (Started from top)
  * CIPHER    6   8
- * SSL       6   22 (Started from top)
- * SSL       7   31
+ * SSL       6   23 (Started from top)
+ * SSL       7   32
  *
  * Module dependent error code (5 bits 0x.00.-0x.F8.)
  */
diff --git a/include/mbedtls/hkdf.h b/include/mbedtls/hkdf.h
index 6833e72..e6ed7cd 100644
--- a/include/mbedtls/hkdf.h
+++ b/include/mbedtls/hkdf.h
@@ -73,6 +73,11 @@
  *  \brief  Take the input keying material \p ikm and extract from it a
  *          fixed-length pseudorandom key \p prk.
  *
+ *  \warning    This function should only be used if the security of it has been
+ *              studied and established in that particular context (eg. TLS 1.3
+ *              key schedule). For standard HKDF security guarantees use
+ *              \c mbedtls_hkdf instead.
+ *
  *  \param       md        A hash function; md.size denotes the length of the
  *                         hash function output in bytes.
  *  \param       salt      An optional salt value (a non-secret random value);
@@ -97,10 +102,15 @@
  *  \brief  Expand the supplied \p prk into several additional pseudorandom
  *          keys, which is the output of the HKDF.
  *
+ *  \warning    This function should only be used if the security of it has been
+ *              studied and established in that particular context (eg. TLS 1.3
+ *              key schedule). For standard HKDF security guarantees use
+ *              \c mbedtls_hkdf instead.
+ *
  *  \param  md        A hash function; md.size denotes the length of the hash
  *                    function output in bytes.
- *  \param  prk       A pseudorandom key of at least md.size bytes. \p prk is usually,
- *                    the output from the HKDF extract step.
+ *  \param  prk       A pseudorandom key of at least md.size bytes. \p prk is
+ *                    usually the output from the HKDF extract step.
  *  \param  prk_len   The length in bytes of \p prk.
  *  \param  info      An optional context and application specific information
  *                    string. This can be a zero-length string.
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index db54c6a..9ec33da 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -127,10 +127,24 @@
  */
 typedef struct mbedtls_pk_context
 {
-    const mbedtls_pk_info_t *   pk_info; /**< Public key informations        */
+    const mbedtls_pk_info_t *   pk_info; /**< Public key information         */
     void *                      pk_ctx;  /**< Underlying public key context  */
 } mbedtls_pk_context;
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Context for resuming operations
+ */
+typedef struct
+{
+    const mbedtls_pk_info_t *   pk_info; /**< Public key information         */
+    void *                      rs_ctx;  /**< Underlying restart context     */
+} mbedtls_pk_restart_ctx;
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_pk_restart_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
 #if defined(MBEDTLS_RSA_C)
 /**
  * Quick access to an RSA context inside a PK context.
@@ -190,6 +204,18 @@
  */
 void mbedtls_pk_free( mbedtls_pk_context *ctx );
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Initialize a restart context
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx );
+
+/**
+ * \brief           Free the components of a restart context
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
 /**
  * \brief           Initialize a PK context with the information given
  *                  and allocates the type-specific PK subcontext.
@@ -287,6 +313,32 @@
                const unsigned char *sig, size_t sig_len );
 
 /**
+ * \brief           Restartable version of \c mbedtls_pk_verify()
+ *
+ * \note            Performs the same job as \c mbedtls_pk_verify(), but can
+ *                  return early and restart according to the limit set with
+ *                  \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ *                  operations. For RSA, same as \c mbedtls_pk_verify().
+ *
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ * \param rs_ctx    Restart context (NULL to disable restart)
+ *
+ * \return          See \c mbedtls_pk_verify(), or
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+               mbedtls_md_type_t md_alg,
+               const unsigned char *hash, size_t hash_len,
+               const unsigned char *sig, size_t sig_len,
+               mbedtls_pk_restart_ctx *rs_ctx );
+
+/**
  * \brief           Verify signature, with options.
  *                  (Includes verification of the padding depending on type.)
  *
@@ -350,6 +402,35 @@
              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
 /**
+ * \brief           Restartable version of \c mbedtls_pk_sign()
+ *
+ * \note            Performs the same job as \c mbedtls_pk_sign(), but can
+ *                  return early and restart according to the limit set with
+ *                  \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ *                  operations. For RSA, same as \c mbedtls_pk_sign().
+ *
+ * \param ctx       PK context to use - must hold a private key
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Place to write the signature
+ * \param sig_len   Number of bytes written
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ * \param rs_ctx    Restart context (NULL to disable restart)
+ *
+ * \return          See \c mbedtls_pk_sign(), or
+ * \return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                  operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+             mbedtls_md_type_t md_alg,
+             const unsigned char *hash, size_t hash_len,
+             unsigned char *sig, size_t *sig_len,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+             mbedtls_pk_restart_ctx *rs_ctx );
+
+/**
  * \brief           Decrypt message (including padding if relevant).
  *
  * \param ctx       PK context to use - must hold a private key
diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h
index 3dae0fc..48b7a5f 100644
--- a/include/mbedtls/pk_internal.h
+++ b/include/mbedtls/pk_internal.h
@@ -59,6 +59,21 @@
                       int (*f_rng)(void *, unsigned char *, size_t),
                       void *p_rng );
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /** Verify signature (restartable) */
+    int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hash_len,
+                           const unsigned char *sig, size_t sig_len,
+                           void *rs_ctx );
+
+    /** Make signature (restartable) */
+    int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+                         const unsigned char *hash, size_t hash_len,
+                         unsigned char *sig, size_t *sig_len,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng, void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
     /** Decrypt message */
     int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
                          unsigned char *output, size_t *olen, size_t osize,
@@ -80,6 +95,14 @@
     /** Free the given context */
     void (*ctx_free_func)( void *ctx );
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /** Allocate the restart context */
+    void * (*rs_alloc_func)( void );
+
+    /** Free the restart context */
+    void (*rs_free_func)( void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
     /** Interface with the debug module */
     void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
 
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index a40a64f..5cd143c 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -43,6 +43,8 @@
 #include "platform_time.h"
 #endif
 
+#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED       -0x0070 /**< Hardware accelerator failed */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 84f0732..164a1a0 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -25,7 +25,17 @@
 #ifndef MBEDTLS_PLATFORM_UTIL_H
 #define MBEDTLS_PLATFORM_UTIL_H
 
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
 #include <stddef.h>
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_time.h"
+#include <time.h>
+#endif /* MBEDTLS_HAVE_TIME_DATE */
 
 #ifdef __cplusplus
 extern "C" {
@@ -55,6 +65,37 @@
  */
 void mbedtls_platform_zeroize( void *buf, size_t len );
 
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief      Platform-specific implementation of gmtime_r()
+ *
+ *             The function is a thread-safe abstraction that behaves
+ *             similarly to the gmtime_r() function from Unix/POSIX.
+ *
+ *             Mbed TLS will try to identify the underlying platform and
+ *             make use of an appropriate underlying implementation (e.g.
+ *             gmtime_r() for POSIX and gmtime_s() for Windows). If this is
+ *             not possible, then gmtime() will be used. In this case, calls
+ *             from the library to gmtime() will be guarded by the mutex
+ *             mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is
+ *             enabled. It is recommended that calls from outside the library
+ *             are also guarded by this mutex.
+ *
+ *             If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will
+ *             unconditionally use the alternative implementation for
+ *             mbedtls_platform_gmtime_r() supplied by the user at compile time.
+ *
+ * \param tt     Pointer to an object containing time (in seconds) since the
+ *               epoch to be converted
+ * \param tm_buf Pointer to an object where the results will be stored
+ *
+ * \return      Pointer to an object of type struct tm on success, otherwise
+ *              NULL
+ */
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+                                      struct tm *tm_buf );
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 2d511a8..e8f664a 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -121,6 +121,8 @@
 #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH               -0x6600  /**< Couldn't set the hash for verifying CertificateVerify */
 #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING               -0x6580  /**< Internal-only message signaling that further message-processing should be done */
 #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS                 -0x6500  /**< The asynchronous operation is not completed yet. */
+#define MBEDTLS_ERR_SSL_EARLY_MESSAGE                     -0x6480  /**< Internal-only message signaling that a message arrived early. */
+#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS                -0x7000  /**< A cryptographic operation is in progress. Try again later. */
 
 /*
  * Various constants
@@ -242,6 +244,14 @@
 #define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
 #endif
 
+/*
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ */
+#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING)
+#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
+#endif
+
 /* \} name SECTION: Module settings */
 
 /*
@@ -1022,14 +1032,14 @@
     int renego_records_seen;    /*!< Records since renego request, or with DTLS,
                                   number of retransmissions of request if
                                   renego_max_records is < 0           */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
 
     int major_ver;              /*!< equal to  MBEDTLS_SSL_MAJOR_VERSION_3    */
     int minor_ver;              /*!< either 0 (SSL3) or 1 (TLS1.0)    */
 
 #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
     unsigned badmac_seen;       /*!< records with a bad MAC received    */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
     mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
     mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
@@ -1085,11 +1095,11 @@
     uint16_t in_epoch;          /*!< DTLS epoch for incoming records  */
     size_t next_record_offset;  /*!< offset of the next record in datagram
                                      (equal to in_left if none)       */
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
     uint64_t in_window_top;     /*!< last validated record seq_num    */
     uint64_t in_window;         /*!< bitmask for replay detection     */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
     size_t in_hslen;            /*!< current handshake message length,
                                      including the handshake header   */
@@ -1098,6 +1108,11 @@
     int keep_current_message;   /*!< drop or reuse current message
                                      on next call to record layer? */
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    uint8_t disable_datagram_packing;  /*!< Disable packing multiple records
+                                        *   within a single datagram.  */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
     /*
      * Record layer (outgoing data)
      */
@@ -1112,12 +1127,18 @@
     size_t out_msglen;          /*!< record header: message length    */
     size_t out_left;            /*!< amount of data not yet written   */
 
+    unsigned char cur_out_ctr[8]; /*!<  Outgoing record sequence  number. */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    uint16_t mtu;               /*!< path mtu, used to fragment outgoing messages */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     unsigned char *compress_buf;        /*!<  zlib data buffer        */
-#endif
+#endif /* MBEDTLS_ZLIB_SUPPORT */
 #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
     signed char split_done;     /*!< current record already splitted? */
-#endif
+#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
 
     /*
      * PKI layer
@@ -1130,11 +1151,11 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     char *hostname;             /*!< expected peer CN for verification
                                      (and SNI if available)                 */
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_ALPN)
     const char *alpn_chosen;    /*!<  negotiated protocol                   */
-#endif
+#endif /* MBEDTLS_SSL_ALPN */
 
     /*
      * Information for DTLS hello verify
@@ -1142,7 +1163,7 @@
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
     unsigned char  *cli_id;         /*!<  transport-level ID of the client  */
     size_t          cli_id_len;     /*!<  length of cli_id                  */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
 
     /*
      * Secure renegotiation
@@ -1154,7 +1175,7 @@
     size_t verify_data_len;             /*!<  length of verify data stored   */
     char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
     char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
 };
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
@@ -1374,6 +1395,52 @@
                           mbedtls_ssl_recv_t *f_recv,
                           mbedtls_ssl_recv_timeout_t *f_recv_timeout );
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+/**
+ * \brief          Set the Maximum Tranport Unit (MTU).
+ *                 Special value: 0 means unset (no limit).
+ *                 This represents the maximum size of a datagram payload
+ *                 handled by the transport layer (usually UDP) as determined
+ *                 by the network link and stack. In practice, this controls
+ *                 the maximum size datagram the DTLS layer will pass to the
+ *                 \c f_send() callback set using \c mbedtls_ssl_set_bio().
+ *
+ * \note           The limit on datagram size is converted to a limit on
+ *                 record payload by subtracting the current overhead of
+ *                 encapsulation and encryption/authentication if any.
+ *
+ * \note           This can be called at any point during the connection, for
+ *                 example when a Path Maximum Transfer Unit (PMTU)
+ *                 estimate becomes available from other sources,
+ *                 such as lower (or higher) protocol layers.
+ *
+ * \note           This setting only controls the size of the packets we send,
+ *                 and does not restrict the size of the datagrams we're
+ *                 willing to receive. Client-side, you can request the
+ *                 server to use smaller records with \c
+ *                 mbedtls_ssl_conf_max_frag_len().
+ *
+ * \note           If both a MTU and a maximum fragment length have been
+ *                 configured (or negotiated with the peer), the resulting
+ *                 lower limit on record payload (see first note) is used.
+ *
+ * \note           This can only be used to decrease the maximum size
+ *                 of datagrams (hence records, see first note) sent. It
+ *                 cannot be used to increase the maximum size of records over
+ *                 the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN.
+ *
+ * \note           Values lower than the current record layer expansion will
+ *                 result in an error when trying to send data.
+ *
+ * \note           Using record compression together with a non-zero MTU value
+ *                 will result in an error when trying to send data.
+ *
+ * \param ssl      SSL context
+ * \param mtu      Value of the path MTU in bytes
+ */
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
 /**
  * \brief          Set the timeout period for mbedtls_ssl_read()
  *                 (Default: no timeout.)
@@ -1757,6 +1824,38 @@
 #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/**
+ * \brief          Allow or disallow packing of multiple handshake records
+ *                 within a single datagram.
+ *
+ * \param ssl           The SSL context to configure.
+ * \param allow_packing This determines whether datagram packing may
+ *                      be used or not. A value of \c 0 means that every
+ *                      record will be sent in a separate datagram; a
+ *                      value of \c 1 means that, if space permits,
+ *                      multiple handshake messages (including CCS) belonging to
+ *                      a single flight may be packed within a single datagram.
+ *
+ * \note           This is enabled by default and should only be disabled
+ *                 for test purposes, or if datagram packing causes
+ *                 interoperability issues with peers that don't support it.
+ *
+ * \note           Allowing datagram packing reduces the network load since
+ *                 there's less overhead if multiple messages share the same
+ *                 datagram. Also, it increases the handshake efficiency
+ *                 since messages belonging to a single datagram will not
+ *                 be reordered in transit, and so future message buffering
+ *                 or flight retransmission (if no buffering is used) as
+ *                 means to deal with reordering are needed less frequently.
+ *
+ * \note           Application records are not affected by this option and
+ *                 are currently always sent in separate datagrams.
+ *
+ */
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+                                       unsigned allow_packing );
+
 /**
  * \brief          Set retransmit timeout values for the DTLS handshake.
  *                 (DTLS only, no effect on TLS.)
@@ -2433,6 +2532,18 @@
  *                 (Client: set maximum fragment length to emit *and*
  *                 negotiate with the server during handshake)
  *
+ * \note           With TLS, this currently only affects ApplicationData (sent
+ *                 with \c mbedtls_ssl_read()), not handshake messages.
+ *                 With DTLS, this affects both ApplicationData and handshake.
+ *
+ * \note           This sets the maximum length for a record's payload,
+ *                 excluding record overhead that will be added to it, see
+ *                 \c mbedtls_ssl_get_record_expansion().
+ *
+ * \note           For DTLS, it is also possible to set a limit for the total
+ *                 size of daragrams passed to the transport layer, including
+ *                 record overhead, see \c mbedtls_ssl_set_mtu().
+ *
  * \param conf     SSL configuration
  * \param mfl_code Code for maximum fragment length (allowed values:
  *                 MBEDTLS_SSL_MAX_FRAG_LEN_512,  MBEDTLS_SSL_MAX_FRAG_LEN_1024,
@@ -2695,6 +2806,9 @@
  * \brief          Return the (maximum) number of bytes added by the record
  *                 layer: header + encryption/MAC overhead (inc. padding)
  *
+ * \note           This function is not available (always returns an error)
+ *                 when record compression is enabled.
+ *
  * \param ssl      SSL context
  *
  * \return         Current maximum record expansion in bytes, or
@@ -2709,12 +2823,8 @@
  *                 This is the value negotiated with peer if any,
  *                 or the locally configured value.
  *
- * \note           With DTLS, \c mbedtls_ssl_write() will return an error if
- *                 called with a larger length value.
- *                 With TLS, \c mbedtls_ssl_write() will fragment the input if
- *                 necessary and return the number of bytes written; it is up
- *                 to the caller to call \c mbedtls_ssl_write() again in
- *                 order to send the remaining bytes if any.
+ * \sa             mbedtls_ssl_conf_max_frag_len()
+ * \sa             mbedtls_ssl_get_max_record_payload()
  *
  * \param ssl      SSL context
  *
@@ -2723,6 +2833,34 @@
 size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
+/**
+ * \brief          Return the current maximum outgoing record payload in bytes.
+ *                 This takes into account the config.h setting \c
+ *                 MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated
+ *                 max fragment length extension if used, and for DTLS the
+ *                 path MTU as configured and current record expansion.
+ *
+ * \note           With DTLS, \c mbedtls_ssl_write() will return an error if
+ *                 called with a larger length value.
+ *                 With TLS, \c mbedtls_ssl_write() will fragment the input if
+ *                 necessary and return the number of bytes written; it is up
+ *                 to the caller to call \c mbedtls_ssl_write() again in
+ *                 order to send the remaining bytes if any.
+ *
+ * \note           This function is not available (always returns an error)
+ *                 when record compression is enabled.
+ *
+ * \sa             mbedtls_ssl_set_mtu()
+ * \sa             mbedtls_ssl_get_max_frag_len()
+ * \sa             mbedtls_ssl_get_record_expansion()
+ *
+ * \param ssl      SSL context
+ *
+ * \return         Current maximum payload for an outgoing record,
+ *                 or a negative error code.
+ */
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl );
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
  * \brief          Return the peer certificate from the current connection
@@ -2776,35 +2914,50 @@
  *
  * \param ssl      SSL context
  *
- * \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.
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ *                 if the handshake is incomplete and waiting for data to
+ *                 be available for reading from or writing to the underlying
+ *                 transport - in this case you must call this function again
+ *                 when the underlying transport is ready for the operation.
+ * \return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ *                 operation is in progress (see
+ *                 mbedtls_ssl_conf_async_private_cb()) - in this case you
+ *                 must call this function again when the operation is ready.
+ * \return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ *                 in this case you must call this function again to complete
+ *                 the handshake when you're done attending other tasks.
+ * \return         #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
+ *                 and the client did not demonstrate reachability yet - in
+ *                 this case you must stop using the context (see below).
+ * \return         Another SSL error code - in this case you must stop using
+ *                 the context (see below).
  *
- *                 If this function returns MBEDTLS_ERR_SSL_WANT_READ, the
- *                 handshake is unfinished and no further data is available
- *                 from the underlying transport. In this case, you must call
- *                 the function again at some later stage.
+ * \warning        If this function returns something other than
+ *                 \c 0,
+ *                 #MBEDTLS_ERR_SSL_WANT_READ,
+ *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ *                 you must stop using the SSL context for reading or writing,
+ *                 and either free it or call \c mbedtls_ssl_session_reset()
+ *                 on it before re-using it for a new connection; the current
+ *                 connection must be closed.
+ *
+ * \note           If DTLS is in use, then you may choose to handle
+ *                 #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
+ *                 purposes, as it is an expected return value rather than an
+ *                 actual error, but you still need to reset/free the context.
  *
  * \note           Remarks regarding event-driven DTLS:
- *                 If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ *                 If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
  *                 from the underlying transport layer is currently being processed,
  *                 and it is safe to idle until the timer or the underlying transport
  *                 signal a new event. This is not true for a successful handshake,
  *                 in which case the datagram of the underlying transport that is
  *                 currently being processed might or might not contain further
  *                 DTLS records.
- *
- * \note           If this function returns something other than 0 or
- *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- *                 the SSL context for reading or writing, and either free it or
- *                 call \c mbedtls_ssl_session_reset() on it before re-using it
- *                 for a new connection; the current connection must be closed.
- *
- * \note           If DTLS is in use, then you may choose to handle
- *                 MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
- *                 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 );
 
@@ -2812,20 +2965,21 @@
  * \brief          Perform a single step of the SSL handshake
  *
  * \note           The state of the context (ssl->state) will be at
- *                 the next state after execution of this function. Do not
+ *                 the next state after this function returns \c 0. Do not
  *                 call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
  *
- * \note           If this function returns something other than 0 or
- *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- *                 the SSL context for reading or writing, and either free it or
- *                 call \c mbedtls_ssl_session_reset() on it before re-using it
- *                 for a new connection; the current connection must be closed.
- *
  * \param ssl      SSL context
  *
- * \return         0 if successful, or
- *                 MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
- *                 a specific SSL error code.
+ * \return         See mbedtls_ssl_handshake().
+ *
+ * \warning        If this function returns something other than \c 0,
+ *                 #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ *                 the SSL context for reading or writing, and either free it
+ *                 or call \c mbedtls_ssl_session_reset() on it before
+ *                 re-using it for a new connection; the current connection
+ *                 must be closed.
  */
 int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
 
@@ -2840,13 +2994,18 @@
  * \param ssl      SSL context
  *
  * \return         0 if successful, or any mbedtls_ssl_handshake() return
- *                 value.
+ *                 value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't
+ *                 happen during a renegotiation.
  *
- * \note           If this function returns something other than 0 or
- *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- *                 the SSL context for reading or writing, and either free it or
- *                 call \c mbedtls_ssl_session_reset() on it before re-using it
- *                 for a new connection; the current connection must be closed.
+ * \warning        If this function returns something other than \c 0,
+ *                 #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ *                 the SSL context for reading or writing, and either free it
+ *                 or call \c mbedtls_ssl_session_reset() on it before
+ *                 re-using it for a new connection; the current connection
+ *                 must be closed.
+ *
  */
 int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
@@ -2858,42 +3017,56 @@
  * \param buf      buffer that will hold the data
  * \param len      maximum number of bytes to read
  *
- * \return         One of the following:
- *                 - 0 if the read end of the underlying transport was closed,
- *                 - the (positive) number of bytes read, or
- *                 - a negative error code on failure.
+ * \return         The (positive) number of bytes read if successful.
+ * \return         \c 0 if the read end of the underlying transport was closed
+ *                 - in this case you must stop using the context (see below).
+ * \return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ *                 if the handshake is incomplete and waiting for data to
+ *                 be available for reading from or writing to the underlying
+ *                 transport - in this case you must call this function again
+ *                 when the underlying transport is ready for the operation.
+ * \return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ *                 operation is in progress (see
+ *                 mbedtls_ssl_conf_async_private_cb()) - in this case you
+ *                 must call this function again when the operation is ready.
+ * \return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ *                 in this case you must call this function again to complete
+ *                 the handshake when you're done attending other tasks.
+ * \return         #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
+ *                 side of a DTLS connection and the client is initiating a
+ *                 new connection using the same source port. See below.
+ * \return         Another SSL error code - in this case you must stop using
+ *                 the context (see below).
  *
- *                 If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data
- *                 is available from the underlying transport. In this case,
- *                 the function needs to be called again at some later stage.
+ * \warning        If this function returns something other than
+ *                 a positive value,
+ *                 #MBEDTLS_ERR_SSL_WANT_READ,
+ *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
+ *                 you must stop using the SSL context for reading or writing,
+ *                 and either free it or call \c mbedtls_ssl_session_reset()
+ *                 on it before re-using it for a new connection; the current
+ *                 connection must be closed.
  *
- *                 If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending
- *                 but the underlying transport isn't available for writing. In this
- *                 case, the function needs to be called again at some later stage.
- *
- *                 When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ * \note           When this function returns #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
+ *                 context (as it has been reset internally). Either way, you
+ *                 must 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!
  *
- * \note           If this function returns something other than a positive value
- *                 or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
- *                 you must stop using the SSL context for reading or writing,
- *                 and either free it or call \c mbedtls_ssl_session_reset() on it
- *                 before re-using it for a new connection; the current connection
- *                 must be closed.
- *
  * \note           Remarks regarding event-driven DTLS:
- *                 - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ *                 - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
  *                   from the underlying transport layer is currently being processed,
  *                   and it is safe to idle until the timer or the underlying transport
  *                   signal a new event.
@@ -2922,21 +3095,39 @@
  * \param buf      buffer holding the data
  * \param len      how many bytes must be written
  *
- * \return         the number of bytes actually written (may be less than len),
- *                 or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
- *                 or another negative error code.
+ * \return         The (non-negative) number of bytes actually written if
+ *                 successful (may be less than \p len).
+ * \return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ *                 if the handshake is incomplete and waiting for data to
+ *                 be available for reading from or writing to the underlying
+ *                 transport - in this case you must call this function again
+ *                 when the underlying transport is ready for the operation.
+ * \return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ *                 operation is in progress (see
+ *                 mbedtls_ssl_conf_async_private_cb()) - in this case you
+ *                 must call this function again when the operation is ready.
+ * \return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ *                 in this case you must call this function again to complete
+ *                 the handshake when you're done attending other tasks.
+ * \return         Another SSL error code - in this case you must stop using
+ *                 the context (see below).
  *
- * \note           If this function returns something other than 0, a positive
- *                 value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop
- *                 using the SSL context for reading or writing, and either
- *                 free it or call \c mbedtls_ssl_session_reset() on it before
- *                 re-using it for a new connection; the current connection
- *                 must be closed.
+ * \warning        If this function returns something other than
+ *                 a non-negative value,
+ *                 #MBEDTLS_ERR_SSL_WANT_READ,
+ *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ *                 you must stop using the SSL context for reading or writing,
+ *                 and either free it or call \c mbedtls_ssl_session_reset()
+ *                 on it before re-using it for a new connection; the current
+ *                 connection must be closed.
  *
- * \note           When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
+ * \note           When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ,
  *                 it must be called later with the *same* arguments,
  *                 until it returns a value greater that or equal to 0. When
- *                 the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be
+ *                 the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be
  *                 some partial data in the output buffer, however this is not
  *                 yet sent.
  *
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index d214703..97abb9f 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -93,6 +93,14 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
+/* Shorthand for restartable ECC */
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+    defined(MBEDTLS_SSL_CLI_C) && \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#define MBEDTLS_SSL__ECP_RESTARTABLE
+#endif
+
 #define MBEDTLS_SSL_INITIAL_HANDSHAKE           0
 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS   1   /* In progress */
 #define MBEDTLS_SSL_RENEGOTIATION_DONE          2   /* Done or aborted */
@@ -155,6 +163,9 @@
 #define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
                                       ( MBEDTLS_SSL_OUT_CONTENT_LEN ) )
 
+/* The maximum number of buffered handshake messages. */
+#define MBEDTLS_SSL_MAX_BUFFERED_HS 4
+
 /* Maximum length we can advertise as our max content length for
    RFC 6066 max_fragment_length extension negotiation purposes
    (the lesser of both sizes, if they are unequal.)
@@ -284,7 +295,18 @@
     mbedtls_x509_crl *sni_ca_crl;       /*!< trusted CAs CRLs from SNI      */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
-
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    int ecrs_enabled;                   /*!< Handshake supports EC restart? */
+    mbedtls_x509_crt_restart_ctx ecrs_ctx;  /*!< restart context            */
+    enum { /* this complements ssl->state with info on intra-state operations */
+        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
+        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
+        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
+        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
+        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
+    } ecrs_state;                       /*!< current (or last) operation    */
+    size_t ecrs_n;                      /*!< place for saving a length      */
+#endif
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
     unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
@@ -294,18 +316,45 @@
     unsigned char verify_cookie_len;    /*!<  Cli: cookie length
                                               Srv: flag for sending a cookie */
 
-    unsigned char *hs_msg;              /*!<  Reassembled handshake message  */
-
     uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
     unsigned char retransmit_state;     /*!<  Retransmission state           */
-    mbedtls_ssl_flight_item *flight;            /*!<  Current outgoing flight        */
-    mbedtls_ssl_flight_item *cur_msg;           /*!<  Current message in flight      */
+    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
+    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
+    unsigned char *cur_msg_p;           /*!<  Position in current message    */
     unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
                                               flight being received          */
     mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
                                               resending messages             */
     unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
                                               for resending messages         */
+
+    struct
+    {
+        size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
+                                      *   buffers used for message buffering. */
+
+        uint8_t seen_ccs;               /*!< Indicates if a CCS message has
+                                         *   been seen in the current flight. */
+
+        struct mbedtls_ssl_hs_buffer
+        {
+            unsigned is_valid      : 1;
+            unsigned is_fragmented : 1;
+            unsigned is_complete   : 1;
+            unsigned char *data;
+            size_t data_len;
+        } hs[MBEDTLS_SSL_MAX_BUFFERED_HS];
+
+        struct
+        {
+            unsigned char *data;
+            size_t len;
+            unsigned epoch;
+        } future_record;
+
+    } buffering;
+
+    uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
     /*
@@ -364,6 +413,8 @@
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 };
 
+typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
+
 /*
  * This structure contains a full set of runtime transform parameters
  * either in negotiation or active.
@@ -478,7 +529,6 @@
 void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
 
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
@@ -490,7 +540,10 @@
  *              of the logic of (D)TLS from the implementation
  *              of the secure transport.
  *
- * \param  ssl  SSL context to use
+ * \param  ssl              The SSL context to use.
+ * \param  update_hs_digest This indicates if the handshake digest
+ *                          should be automatically updated in case
+ *                          a handshake message is found.
  *
  * \return      0 or non-zero error code.
  *
@@ -556,10 +609,12 @@
  *              following the above definition.
  *
  */
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+                             unsigned update_hs_digest );
 int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
 
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush );
 int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
 
 int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
@@ -668,6 +723,7 @@
 void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
 #endif
 
 /* Visible for testing purposes only */
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index 5112ebb..75298bf 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -99,6 +99,17 @@
 #if defined(MBEDTLS_FS_IO)
 extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
 #endif
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+/* This mutex may or may not be used in the default definition of
+ * mbedtls_platform_gmtime_r(), but in order to determine that,
+ * we need to check POSIX features, hence modify _POSIX_C_SOURCE.
+ * With the current approach, this declaration is orphaned, lacking
+ * an accompanying definition, in case mbedtls_platform_gmtime_r()
+ * doesn't need it, but that's not a problem. */
+extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
 #endif /* MBEDTLS_THREADING_C */
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index eaf25d9..326b8bd 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  12
-#define MBEDTLS_VERSION_PATCH  0
+#define MBEDTLS_VERSION_MINOR  13
+#define MBEDTLS_VERSION_PATCH  1
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x020C0000
-#define MBEDTLS_VERSION_STRING         "2.12.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.12.0"
+#define MBEDTLS_VERSION_NUMBER         0x020D0100
+#define MBEDTLS_VERSION_STRING         "2.13.1"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.13.1"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index d41ec93..afeefca 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -143,6 +143,63 @@
 }
 mbedtls_x509write_cert;
 
+/**
+ * Item in a verification chain: cert and flags for it
+ */
+typedef struct {
+    mbedtls_x509_crt *crt;
+    uint32_t flags;
+} mbedtls_x509_crt_verify_chain_item;
+
+/**
+ * Max size of verification chain: end-entity + intermediates + trusted root
+ */
+#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE  ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
+
+/**
+ * Verification chain as built by \c mbedtls_crt_verify_chain()
+ */
+typedef struct
+{
+    mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
+    unsigned len;
+} mbedtls_x509_crt_verify_chain;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief       Context for resuming X.509 verify operations
+ */
+typedef struct
+{
+    /* for check_signature() */
+    mbedtls_pk_restart_ctx pk;
+
+    /* for find_parent_in() */
+    mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */
+    mbedtls_x509_crt *fallback_parent;
+    int fallback_signature_is_good;
+
+    /* for find_parent() */
+    int parent_is_trusted; /* -1 if find_parent is not in progress */
+
+    /* for verify_chain() */
+    enum {
+        x509_crt_rs_none,
+        x509_crt_rs_find_parent,
+    } in_progress;  /* none if no operation is in progress */
+    int self_cnt;
+    mbedtls_x509_crt_verify_chain ver_chain;
+
+} mbedtls_x509_crt_restart_ctx;
+
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_x509_crt_restart_ctx;
+
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
  * Default security profile. Should provide a good balance between security
@@ -353,6 +410,37 @@
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy );
 
+/**
+ * \brief          Restartable version of \c mbedtls_crt_verify_with_profile()
+ *
+ * \note           Performs the same job as \c mbedtls_crt_verify_with_profile()
+ *                 but can return early and restart according to the limit
+ *                 set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param crt      a certificate (chain) to be verified
+ * \param trust_ca the list of trusted CAs
+ * \param ca_crl   the list of CRLs for trusted CAs
+ * \param profile  security profile for verification
+ * \param cn       expected Common Name (can be set to
+ *                 NULL if the CN must not be verified)
+ * \param flags    result of the verification
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ * \param rs_ctx   restart context (NULL to disable restart)
+ *
+ * \return         See \c mbedtls_crt_verify_with_profile(), or
+ * \return         #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ *                 operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+                     mbedtls_x509_crt *trust_ca,
+                     mbedtls_x509_crl *ca_crl,
+                     const mbedtls_x509_crt_profile *profile,
+                     const char *cn, uint32_t *flags,
+                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy,
+                     mbedtls_x509_crt_restart_ctx *rs_ctx );
+
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
 /**
  * \brief          Check usage of certificate against keyUsage extension.
@@ -424,6 +512,18 @@
  * \param crt      Certificate chain to free
  */
 void mbedtls_x509_crt_free( mbedtls_x509_crt *crt );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief           Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx );
+
+/**
+ * \brief           Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 /* \} name */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 5115b96..275eda3 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -159,15 +159,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.12.0 SOVERSION 3)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.13.1 SOVERSION 3)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.12.0 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.13.1 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.12.0 SOVERSION 11)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.13.1 SOVERSION 12)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/Makefile b/library/Makefile
index ac88d4c..430c598 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -35,7 +35,7 @@
 endif
 endif
 
-SOEXT_TLS=so.11
+SOEXT_TLS=so.12
 SOEXT_X509=so.0
 SOEXT_CRYPTO=so.3
 
diff --git a/library/ecdh.c b/library/ecdh.c
index 61380b6..80e9676 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -40,13 +40,41 @@
 
 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
 /*
- * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
+ * Generate public key (restartable version)
+ *
+ * Note: this internal function relies on its caller preserving the value of
+ * the output parameter 'd' across continuation calls. This would not be
+ * acceptable for a public function but is OK here as we control call sites.
+ */
+static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
+                    mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                    int (*f_rng)(void *, unsigned char *, size_t),
+                    void *p_rng,
+                    mbedtls_ecp_restart_ctx *rs_ctx )
+{
+    int ret;
+
+    /* If multiplication is in progress, we already generated a privkey */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
+                                                  f_rng, p_rng, rs_ctx ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Generate public key
  */
 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
-    return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
+    return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
 }
 #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
 
@@ -54,22 +82,20 @@
 /*
  * Compute shared secret (SEC1 3.3.1)
  */
-int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
+                         mbedtls_mpi *z,
                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
                          int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng )
+                         void *p_rng,
+                         mbedtls_ecp_restart_ctx *rs_ctx )
 {
     int ret;
     mbedtls_ecp_point P;
 
     mbedtls_ecp_point_init( &P );
 
-    /*
-     * Make sure Q is a valid pubkey before using it
-     */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
+                                                  f_rng, p_rng, rs_ctx ) );
 
     if( mbedtls_ecp_is_zero( &P ) )
     {
@@ -87,11 +113,36 @@
 #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
 
 /*
+ * Compute shared secret (SEC1 3.3.1)
+ */
+int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+                         const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
+{
+    return( ecdh_compute_shared_restartable( grp, z, Q, d,
+                                             f_rng, p_rng, NULL ) );
+}
+
+/*
  * Initialize context
  */
 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
 {
-    memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
+    mbedtls_ecp_group_init( &ctx->grp );
+    mbedtls_mpi_init( &ctx->d  );
+    mbedtls_ecp_point_init( &ctx->Q   );
+    mbedtls_ecp_point_init( &ctx->Qp  );
+    mbedtls_mpi_init( &ctx->z  );
+    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+    mbedtls_ecp_point_init( &ctx->Vi  );
+    mbedtls_ecp_point_init( &ctx->Vf  );
+    mbedtls_mpi_init( &ctx->_d );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    ctx->restart_enabled = 0;
+    mbedtls_ecp_restart_init( &ctx->rs );
+#endif
 }
 
 /*
@@ -103,15 +154,29 @@
         return;
 
     mbedtls_ecp_group_free( &ctx->grp );
+    mbedtls_mpi_free( &ctx->d  );
     mbedtls_ecp_point_free( &ctx->Q   );
     mbedtls_ecp_point_free( &ctx->Qp  );
+    mbedtls_mpi_free( &ctx->z  );
     mbedtls_ecp_point_free( &ctx->Vi  );
     mbedtls_ecp_point_free( &ctx->Vf  );
-    mbedtls_mpi_free( &ctx->d  );
-    mbedtls_mpi_free( &ctx->z  );
     mbedtls_mpi_free( &ctx->_d );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_ecp_restart_free( &ctx->rs );
+#endif
 }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Enable restartable operations for context
+ */
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
+{
+    ctx->restart_enabled = 1;
+}
+#endif
+
 /*
  * Setup and write the ServerKeyExhange parameters (RFC 4492)
  *      struct {
@@ -126,12 +191,18 @@
 {
     int ret;
     size_t grp_len, pt_len;
+    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 
     if( ctx == NULL || ctx->grp.pbits == 0 )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
-    if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
-                != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( ctx->restart_enabled )
+        rs_ctx = &ctx->rs;
+#endif
+
+    if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+                                             f_rng, p_rng, rs_ctx ) ) != 0 )
         return( ret );
 
     if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
@@ -142,7 +213,7 @@
     blen -= grp_len;
 
     if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
-                                     &pt_len, buf, blen ) ) != 0 )
+                                             &pt_len, buf, blen ) ) != 0 )
         return( ret );
 
     *olen = grp_len + pt_len;
@@ -206,12 +277,18 @@
                       void *p_rng )
 {
     int ret;
+    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 
     if( ctx == NULL || ctx->grp.pbits == 0 )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
-    if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
-                != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( ctx->restart_enabled )
+        rs_ctx = &ctx->rs;
+#endif
+
+    if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+                    f_rng, p_rng, rs_ctx ) ) != 0 )
         return( ret );
 
     return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
@@ -248,12 +325,18 @@
                       void *p_rng )
 {
     int ret;
+    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 
-    if( ctx == NULL )
+    if( ctx == NULL || ctx->grp.pbits == 0 )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
-    if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
-                                     f_rng, p_rng ) ) != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( ctx->restart_enabled )
+        rs_ctx = &ctx->rs;
+#endif
+
+    if( ( ret = ecdh_compute_shared_restartable( &ctx->grp,
+                    &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 )
     {
         return( ret );
     }
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 17a88bd..abac015 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -42,6 +42,178 @@
 #include "mbedtls/hmac_drbg.h"
 #endif
 
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/*
+ * Sub-context for ecdsa_verify()
+ */
+struct mbedtls_ecdsa_restart_ver
+{
+    mbedtls_mpi u1, u2;     /* intermediate values  */
+    enum {                  /* what to do next?     */
+        ecdsa_ver_init = 0, /* getting started      */
+        ecdsa_ver_muladd,   /* muladd step          */
+    } state;
+};
+
+/*
+ * Init verify restart sub-context
+ */
+static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+    mbedtls_mpi_init( &ctx->u1 );
+    mbedtls_mpi_init( &ctx->u2 );
+    ctx->state = ecdsa_ver_init;
+}
+
+/*
+ * Free the components of a verify restart sub-context
+ */
+static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_mpi_free( &ctx->u1 );
+    mbedtls_mpi_free( &ctx->u2 );
+
+    ecdsa_restart_ver_init( ctx );
+}
+
+/*
+ * Sub-context for ecdsa_sign()
+ */
+struct mbedtls_ecdsa_restart_sig
+{
+    int sign_tries;
+    int key_tries;
+    mbedtls_mpi k;          /* per-signature random */
+    mbedtls_mpi r;          /* r value              */
+    enum {                  /* what to do next?     */
+        ecdsa_sig_init = 0, /* getting started      */
+        ecdsa_sig_mul,      /* doing ecp_mul()      */
+        ecdsa_sig_modn,     /* mod N computations   */
+    } state;
+};
+
+/*
+ * Init verify sign sub-context
+ */
+static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+    ctx->sign_tries = 0;
+    ctx->key_tries = 0;
+    mbedtls_mpi_init( &ctx->k );
+    mbedtls_mpi_init( &ctx->r );
+    ctx->state = ecdsa_sig_init;
+}
+
+/*
+ * Free the components of a sign restart sub-context
+ */
+static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_mpi_free( &ctx->k );
+    mbedtls_mpi_free( &ctx->r );
+}
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/*
+ * Sub-context for ecdsa_sign_det()
+ */
+struct mbedtls_ecdsa_restart_det
+{
+    mbedtls_hmac_drbg_context rng_ctx;  /* DRBG state   */
+    enum {                      /* what to do next?     */
+        ecdsa_det_init = 0,     /* getting started      */
+        ecdsa_det_sign,         /* make signature       */
+    } state;
+};
+
+/*
+ * Init verify sign_det sub-context
+ */
+static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+    mbedtls_hmac_drbg_init( &ctx->rng_ctx );
+    ctx->state = ecdsa_det_init;
+}
+
+/*
+ * Free the components of a sign_det restart sub-context
+ */
+static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_hmac_drbg_free( &ctx->rng_ctx );
+
+    ecdsa_restart_det_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#define ECDSA_RS_ECP    &rs_ctx->ecp
+
+/* Utility macro for checking and updating ops budget */
+#define ECDSA_BUDGET( ops )   \
+    MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECDSA_RS_ENTER( SUB )   do {                                 \
+    /* reset ops count for this call if top-level */                 \
+    if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 )                 \
+        rs_ctx->ecp.ops_done = 0;                                    \
+                                                                     \
+    /* set up our own sub-context if needed */                       \
+    if( mbedtls_ecp_restart_is_enabled() &&                          \
+        rs_ctx != NULL && rs_ctx->SUB == NULL )                      \
+    {                                                                \
+        rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) );   \
+        if( rs_ctx->SUB == NULL )                                    \
+            return( MBEDTLS_ERR_ECP_ALLOC_FAILED );                  \
+                                                                     \
+        ecdsa_restart_## SUB ##_init( rs_ctx->SUB );                 \
+    }                                                                \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECDSA_RS_LEAVE( SUB )   do {                                 \
+    /* clear our sub-context when not in progress (done or error) */ \
+    if( rs_ctx != NULL && rs_ctx->SUB != NULL &&                     \
+        ret != MBEDTLS_ERR_ECP_IN_PROGRESS )                         \
+    {                                                                \
+        ecdsa_restart_## SUB ##_free( rs_ctx->SUB );                 \
+        mbedtls_free( rs_ctx->SUB );                                 \
+        rs_ctx->SUB = NULL;                                          \
+    }                                                                \
+                                                                     \
+    if( rs_ctx != NULL )                                             \
+        rs_ctx->ecp.depth--;                                         \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECDSA_RS_ECP    NULL
+
+#define ECDSA_BUDGET( ops )   /* no-op; for compatibility */
+
+#define ECDSA_RS_ENTER( SUB )   (void) rs_ctx
+#define ECDSA_RS_LEAVE( SUB )   (void) rs_ctx
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 /*
  * Derive a suitable integer for group grp from a buffer of length len
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -70,13 +242,17 @@
  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
  */
-int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
+                mbedtls_mpi *r, mbedtls_mpi *s,
                 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
-    int ret, key_tries, sign_tries, blind_tries;
+    int ret, key_tries, sign_tries;
+    int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
     mbedtls_ecp_point R;
     mbedtls_mpi k, e, t;
+    mbedtls_mpi *pk = &k, *pr = r;
 
     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
     if( grp->N.p == NULL )
@@ -89,26 +265,72 @@
     mbedtls_ecp_point_init( &R );
     mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
 
-    sign_tries = 0;
+    ECDSA_RS_ENTER( sig );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->sig != NULL )
+    {
+        /* redirect to our context */
+        p_sign_tries = &rs_ctx->sig->sign_tries;
+        p_key_tries = &rs_ctx->sig->key_tries;
+        pk = &rs_ctx->sig->k;
+        pr = &rs_ctx->sig->r;
+
+        /* jump to current step */
+        if( rs_ctx->sig->state == ecdsa_sig_mul )
+            goto mul;
+        if( rs_ctx->sig->state == ecdsa_sig_modn )
+            goto modn;
+    }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+    *p_sign_tries = 0;
     do
     {
+        if( *p_sign_tries++ > 10 )
+        {
+            ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
+            goto cleanup;
+        }
+
         /*
          * Steps 1-3: generate a suitable ephemeral keypair
          * and set r = xR mod n
          */
-        key_tries = 0;
+        *p_key_tries = 0;
         do
         {
-            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
-
-            if( key_tries++ > 10 )
+            if( *p_key_tries++ > 10 )
             {
                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
                 goto cleanup;
             }
+
+            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+            if( rs_ctx != NULL && rs_ctx->sig != NULL )
+                rs_ctx->sig->state = ecdsa_sig_mul;
+
+mul:
+#endif
+            MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
+                                                  f_rng, p_rng, ECDSA_RS_ECP ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
         }
-        while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
+        while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+        if( rs_ctx != NULL && rs_ctx->sig != NULL )
+            rs_ctx->sig->state = ecdsa_sig_modn;
+
+modn:
+#endif
+        /*
+         * Accounting for everything up to the end of the loop
+         * (step 6, but checking now avoids saving e and t)
+         */
+        ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
 
         /*
          * Step 5: derive MPI from hashed message
@@ -119,57 +341,60 @@
          * Generate a random value to blind inv_mod in next step,
          * avoiding a potential timing leak.
          */
-        blind_tries = 0;
-        do
-        {
-            size_t n_size = ( grp->nbits + 7 ) / 8;
-            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
-
-            /* See mbedtls_ecp_gen_keypair() */
-            if( ++blind_tries > 30 )
-                return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
-        }
-        while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
-               mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
 
         /*
          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
-
-        if( sign_tries++ > 10 )
-        {
-            ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-            goto cleanup;
-        }
     }
     while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->sig != NULL )
+        mbedtls_mpi_copy( r, pr );
+#endif
+
 cleanup:
     mbedtls_ecp_point_free( &R );
     mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
 
+    ECDSA_RS_LEAVE( sig );
+
     return( ret );
 }
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 
+/*
+ * Compute ECDSA signature of a hashed message
+ */
+int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+                                    f_rng, p_rng, NULL ) );
+}
+
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
 /*
  * Deterministic signature wrapper
  */
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
+                    mbedtls_mpi *r, mbedtls_mpi *s,
                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                    mbedtls_md_type_t md_alg )
+                    mbedtls_md_type_t md_alg,
+                    mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
     int ret;
     mbedtls_hmac_drbg_context rng_ctx;
+    mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
     size_t grp_len = ( grp->nbits + 7 ) / 8;
     const mbedtls_md_info_t *md_info;
@@ -181,21 +406,53 @@
     mbedtls_mpi_init( &h );
     mbedtls_hmac_drbg_init( &rng_ctx );
 
+    ECDSA_RS_ENTER( det );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->det != NULL )
+    {
+        /* redirect to our context */
+        p_rng = &rs_ctx->det->rng_ctx;
+
+        /* jump to current step */
+        if( rs_ctx->det->state == ecdsa_det_sign )
+            goto sign;
+    }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
     MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
-    mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
+    mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
 
-    ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
-                      mbedtls_hmac_drbg_random, &rng_ctx );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->det != NULL )
+        rs_ctx->det->state = ecdsa_det_sign;
+
+sign:
+#endif
+    ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+                      mbedtls_hmac_drbg_random, p_rng, rs_ctx );
 
 cleanup:
     mbedtls_hmac_drbg_free( &rng_ctx );
     mbedtls_mpi_free( &h );
 
+    ECDSA_RS_LEAVE( det );
+
     return( ret );
 }
+
+/*
+ * Deterministic signature wrapper
+ */
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                    mbedtls_md_type_t md_alg )
+{
+    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
+}
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
 #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
@@ -203,21 +460,40 @@
  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
  */
-int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
-                  const unsigned char *buf, size_t blen,
-                  const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
+static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
+                                     const unsigned char *buf, size_t blen,
+                                     const mbedtls_ecp_point *Q,
+                                     const mbedtls_mpi *r, const mbedtls_mpi *s,
+                                     mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
     int ret;
     mbedtls_mpi e, s_inv, u1, u2;
     mbedtls_ecp_point R;
+    mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
 
     mbedtls_ecp_point_init( &R );
-    mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
+    mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
+    mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
 
     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
     if( grp->N.p == NULL )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
+    ECDSA_RS_ENTER( ver );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ver != NULL )
+    {
+        /* redirect to our context */
+        pu1 = &rs_ctx->ver->u1;
+        pu2 = &rs_ctx->ver->u2;
+
+        /* jump to current step */
+        if( rs_ctx->ver->state == ecdsa_ver_muladd )
+            goto muladd;
+    }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
     /*
      * Step 1: make sure r and s are in range 1..n-1
      */
@@ -229,11 +505,6 @@
     }
 
     /*
-     * Additional precaution: make sure Q is valid
-     */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
-    /*
      * Step 3: derive MPI from hashed message
      */
     MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
@@ -241,21 +512,27 @@
     /*
      * Step 4: u1 = e / s mod n, u2 = r / s mod n
      */
+    ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
+
     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ver != NULL )
+        rs_ctx->ver->state = ecdsa_ver_muladd;
+
+muladd:
+#endif
     /*
      * Step 5: R = u1 G + u2 Q
-     *
-     * Since we're not using any secret data, no need to pass a RNG to
-     * mbedtls_ecp_mul() for countermesures.
      */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
+                     &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
 
     if( mbedtls_ecp_is_zero( &R ) )
     {
@@ -280,13 +557,26 @@
 
 cleanup:
     mbedtls_ecp_point_free( &R );
-    mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+    mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
+    mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+
+    ECDSA_RS_LEAVE( ver );
 
     return( ret );
 }
 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
 
 /*
+ * Verify ECDSA signature of hashed message
+ */
+int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
+                  const unsigned char *buf, size_t blen,
+                  const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
+{
+    return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
+}
+
+/*
  * Convert a signature (given by context) to ASN.1
  */
 static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
@@ -313,11 +603,13 @@
 /*
  * Compute and write signature
  */
-int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+                           mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hlen,
                            unsigned char *sig, size_t *slen,
                            int (*f_rng)(void *, unsigned char *, size_t),
-                           void *p_rng )
+                           void *p_rng,
+                           mbedtls_ecdsa_restart_ctx *rs_ctx )
 {
     int ret;
     mbedtls_mpi r, s;
@@ -329,13 +621,13 @@
     (void) f_rng;
     (void) p_rng;
 
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
-                             hash, hlen, md_alg ) );
+    MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
+                             hash, hlen, md_alg, rs_ctx ) );
 #else
     (void) md_alg;
 
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
-                         hash, hlen, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
+                         hash, hlen, f_rng, p_rng, rs_ctx ) );
 #endif
 
     MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
@@ -347,6 +639,19 @@
     return( ret );
 }
 
+/*
+ * Compute and write signature
+ */
+int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hlen,
+                           unsigned char *sig, size_t *slen,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng )
+{
+    return( mbedtls_ecdsa_write_signature_restartable(
+                ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
+}
+
 #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
     defined(MBEDTLS_ECDSA_DETERMINISTIC)
 int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
@@ -366,6 +671,18 @@
                           const unsigned char *hash, size_t hlen,
                           const unsigned char *sig, size_t slen )
 {
+    return( mbedtls_ecdsa_read_signature_restartable(
+                ctx, hash, hlen, sig, slen, NULL ) );
+}
+
+/*
+ * Restartable read and check signature
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+                          const unsigned char *hash, size_t hlen,
+                          const unsigned char *sig, size_t slen,
+                          mbedtls_ecdsa_restart_ctx *rs_ctx )
+{
     int ret;
     unsigned char *p = (unsigned char *) sig;
     const unsigned char *end = sig + slen;
@@ -396,8 +713,8 @@
         goto cleanup;
     }
 
-    if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
-                              &ctx->Q, &r, &s ) ) != 0 )
+    if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
+                              &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
         goto cleanup;
 
     /* At this point we know that the buffer starts with a valid signature.
@@ -458,4 +775,42 @@
     mbedtls_ecp_keypair_free( ctx );
 }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
+{
+    mbedtls_ecp_restart_init( &ctx->ecp );
+
+    ctx->ver = NULL;
+    ctx->sig = NULL;
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+    ctx->det = NULL;
+#endif
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
+{
+    mbedtls_ecp_restart_free( &ctx->ecp );
+
+    ecdsa_restart_ver_free( ctx->ver );
+    mbedtls_free( ctx->ver );
+    ctx->ver = NULL;
+
+    ecdsa_restart_sig_free( ctx->sig );
+    mbedtls_free( ctx->sig );
+    ctx->sig = NULL;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+    ecdsa_restart_det_free( ctx->det );
+    mbedtls_free( ctx->det );
+    ctx->det = NULL;
+#endif
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 #endif /* MBEDTLS_ECDSA_C */
diff --git a/library/ecp.c b/library/ecp.c
index 68c6f49..de5725c 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -82,6 +82,230 @@
 static unsigned long add_count, dbl_count, mul_count;
 #endif
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Maximum number of "basic operations" to be done in a row.
+ *
+ * Default value 0 means that ECC operations will not yield.
+ * Note that regardless of the value of ecp_max_ops, always at
+ * least one step is performed before yielding.
+ *
+ * Setting ecp_max_ops=1 can be suitable for testing purposes
+ * as it will interrupt computation at all possible points.
+ */
+static unsigned ecp_max_ops = 0;
+
+/*
+ * Set ecp_max_ops
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops )
+{
+    ecp_max_ops = max_ops;
+}
+
+/*
+ * Check if restart is enabled
+ */
+int mbedtls_ecp_restart_is_enabled( void )
+{
+    return( ecp_max_ops != 0 );
+}
+
+/*
+ * Restart sub-context for ecp_mul_comb()
+ */
+struct mbedtls_ecp_restart_mul
+{
+    mbedtls_ecp_point R;    /* current intermediate result                  */
+    size_t i;               /* current index in various loops, 0 outside    */
+    mbedtls_ecp_point *T;   /* table for precomputed points                 */
+    unsigned char T_size;   /* number of points in table T                  */
+    enum {                  /* what were we doing last time we returned?    */
+        ecp_rsm_init = 0,       /* nothing so far, dummy initial state      */
+        ecp_rsm_pre_dbl,        /* precompute 2^n multiples                 */
+        ecp_rsm_pre_norm_dbl,   /* normalize precomputed 2^n multiples      */
+        ecp_rsm_pre_add,        /* precompute remaining points by adding    */
+        ecp_rsm_pre_norm_add,   /* normalize all precomputed points         */
+        ecp_rsm_comb_core,      /* ecp_mul_comb_core()                      */
+        ecp_rsm_final_norm,     /* do the final normalization               */
+    } state;
+};
+
+/*
+ * Init restart_mul sub-context
+ */
+static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+    mbedtls_ecp_point_init( &ctx->R );
+    ctx->i = 0;
+    ctx->T = NULL;
+    ctx->T_size = 0;
+    ctx->state = ecp_rsm_init;
+}
+
+/*
+ * Free the components of a restart_mul sub-context
+ */
+static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+    unsigned char i;
+
+    if( ctx == NULL )
+        return;
+
+    mbedtls_ecp_point_free( &ctx->R );
+
+    if( ctx->T != NULL )
+    {
+        for( i = 0; i < ctx->T_size; i++ )
+            mbedtls_ecp_point_free( ctx->T + i );
+        mbedtls_free( ctx->T );
+    }
+
+    ecp_restart_rsm_init( ctx );
+}
+
+/*
+ * Restart context for ecp_muladd()
+ */
+struct mbedtls_ecp_restart_muladd
+{
+    mbedtls_ecp_point mP;       /* mP value                             */
+    mbedtls_ecp_point R;        /* R intermediate result                */
+    enum {                      /* what should we do next?              */
+        ecp_rsma_mul1 = 0,      /* first multiplication                 */
+        ecp_rsma_mul2,          /* second multiplication                */
+        ecp_rsma_add,           /* addition                             */
+        ecp_rsma_norm,          /* normalization                        */
+    } state;
+};
+
+/*
+ * Init restart_muladd sub-context
+ */
+static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+    mbedtls_ecp_point_init( &ctx->mP );
+    mbedtls_ecp_point_init( &ctx->R );
+    ctx->state = ecp_rsma_mul1;
+}
+
+/*
+ * Free the components of a restart_muladd sub-context
+ */
+static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_ecp_point_free( &ctx->mP );
+    mbedtls_ecp_point_free( &ctx->R );
+
+    ecp_restart_ma_init( ctx );
+}
+
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
+{
+    ctx->ops_done = 0;
+    ctx->depth = 0;
+    ctx->rsm = NULL;
+    ctx->ma = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    ecp_restart_rsm_free( ctx->rsm );
+    mbedtls_free( ctx->rsm );
+
+    ecp_restart_ma_free( ctx->ma );
+    mbedtls_free( ctx->ma );
+
+    mbedtls_ecp_restart_init( ctx );
+}
+
+/*
+ * Check if we can do the next step
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+                              mbedtls_ecp_restart_ctx *rs_ctx,
+                              unsigned ops )
+{
+    if( rs_ctx != NULL && ecp_max_ops != 0 )
+    {
+        /* scale depending on curve size: the chosen reference is 256-bit,
+         * and multiplication is quadratic. Round to the closest integer. */
+        if( grp->pbits >= 512 )
+            ops *= 4;
+        else if( grp->pbits >= 384 )
+            ops *= 2;
+
+        /* Avoid infinite loops: always allow first step.
+         * Because of that, however, it's not generally true
+         * that ops_done <= ecp_max_ops, so the check
+         * ops_done > ecp_max_ops below is mandatory. */
+        if( ( rs_ctx->ops_done != 0 ) &&
+            ( rs_ctx->ops_done > ecp_max_ops ||
+              ops > ecp_max_ops - rs_ctx->ops_done ) )
+        {
+            return( MBEDTLS_ERR_ECP_IN_PROGRESS );
+        }
+
+        /* update running count */
+        rs_ctx->ops_done += ops;
+    }
+
+    return( 0 );
+}
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECP_RS_ENTER( SUB )   do {                                      \
+    /* reset ops count for this call if top-level */                    \
+    if( rs_ctx != NULL && rs_ctx->depth++ == 0 )                        \
+        rs_ctx->ops_done = 0;                                           \
+                                                                        \
+    /* set up our own sub-context if needed */                          \
+    if( mbedtls_ecp_restart_is_enabled() &&                             \
+        rs_ctx != NULL && rs_ctx->SUB == NULL )                         \
+    {                                                                   \
+        rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) );      \
+        if( rs_ctx->SUB == NULL )                                       \
+            return( MBEDTLS_ERR_ECP_ALLOC_FAILED );                     \
+                                                                        \
+        ecp_restart_## SUB ##_init( rs_ctx->SUB );                      \
+    }                                                                   \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECP_RS_LEAVE( SUB )   do {                                      \
+    /* clear our sub-context when not in progress (done or error) */    \
+    if( rs_ctx != NULL && rs_ctx->SUB != NULL &&                        \
+        ret != MBEDTLS_ERR_ECP_IN_PROGRESS )                            \
+    {                                                                   \
+        ecp_restart_## SUB ##_free( rs_ctx->SUB );                      \
+        mbedtls_free( rs_ctx->SUB );                                    \
+        rs_ctx->SUB = NULL;                                             \
+    }                                                                   \
+                                                                        \
+    if( rs_ctx != NULL )                                                \
+        rs_ctx->depth--;                                                \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECP_RS_ENTER( sub )     (void) rs_ctx;
+#define ECP_RS_LEAVE( sub )     (void) rs_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
@@ -289,7 +513,21 @@
     if( grp == NULL )
         return;
 
-    memset( grp, 0, sizeof( mbedtls_ecp_group ) );
+    grp->id = MBEDTLS_ECP_DP_NONE;
+    mbedtls_mpi_init( &grp->P );
+    mbedtls_mpi_init( &grp->A );
+    mbedtls_mpi_init( &grp->B );
+    mbedtls_ecp_point_init( &grp->G );
+    mbedtls_mpi_init( &grp->N );
+    grp->pbits = 0;
+    grp->nbits = 0;
+    grp->h = 0;
+    grp->modp = NULL;
+    grp->t_pre = NULL;
+    grp->t_post = NULL;
+    grp->t_data = NULL;
+    grp->T = NULL;
+    grp->T_size = 0;
 }
 
 /*
@@ -752,11 +990,10 @@
         return( 0 );
 
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_normalize_jac( grp, pt );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
 #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
+
     mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
 
     /*
@@ -796,32 +1033,33 @@
  * Cost: 1N(t) := 1I + (6t - 3)M + 1S
  */
 static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
-                                   mbedtls_ecp_point *T[], size_t t_len )
+                                   mbedtls_ecp_point *T[], size_t T_size )
 {
     int ret;
     size_t i;
     mbedtls_mpi *c, u, Zi, ZZi;
 
-    if( t_len < 2 )
+    if( T_size < 2 )
         return( ecp_normalize_jac( grp, *T ) );
 
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
 #endif
 
-    if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
+    if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
         return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
 
+    for( i = 0; i < T_size; i++ )
+        mbedtls_mpi_init( &c[i] );
+
     mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
 
     /*
      * c[i] = Z_0 * ... * Z_i
      */
     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
-    for( i = 1; i < t_len; i++ )
+    for( i = 1; i < T_size; i++ )
     {
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
         MOD_MUL( c[i] );
@@ -830,9 +1068,9 @@
     /*
      * u = 1 / (Z_0 * ... * Z_n) mod P
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
 
-    for( i = t_len - 1; ; i-- )
+    for( i = T_size - 1; ; i-- )
     {
         /*
          * Zi = 1 / Z_i mod p
@@ -872,7 +1110,7 @@
 cleanup:
 
     mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
-    for( i = 0; i < t_len; i++ )
+    for( i = 0; i < T_size; i++ )
         mbedtls_mpi_free( &c[i] );
     mbedtls_free( c );
 
@@ -929,10 +1167,8 @@
 #endif
 
 #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_double_jac( grp, R, P );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
 #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
 
     mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
@@ -1027,10 +1263,8 @@
 #endif
 
 #if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
 #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
 
     /*
@@ -1114,10 +1348,8 @@
     int count = 0;
 
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
 #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
 
     p_size = ( grp->pbits + 7 ) / 8;
@@ -1173,11 +1405,38 @@
  * modified version that provides resistance to SPA by avoiding zero
  * digits in the representation as in [3]. We modify the method further by
  * requiring that all K_i be odd, which has the small cost that our
- * representation uses one more K_i, due to carries.
+ * representation uses one more K_i, due to carries, but saves on the size of
+ * the precomputed table.
  *
- * Also, for the sake of compactness, only the seven low-order bits of x[i]
- * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
- * the paper): it is set if and only if if s_i == -1;
+ * Summary of the comb method and its modifications:
+ *
+ * - The goal is to compute m*P for some w*d-bit integer m.
+ *
+ * - The basic comb method splits m into the w-bit integers
+ *   x[0] .. x[d-1] where x[i] consists of the bits in m whose
+ *   index has residue i modulo d, and computes m * P as
+ *   S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
+ *   S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
+ *
+ * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
+ *    .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] ..,
+ *   thereby successively converting it into a form where all summands
+ *   are nonzero, at the cost of negative summands. This is the basic idea of [3].
+ *
+ * - More generally, even if x[i+1] != 0, we can first transform the sum as
+ *   .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
+ *   and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
+ *   Performing and iterating this procedure for those x[i] that are even
+ *   (keeping track of carry), we can transform the original sum into one of the form
+ *   S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
+ *   with all x'[i] odd. It is therefore only necessary to know S at odd indices,
+ *   which is why we are only computing half of it in the first place in
+ *   ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
+ *
+ * - For the sake of compactness, only the seven low-order bits of x[i]
+ *   are used to represent its absolute value (K_i in the paper), and the msb
+ *   of x[i] encodes the sign (s_i in the paper): it is set if and only if
+ *   if s_i == -1;
  *
  * Calling conventions:
  * - x is an array of size d + 1
@@ -1186,8 +1445,8 @@
  * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
  *   (the result will be incorrect if these assumptions are not satisfied)
  */
-static void ecp_comb_fixed( unsigned char x[], size_t d,
-                            unsigned char w, const mbedtls_mpi *m )
+static void ecp_comb_recode_core( unsigned char x[], size_t d,
+                                  unsigned char w, const mbedtls_mpi *m )
 {
     size_t i, j;
     unsigned char c, cc, adjust;
@@ -1217,70 +1476,178 @@
 }
 
 /*
- * Precompute points for the comb method
+ * Precompute points for the adapted comb method
  *
- * If i = i_{w-1} ... i_1 is the binary representation of i, then
- * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ * Assumption: T must be able to hold 2^{w - 1} elements.
  *
- * T must be able to hold 2^{w - 1} elements
+ * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
+ *            sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P.
  *
  * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
+ *
+ * Note: Even comb values (those where P would be omitted from the
+ *       sum defining T[i] above) are not needed in our adaption
+ *       the comb method. See ecp_comb_recode_core().
+ *
+ * This function currently works in four steps:
+ * (1) [dbl]      Computation of intermediate T[i] for 2-power values of i
+ * (2) [norm_dbl] Normalization of coordinates of these T[i]
+ * (3) [add]      Computation of all T[i]
+ * (4) [norm_add] Normalization of all T[i]
+ *
+ * Step 1 can be interrupted but not the others; together with the final
+ * coordinate normalization they are the largest steps done at once, depending
+ * on the window size. Here are operation counts for P-256:
+ *
+ * step     (2)     (3)     (4)
+ * w = 5    142     165     208
+ * w = 4    136      77     160
+ * w = 3    130      33     136
+ * w = 2    124      11     124
+ *
+ * So if ECC operations are blocking for too long even with a low max_ops
+ * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
+ * to minimize maximum blocking time.
  */
 static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
                                 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
-                                unsigned char w, size_t d )
+                                unsigned char w, size_t d,
+                                mbedtls_ecp_restart_ctx *rs_ctx )
 {
     int ret;
-    unsigned char i, k;
-    size_t j;
+    unsigned char i;
+    size_t j = 0;
+    const unsigned char T_size = 1U << ( w - 1 );
     mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    {
+        if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+            goto dbl;
+        if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
+            goto norm_dbl;
+        if( rs_ctx->rsm->state == ecp_rsm_pre_add )
+            goto add;
+        if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
+            goto norm_add;
+    }
+#else
+    (void) rs_ctx;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    {
+        rs_ctx->rsm->state = ecp_rsm_pre_dbl;
+
+        /* initial state for the loop */
+        rs_ctx->rsm->i = 0;
+    }
+
+dbl:
+#endif
     /*
      * Set T[0] = P and
      * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
      */
     MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
 
-    k = 0;
-    for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
-    {
-        cur = T + i;
-        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
-        for( j = 0; j < d; j++ )
-            MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+        j = rs_ctx->rsm->i;
+    else
+#endif
+        j = 0;
 
-        TT[k++] = cur;
+    for( ; j < d * ( w - 1 ); j++ )
+    {
+        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
+
+        i = 1U << ( j / d );
+        cur = T + i;
+
+        if( j % d == 0 )
+            MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
+
+        MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
     }
 
-    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+        rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
 
+norm_dbl:
+#endif
+    /*
+     * Normalize current elements in T. As T has holes,
+     * use an auxiliary array of pointers to elements in T.
+     */
+    j = 0;
+    for( i = 1; i < T_size; i <<= 1 )
+        TT[j++] = T + i;
+
+    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+        rs_ctx->rsm->state = ecp_rsm_pre_add;
+
+add:
+#endif
     /*
      * Compute the remaining ones using the minimal number of additions
      * Be careful to update T[2^l] only after using it!
      */
-    k = 0;
-    for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+    MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
+
+    for( i = 1; i < T_size; i <<= 1 )
     {
         j = i;
         while( j-- )
-        {
             MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
-            TT[k++] = &T[i + j];
-        }
     }
 
-    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+        rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
+
+norm_add:
+#endif
+    /*
+     * Normalize final elements in T. Even though there are no holes now, we
+     * still need the auxiliary array for homogeneity with the previous
+     * call. Also, skip T[0] which is already normalised, being a copy of P.
+     */
+    for( j = 0; j + 1 < T_size; j++ )
+        TT[j] = T + j + 1;
+
+    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
 
 cleanup:
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+    {
+        if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+            rs_ctx->rsm->i = j;
+    }
+#endif
 
     return( ret );
 }
 
 /*
  * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ *
+ * See ecp_comb_recode_core() for background
  */
 static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                            const mbedtls_ecp_point T[], unsigned char t_len,
+                            const mbedtls_ecp_point T[], unsigned char T_size,
                             unsigned char i )
 {
     int ret;
@@ -1290,7 +1657,7 @@
     ii =  ( i & 0x7Fu ) >> 1;
 
     /* Read the whole table to thwart cache-based timing attacks */
-    for( j = 0; j < t_len; j++ )
+    for( j = 0; j < T_size; j++ )
     {
         MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
@@ -1310,10 +1677,11 @@
  * Cost: d A + d D + 1 R
  */
 static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                              const mbedtls_ecp_point T[], unsigned char t_len,
+                              const mbedtls_ecp_point T[], unsigned char T_size,
                               const unsigned char x[], size_t d,
                               int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+                              void *p_rng,
+                              mbedtls_ecp_restart_ctx *rs_ctx )
 {
     int ret;
     mbedtls_ecp_point Txi;
@@ -1321,17 +1689,42 @@
 
     mbedtls_ecp_point_init( &Txi );
 
-    /* Start with a non-zero point and randomize its coordinates */
-    i = d;
-    MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
-    if( f_rng != 0 )
-        MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+#if !defined(MBEDTLS_ECP_RESTARTABLE)
+    (void) rs_ctx;
+#endif
 
-    while( i-- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        rs_ctx->rsm->state != ecp_rsm_comb_core )
     {
+        rs_ctx->rsm->i = 0;
+        rs_ctx->rsm->state = ecp_rsm_comb_core;
+    }
+
+    /* new 'if' instead of nested for the sake of the 'else' branch */
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+    {
+        /* restore current index (R already pointing to rs_ctx->rsm->R) */
+        i = rs_ctx->rsm->i;
+    }
+    else
+#endif
+    {
+        /* Start with a non-zero point and randomize its coordinates */
+        i = d;
+        MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
+        if( f_rng != 0 )
+            MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+    }
+
+    while( i != 0 )
+    {
+        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
+        --i;
+
         MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
-        MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+        MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
         MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
     }
 
@@ -1339,32 +1732,130 @@
 
     mbedtls_ecp_point_free( &Txi );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+    {
+        rs_ctx->rsm->i = i;
+        /* no need to save R, already pointing to rs_ctx->rsm->R */
+    }
+#endif
+
     return( ret );
 }
 
 /*
- * Multiplication using the comb method,
- * for curves in short Weierstrass form
+ * Recode the scalar to get constant-time comb multiplication
+ *
+ * As the actual scalar recoding needs an odd scalar as a starting point,
+ * this wrapper ensures that by replacing m by N - m if necessary, and
+ * informs the caller that the result of multiplication will be negated.
+ *
+ * This works because we only support large prime order for Short Weierstrass
+ * curves, so N is always odd hence either m or N - m is.
+ *
+ * See ecp_comb_recode_core() for background.
  */
-static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                         const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng )
+static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
+                                   const mbedtls_mpi *m,
+                                   unsigned char k[COMB_MAX_D + 1],
+                                   size_t d,
+                                   unsigned char w,
+                                   unsigned char *parity_trick )
 {
     int ret;
-    unsigned char w, m_is_odd, p_eq_g, pre_len, i;
-    size_t d;
-    unsigned char k[COMB_MAX_D + 1];
-    mbedtls_ecp_point *T;
     mbedtls_mpi M, mm;
 
     mbedtls_mpi_init( &M );
     mbedtls_mpi_init( &mm );
 
-    /* we need N to be odd to trnaform m in an odd number, check now */
+    /* N is always odd (see above), just make extra sure */
     if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
+    /* do we need the parity trick? */
+    *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
+
+    /* execute parity fix in constant time */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
+
+    /* actual scalar recoding */
+    ecp_comb_recode_core( k, d, w, &M );
+
+cleanup:
+    mbedtls_mpi_free( &mm );
+    mbedtls_mpi_free( &M );
+
+    return( ret );
+}
+
+/*
+ * Perform comb multiplication (for short Weierstrass curves)
+ * once the auxiliary table has been pre-computed.
+ *
+ * Scalar recoding may use a parity trick that makes us compute -m * P,
+ * if that is the case we'll need to recover m * P at the end.
+ */
+static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
+                                mbedtls_ecp_point *R,
+                                const mbedtls_mpi *m,
+                                const mbedtls_ecp_point *T,
+                                unsigned char T_size,
+                                unsigned char w,
+                                size_t d,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng,
+                                mbedtls_ecp_restart_ctx *rs_ctx )
+{
+    int ret;
+    unsigned char parity_trick;
+    unsigned char k[COMB_MAX_D + 1];
+    mbedtls_ecp_point *RR = R;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    {
+        RR = &rs_ctx->rsm->R;
+
+        if( rs_ctx->rsm->state == ecp_rsm_final_norm )
+            goto final_norm;
+    }
+#endif
+
+    MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
+                                            &parity_trick ) );
+    MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
+                                        f_rng, p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+        rs_ctx->rsm->state = ecp_rsm_final_norm;
+
+final_norm:
+#endif
+    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
+#endif
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Pick window size based on curve size and whether we optimize for base point
+ */
+static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
+                                           unsigned char p_eq_g )
+{
+    unsigned char w;
+
     /*
      * Minimize the number of multiplications, that is minimize
      * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
@@ -1377,14 +1868,8 @@
      * Just adding one avoids upping the cost of the first mul too much,
      * and the memory cost too.
      */
-#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
-    p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
-               mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
     if( p_eq_g )
         w++;
-#else
-    p_eq_g = 0;
-#endif
 
     /*
      * Make sure w is within bounds.
@@ -1395,75 +1880,140 @@
     if( w >= grp->nbits )
         w = 2;
 
-    /* Other sizes that depend on w */
-    pre_len = 1U << ( w - 1 );
+    return( w );
+}
+
+/*
+ * Multiplication using the comb method - for curves in short Weierstrass form
+ *
+ * This function is mainly responsible for administrative work:
+ * - managing the restart context if enabled
+ * - managing the table of precomputed points (passed between the below two
+ *   functions): allocation, computation, ownership tranfer, freeing.
+ *
+ * It delegates the actual arithmetic work to:
+ *      ecp_precompute_comb() and ecp_mul_comb_with_precomp()
+ *
+ * See comments on ecp_comb_recode_core() regarding the computation strategy.
+ */
+static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                         const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         mbedtls_ecp_restart_ctx *rs_ctx )
+{
+    int ret;
+    unsigned char w, p_eq_g, i;
+    size_t d;
+    unsigned char T_size, T_ok;
+    mbedtls_ecp_point *T;
+
+    ECP_RS_ENTER( rsm );
+
+    /* Is P the base point ? */
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+    p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+               mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+#else
+    p_eq_g = 0;
+#endif
+
+    /* Pick window size and deduce related sizes */
+    w = ecp_pick_window_size( grp, p_eq_g );
+    T_size = 1U << ( w - 1 );
     d = ( grp->nbits + w - 1 ) / w;
 
-    /*
-     * Prepare precomputed points: if P == G we want to
-     * use grp->T if already initialized, or initialize it.
-     */
-    T = p_eq_g ? grp->T : NULL;
-
-    if( T == NULL )
+    /* Pre-computed table: do we have it already for the base point? */
+    if( p_eq_g && grp->T != NULL )
     {
-        T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
+        /* second pointer to the same table, will be deleted on exit */
+        T = grp->T;
+        T_ok = 1;
+    }
+    else
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    /* Pre-computed table: do we have one in progress? complete? */
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
+    {
+        /* transfer ownership of T from rsm to local function */
+        T = rs_ctx->rsm->T;
+        rs_ctx->rsm->T = NULL;
+        rs_ctx->rsm->T_size = 0;
+
+        /* This effectively jumps to the call to mul_comb_after_precomp() */
+        T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
+    }
+    else
+#endif
+    /* Allocate table if we didn't have any */
+    {
+        T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
         if( T == NULL )
         {
             ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
             goto cleanup;
         }
 
-        MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
+        for( i = 0; i < T_size; i++ )
+            mbedtls_ecp_point_init( &T[i] );
+
+        T_ok = 0;
+    }
+
+    /* Compute table (or finish computing it) if not done already */
+    if( !T_ok )
+    {
+        MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
 
         if( p_eq_g )
         {
+            /* almost transfer ownership of T to the group, but keep a copy of
+             * the pointer to use for calling the next function more easily */
             grp->T = T;
-            grp->T_size = pre_len;
+            grp->T_size = T_size;
         }
     }
 
-    /*
-     * Make sure M is odd (M = m or M = N - m, since N is odd)
-     * using the fact that m * P = - (N - m) * P
-     */
-    m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
-
-    /*
-     * Go for comb multiplication, R = M * P
-     */
-    ecp_comb_fixed( k, d, w, &M );
-    MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
-
-    /*
-     * Now get m * P from M * P and normalize it
-     */
-    MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
-    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
+    /* Actual comb multiplication using precomputed points */
+    MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
+                                                 T, T_size, w, d,
+                                                 f_rng, p_rng, rs_ctx ) );
 
 cleanup:
 
-    /* There are two cases where T is not stored in grp:
-     * - P != G
-     * - An intermediate operation failed before setting grp->T
-     * In either case, T must be freed.
-     */
-    if( T != NULL && T != grp->T )
+    /* does T belong to the group? */
+    if( T == grp->T )
+        T = NULL;
+
+    /* does T belong to the restart context? */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL )
     {
-        for( i = 0; i < pre_len; i++ )
+        /* transfer ownership of T from local function to rsm */
+        rs_ctx->rsm->T_size = T_size;
+        rs_ctx->rsm->T = T;
+        T = NULL;
+    }
+#endif
+
+    /* did T belong to us? then let's destroy it! */
+    if( T != NULL )
+    {
+        for( i = 0; i < T_size; i++ )
             mbedtls_ecp_point_free( &T[i] );
         mbedtls_free( T );
     }
 
-    mbedtls_mpi_free( &M );
-    mbedtls_mpi_free( &mm );
-
+    /* don't free R while in progress in case R == P */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+    /* prevent caller from using invalid value */
     if( ret != 0 )
         mbedtls_ecp_point_free( R );
 
+    ECP_RS_LEAVE( rsm );
+
     return( ret );
 }
 
@@ -1487,10 +2037,8 @@
     int ret;
 
 #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_normalize_mxz( grp, P );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
 #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
@@ -1518,10 +2066,8 @@
     int count = 0;
 
 #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
 #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
 
     p_size = ( grp->pbits + 7 ) / 8;
@@ -1573,10 +2119,8 @@
     mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
 
 #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
-    if ( mbedtls_internal_ecp_grp_capable( grp ) )
-    {
-        return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
-    }
+    if( mbedtls_internal_ecp_grp_capable( grp ) )
+        return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
 #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
 
     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
@@ -1673,54 +2217,77 @@
 #endif /* ECP_MONTGOMERY */
 
 /*
- * Multiplication R = m * P
+ * Restartable multiplication R = m * P
  */
-int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
              const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+             mbedtls_ecp_restart_ctx *rs_ctx )
 {
     int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
     char is_grp_capable = 0;
 #endif
 
-    /* Common sanity checks */
-    if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-
-    if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
-        ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
-        return( ret );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    /* reset ops count for this call if top-level */
+    if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
+        rs_ctx->ops_done = 0;
+#endif
 
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp )  )
-    {
+    if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
         MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    /* skip argument check when restarting */
+    if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+    {
+        /* check_privkey is free */
+        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
+
+        /* Common sanity checks */
+        MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
+        MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
     }
 
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+    ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 #if defined(ECP_MONTGOMERY)
     if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
-        ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
-
+        MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
 #endif
 #if defined(ECP_SHORTWEIERSTRASS)
     if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
-        ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
-
+        MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
 #endif
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+
 cleanup:
 
-    if ( is_grp_capable )
-    {
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+    if( is_grp_capable )
         mbedtls_internal_ecp_free( grp );
-    }
-
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL )
+        rs_ctx->depth--;
+#endif
+
     return( ret );
 }
 
+/*
+ * Multiplication R = m * P
+ */
+int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
+}
+
 #if defined(ECP_SHORTWEIERSTRASS)
 /*
  * Check that an affine point is valid as a public key,
@@ -1778,7 +2345,8 @@
 static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
                                       mbedtls_ecp_point *R,
                                       const mbedtls_mpi *m,
-                                      const mbedtls_ecp_point *P )
+                                      const mbedtls_ecp_point *P,
+                                      mbedtls_ecp_restart_ctx *rs_ctx )
 {
     int ret;
 
@@ -1794,7 +2362,8 @@
     }
     else
     {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
+        MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
+                                                      NULL, NULL, rs_ctx ) );
     }
 
 cleanup:
@@ -1802,6 +2371,96 @@
 }
 
 /*
+ * Restartable linear combination
+ * NOT constant-time
+ */
+int mbedtls_ecp_muladd_restartable(
+             mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+             const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+             mbedtls_ecp_restart_ctx *rs_ctx )
+{
+    int ret;
+    mbedtls_ecp_point mP;
+    mbedtls_ecp_point *pmP = &mP;
+    mbedtls_ecp_point *pR = R;
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+    char is_grp_capable = 0;
+#endif
+
+    if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
+        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    mbedtls_ecp_point_init( &mP );
+
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+    if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
+        MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+    ECP_RS_ENTER( ma );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+    {
+        /* redirect intermediate results to restart context */
+        pmP = &rs_ctx->ma->mP;
+        pR  = &rs_ctx->ma->R;
+
+        /* jump to next operation */
+        if( rs_ctx->ma->state == ecp_rsma_mul2 )
+            goto mul2;
+        if( rs_ctx->ma->state == ecp_rsma_add )
+            goto add;
+        if( rs_ctx->ma->state == ecp_rsma_norm )
+            goto norm;
+    }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+        rs_ctx->ma->state = ecp_rsma_mul2;
+
+mul2:
+#endif
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR,  n, Q, rs_ctx ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+        rs_ctx->ma->state = ecp_rsma_add;
+
+add:
+#endif
+    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
+    MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+        rs_ctx->ma->state = ecp_rsma_norm;
+
+norm:
+#endif
+    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
+#endif
+
+cleanup:
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+    if( is_grp_capable )
+        mbedtls_internal_ecp_free( grp );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+    mbedtls_ecp_point_free( &mP );
+
+    ECP_RS_LEAVE( ma );
+
+    return( ret );
+}
+
+/*
  * Linear combination
  * NOT constant-time
  */
@@ -1809,45 +2468,9 @@
              const mbedtls_mpi *m, const mbedtls_ecp_point *P,
              const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
 {
-    int ret;
-    mbedtls_ecp_point mP;
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    char is_grp_capable = 0;
-#endif
-
-    if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
-        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
-
-    mbedtls_ecp_point_init( &mP );
-
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R,   n, Q ) );
-
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if (  is_grp_capable = mbedtls_internal_ecp_grp_capable( grp )  )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
-    }
-
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
-    MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
-    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
-
-cleanup:
-
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if ( is_grp_capable )
-    {
-        mbedtls_internal_ecp_free( grp );
-    }
-
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
-    mbedtls_ecp_point_free( &mP );
-
-    return( ret );
+    return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
 }
 
-
 #if defined(ECP_MONTGOMERY)
 /*
  * Check validity of a public key for Montgomery curves with x-only schemes
@@ -1897,7 +2520,6 @@
             mbedtls_mpi_get_bit( d, 1 ) != 0 ||
             mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
             return( MBEDTLS_ERR_ECP_INVALID_KEY );
-        else
 
         /* see [Curve25519] page 5 */
         if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
@@ -1922,15 +2544,14 @@
 }
 
 /*
- * Generate a keypair with configurable base point
+ * Generate a private key
  */
-int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
-                     const mbedtls_ecp_point *G,
-                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+                     mbedtls_mpi *d,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     size_t n_size = ( grp->nbits + 7 ) / 8;
 
 #if defined(ECP_MONTGOMERY)
@@ -1959,8 +2580,8 @@
             MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
         }
     }
-    else
 #endif /* ECP_MONTGOMERY */
+
 #if defined(ECP_SHORTWEIERSTRASS)
     if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
     {
@@ -1994,15 +2615,28 @@
         while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
                mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
     }
-    else
 #endif /* ECP_SHORTWEIERSTRASS */
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
 cleanup:
-    if( ret != 0 )
-        return( ret );
+    return( ret );
+}
 
-    return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+/*
+ * Generate a keypair with configurable base point
+ */
+int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
+                     const mbedtls_ecp_point *G,
+                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+
+cleanup:
+    return( ret );
 }
 
 /*
diff --git a/library/error.c b/library/error.c
index 774244b..27692db 100644
--- a/library/error.c
+++ b/library/error.c
@@ -165,6 +165,10 @@
 #include "mbedtls/pkcs5.h"
 #endif
 
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
 #if defined(MBEDTLS_POLY1305_C)
 #include "mbedtls/poly1305.h"
 #endif
@@ -289,6 +293,8 @@
             mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" );
         if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
             mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" );
+        if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) )
+            mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" );
 #endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_MD_C)
@@ -515,6 +521,10 @@
             mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
         if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
             mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
+        if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
+            mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
+        if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
+            mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
 #endif /* MBEDTLS_SSL_TLS_C */
 
 #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@@ -821,6 +831,11 @@
         mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
 #endif /* MBEDTLS_PADLOCK_C */
 
+#if defined(MBEDTLS_PLATFORM_C)
+    if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) )
+        mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" );
+#endif /* MBEDTLS_PLATFORM_C */
+
 #if defined(MBEDTLS_POLY1305_C)
     if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
         mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
diff --git a/library/pk.c b/library/pk.c
index f05b139..e0e8dba 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -69,6 +69,34 @@
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
 }
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
+{
+    ctx->pk_info = NULL;
+    ctx->rs_ctx = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        ctx->pk_info->rs_free_func == NULL )
+    {
+        return;
+    }
+
+    ctx->pk_info->rs_free_func( ctx->rs_ctx );
+
+    ctx->pk_info = NULL;
+    ctx->rs_ctx = NULL;
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
 /*
  * Get pk_info structure from type
  */
@@ -171,6 +199,73 @@
     return( 0 );
 }
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Helper to set up a restart context if needed
+ */
+static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
+                             const mbedtls_pk_info_t *info )
+{
+    /* Don't do anything if already set up or invalid */
+    if( ctx == NULL || ctx->pk_info != NULL )
+        return( 0 );
+
+    /* Should never happen when we're called */
+    if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
+        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+    if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
+        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+
+    ctx->pk_info = info;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/*
+ * Verify a signature (restartable)
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+               mbedtls_md_type_t md_alg,
+               const unsigned char *hash, size_t hash_len,
+               const unsigned char *sig, size_t sig_len,
+               mbedtls_pk_restart_ctx *rs_ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /* optimization: use non-restartable version if restart disabled */
+    if( rs_ctx != NULL &&
+        mbedtls_ecp_restart_is_enabled() &&
+        ctx->pk_info->verify_rs_func != NULL )
+    {
+        int ret;
+
+        if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+            return( ret );
+
+        ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
+                   md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
+
+        if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+            mbedtls_pk_restart_free( rs_ctx );
+
+        return( ret );
+    }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+    if( ctx->pk_info->verify_func == NULL )
+        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
+                                       sig, sig_len ) );
+}
+
 /*
  * Verify a signature
  */
@@ -178,15 +273,8 @@
                const unsigned char *hash, size_t hash_len,
                const unsigned char *sig, size_t sig_len )
 {
-    if( ctx == NULL || ctx->pk_info == NULL ||
-        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-    if( ctx->pk_info->verify_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
-    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
-                                       sig, sig_len ) );
+    return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
+                                           sig, sig_len, NULL ) );
 }
 
 /*
@@ -248,6 +336,50 @@
 }
 
 /*
+ * Make a signature (restartable)
+ */
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+             mbedtls_md_type_t md_alg,
+             const unsigned char *hash, size_t hash_len,
+             unsigned char *sig, size_t *sig_len,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+             mbedtls_pk_restart_ctx *rs_ctx )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /* optimization: use non-restartable version if restart disabled */
+    if( rs_ctx != NULL &&
+        mbedtls_ecp_restart_is_enabled() &&
+        ctx->pk_info->sign_rs_func != NULL )
+    {
+        int ret;
+
+        if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+            return( ret );
+
+        ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
+                hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
+
+        if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+            mbedtls_pk_restart_free( rs_ctx );
+
+        return( ret );
+    }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+    if( ctx->pk_info->sign_func == NULL )
+        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
+                                     sig, sig_len, f_rng, p_rng ) );
+}
+
+/*
  * Make a signature
  */
 int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
@@ -255,15 +387,8 @@
              unsigned char *sig, size_t *sig_len,
              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
-    if( ctx == NULL || ctx->pk_info == NULL ||
-        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-    if( ctx->pk_info->sign_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
-    return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
-                                     sig, sig_len, f_rng, p_rng ) );
+    return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
+                                         sig, sig_len, f_rng, p_rng, NULL ) );
 }
 
 /*
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 2c7d2d7..87806be 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -190,11 +190,19 @@
     rsa_can_do,
     rsa_verify_wrap,
     rsa_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     rsa_decrypt_wrap,
     rsa_encrypt_wrap,
     rsa_check_pair_wrap,
     rsa_alloc_wrap,
     rsa_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     rsa_debug,
 };
 #endif /* MBEDTLS_RSA_C */
@@ -262,6 +270,110 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/* Forward declarations */
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len,
+                       void *rs_ctx );
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                   void *rs_ctx );
+
+/*
+ * Restart context for ECDSA operations with ECKEY context
+ *
+ * We need to store an actual ECDSA context, as we need to pass the same to
+ * the underlying ecdsa function, so we can't create it on the fly every time.
+ */
+typedef struct
+{
+    mbedtls_ecdsa_restart_ctx ecdsa_rs;
+    mbedtls_ecdsa_context ecdsa_ctx;
+} eckey_restart_ctx;
+
+static void *eckey_rs_alloc( void )
+{
+    eckey_restart_ctx *rs_ctx;
+
+    void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
+
+    if( ctx != NULL )
+    {
+        rs_ctx = ctx;
+        mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
+        mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
+    }
+
+    return( ctx );
+}
+
+static void eckey_rs_free( void *ctx )
+{
+    eckey_restart_ctx *rs_ctx;
+
+    if( ctx == NULL)
+        return;
+
+    rs_ctx = ctx;
+    mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
+    mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
+
+    mbedtls_free( ctx );
+}
+
+static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len,
+                       void *rs_ctx )
+{
+    int ret;
+    eckey_restart_ctx *rs = rs_ctx;
+
+    /* Should never happen */
+    if( rs == NULL )
+        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+    /* set up our own sub-context if needed (that is, on first run) */
+    if( rs->ecdsa_ctx.grp.pbits == 0 )
+        MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+    MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
+                                           md_alg, hash, hash_len,
+                                           sig, sig_len, &rs->ecdsa_rs ) );
+
+cleanup:
+    return( ret );
+}
+
+static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                       void *rs_ctx )
+{
+    int ret;
+    eckey_restart_ctx *rs = rs_ctx;
+
+    /* Should never happen */
+    if( rs == NULL )
+        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+    /* set up our own sub-context if needed (that is, on first run) */
+    if( rs->ecdsa_ctx.grp.pbits == 0 )
+        MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+    MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
+                                         hash, hash_len, sig, sig_len,
+                                         f_rng, p_rng, &rs->ecdsa_rs ) );
+
+cleanup:
+    return( ret );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
 #endif /* MBEDTLS_ECDSA_C */
 
 static int eckey_check_pair( const void *pub, const void *prv )
@@ -301,15 +413,23 @@
 #if defined(MBEDTLS_ECDSA_C)
     eckey_verify_wrap,
     eckey_sign_wrap,
-#else
-    NULL,
-    NULL,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    eckey_verify_rs_wrap,
+    eckey_sign_rs_wrap,
 #endif
+#else /* MBEDTLS_ECDSA_C */
+    NULL,
+    NULL,
+#endif /* MBEDTLS_ECDSA_C */
     NULL,
     NULL,
     eckey_check_pair,
     eckey_alloc_wrap,
     eckey_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    eckey_rs_alloc,
+    eckey_rs_free,
+#endif
     eckey_debug,
 };
 
@@ -329,11 +449,19 @@
     eckeydh_can_do,
     NULL,
     NULL,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     NULL,
     NULL,
     eckey_check_pair,
     eckey_alloc_wrap,       /* Same underlying key structure */
     eckey_free_wrap,        /* Same underlying key structure */
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     eckey_debug,            /* Same underlying key structure */
 };
 #endif /* MBEDTLS_ECP_C */
@@ -369,6 +497,40 @@
                 md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
 }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len,
+                       void *rs_ctx )
+{
+    int ret;
+    ((void) md_alg);
+
+    ret = mbedtls_ecdsa_read_signature_restartable(
+            (mbedtls_ecdsa_context *) ctx,
+            hash, hash_len, sig, sig_len,
+            (mbedtls_ecdsa_restart_ctx *) rs_ctx );
+
+    if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
+        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
+
+    return( ret );
+}
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                   void *rs_ctx )
+{
+    return( mbedtls_ecdsa_write_signature_restartable(
+                (mbedtls_ecdsa_context *) ctx,
+                md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
+                (mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
+
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 static void *ecdsa_alloc_wrap( void )
 {
     void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
@@ -385,6 +547,24 @@
     mbedtls_free( ctx );
 }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static void *ecdsa_rs_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
+
+    if( ctx != NULL )
+        mbedtls_ecdsa_restart_init( ctx );
+
+    return( ctx );
+}
+
+static void ecdsa_rs_free( void *ctx )
+{
+    mbedtls_ecdsa_restart_free( ctx );
+    mbedtls_free( ctx );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
 const mbedtls_pk_info_t mbedtls_ecdsa_info = {
     MBEDTLS_PK_ECDSA,
     "ECDSA",
@@ -392,11 +572,19 @@
     ecdsa_can_do,
     ecdsa_verify_wrap,
     ecdsa_sign_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    ecdsa_verify_rs_wrap,
+    ecdsa_sign_rs_wrap,
+#endif
     NULL,
     NULL,
     eckey_check_pair,   /* Compatible key structures */
     ecdsa_alloc_wrap,
     ecdsa_free_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    ecdsa_rs_alloc,
+    ecdsa_rs_free,
+#endif
     eckey_debug,        /* Compatible key structures */
 };
 #endif /* MBEDTLS_ECDSA_C */
@@ -506,6 +694,10 @@
     rsa_alt_can_do,
     NULL,
     rsa_alt_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     rsa_alt_decrypt_wrap,
     NULL,
 #if defined(MBEDTLS_RSA_C)
@@ -515,6 +707,10 @@
 #endif
     rsa_alt_alloc_wrap,
     rsa_alt_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL,
+    NULL,
+#endif
     NULL,
 };
 
diff --git a/library/platform_util.c b/library/platform_util.c
index 1a57de9..ca5fe4f 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -20,6 +20,14 @@
  *  This file is part of Mbed TLS (https://tls.mbed.org)
  */
 
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -27,6 +35,7 @@
 #endif
 
 #include "mbedtls/platform_util.h"
+#include "mbedtls/threading.h"
 
 #include <stddef.h>
 #include <string.h>
@@ -65,3 +74,62 @@
     memset_func( buf, 0, len );
 }
 #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+#include <time.h>
+#if !defined(_WIN32) && (defined(unix) || \
+    defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+    defined(__MACH__)))
+#include <unistd.h>
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+        * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
+       ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+         _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define PLATFORM_UTIL_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
+             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+                _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+                                      struct tm *tm_buf )
+{
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+    return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL );
+#elif !defined(PLATFORM_UTIL_USE_GMTIME)
+    return( gmtime_r( tt, tm_buf ) );
+#else
+    struct tm *lt;
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
+        return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+    lt = gmtime( tt );
+
+    if( lt != NULL )
+    {
+        memcpy( tm_buf, lt, sizeof( struct tm ) );
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
+        return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+    return( ( lt == NULL ) ? NULL : tm_buf );
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+}
+#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 321d636..5720a4b 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1088,12 +1088,21 @@
         mbedtls_ssl_send_flight_completed( ssl );
 #endif
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+        return( ret );
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
 
     return( 0 );
@@ -1491,7 +1500,7 @@
 
     buf = ssl->in_msg;
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         /* No alert on a read error. */
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@@ -1754,6 +1763,14 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
+        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    {
+        ssl->handshake->ecrs_enabled = 1;
+    }
+#endif
+
     if( comp != MBEDTLS_SSL_COMPRESS_NULL
 #if defined(MBEDTLS_ZLIB_SUPPORT)
         && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
@@ -2059,6 +2076,10 @@
                                   (const unsigned char **) p, end ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
         return( ret );
     }
 
@@ -2340,7 +2361,15 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
+    {
+        goto start_processing;
+    }
+#endif
+
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -2377,6 +2406,12 @@
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled )
+        ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
+
+start_processing:
+#endif
     p   = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
     end = ssl->in_msg + ssl->in_hslen;
     MBEDTLS_SSL_DEBUG_BUF( 3,   "server key exchange", p, end - p );
@@ -2469,6 +2504,7 @@
         mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
         unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
         size_t params_len = p - params;
+        void *rs_ctx = NULL;
 
         /*
          * Handle the digitally-signed structure
@@ -2591,12 +2627,25 @@
             return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
         }
 
-        if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
-                               md_alg, hash, hashlen, p, sig_len ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ssl->handshake->ecrs_enabled )
+            rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+        if( ( ret = mbedtls_pk_verify_restartable(
+                        &ssl->session_negotiate->peer_cert->pk,
+                        md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
         {
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+            if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                                MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
             return( ret );
         }
     }
@@ -2647,7 +2696,7 @@
         return( 0 );
     }
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -2721,7 +2770,7 @@
      * therefore the buffer length at this point must be greater than that
      * regardless of the actual code path.
      */
-    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
+    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2799,7 +2848,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -2894,6 +2943,16 @@
          */
         i = 4;
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ssl->handshake->ecrs_enabled )
+        {
+            if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
+                goto ecdh_calc_secret;
+
+            mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
+        }
+#endif
+
         ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
                                 &n,
                                 &ssl->out_msg[i], 1000,
@@ -2901,11 +2960,26 @@
         if( ret != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
             return( ret );
         }
 
         MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ssl->handshake->ecrs_enabled )
+        {
+            ssl->handshake->ecrs_n = n;
+            ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
+        }
+
+ecdh_calc_secret:
+        if( ssl->handshake->ecrs_enabled )
+            n = ssl->handshake->ecrs_n;
+#endif
         if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
                                       &ssl->handshake->pmslen,
                                        ssl->handshake->premaster,
@@ -2913,6 +2987,10 @@
                                        ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
             return( ret );
         }
 
@@ -3075,9 +3153,9 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -3131,9 +3209,18 @@
     unsigned char *hash_start = hash;
     mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
     unsigned int hashlen;
+    void *rs_ctx = NULL;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
+    {
+        goto sign;
+    }
+#endif
+
     if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
@@ -3165,8 +3252,15 @@
     }
 
     /*
-     * Make an RSA signature of the handshake digests
+     * Make a signature of the handshake digests
      */
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled )
+        ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
+
+sign:
+#endif
+
     ssl->handshake->calc_verify( ssl, hash );
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
@@ -3243,11 +3337,21 @@
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
 
-    if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen,
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled )
+        rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+    if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
+                         md_alg, hash_start, hashlen,
                          ssl->out_msg + 6 + offset, &n,
-                         ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+                         ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
         return( ret );
     }
 
@@ -3260,9 +3364,9 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -3288,7 +3392,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -3323,8 +3427,8 @@
 
     msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
 
-    lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) |
-               ( msg[2] <<  8 ) | ( msg[3]       );
+    lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
+               ( msg[2] << 8 ) | ( msg[3] );
 
     ticket_len = ( msg[4] << 8 ) | ( msg[5] );
 
@@ -3402,10 +3506,10 @@
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
     {
-        if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+        if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
             return( ret );
     }
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
     /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
      * by DTLS for dropping out-of-sequence ChangeCipherSpec records */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 2872f1f..36ca0d6 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1294,7 +1294,7 @@
             return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
         }
 
-        memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 );
+        memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
         if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
@@ -2384,12 +2384,21 @@
 
     ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+        return( ret );
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
 
     return( 0 );
@@ -2624,7 +2633,7 @@
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO;
 
-    ret = mbedtls_ssl_write_record( ssl );
+    ret = mbedtls_ssl_write_handshake_msg( ssl );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
 
@@ -2819,7 +2828,7 @@
     ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size  >> 8 );
     ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size       );
 
-    ret = mbedtls_ssl_write_record( ssl );
+    ret = mbedtls_ssl_write_handshake_msg( ssl );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
 
@@ -3336,9 +3345,9 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -3363,12 +3372,21 @@
         mbedtls_ssl_send_flight_completed( ssl );
 #endif
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+        return( ret );
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
 
     return( 0 );
@@ -3710,7 +3728,7 @@
     }
     else
 #endif
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -4020,25 +4038,10 @@
     }
 
     /* Read the message without adding it to the checksum */
-    do {
-
-        do ret = mbedtls_ssl_read_record_layer( ssl );
-        while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
-            return( ret );
-        }
-
-        ret = mbedtls_ssl_handle_message_type( ssl );
-
-    } while( MBEDTLS_ERR_SSL_NON_FATAL           == ret ||
-             MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
-
+    ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
     if( 0 != ret )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
         return( ret );
     }
 
@@ -4227,9 +4230,9 @@
      */
     ssl->handshake->new_session_ticket = 0;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -4258,10 +4261,10 @@
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
     {
-        if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+        if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
             return( ret );
     }
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
     switch( ssl->state )
     {
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index a2b3048..985b7cd 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -97,7 +97,7 @@
         uint32_t current_time = (uint32_t) mbedtls_time( NULL );
         uint32_t key_time = ctx->keys[ctx->active].generation_time;
 
-        if( current_time > key_time &&
+        if( current_time >= key_time &&
             current_time - key_time < ctx->ticket_lifetime )
         {
             return( 0 );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 3b047fc..ee7944b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -54,6 +54,9 @@
 #include "mbedtls/oid.h"
 #endif
 
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
+
 /* Length of the "epoch" field in the record header */
 static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
 {
@@ -96,7 +99,101 @@
     return( 0 );
 }
 
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+                                     mbedtls_ssl_transform *transform );
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+                                    mbedtls_ssl_transform *transform );
+
+#define SSL_DONT_FORCE_FLUSH 0
+#define SSL_FORCE_FLUSH      1
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/* Forward declarations for functions related to message buffering. */
+static void ssl_buffering_free( mbedtls_ssl_context *ssl );
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+                                     uint8_t slot );
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
+static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
+{
+    size_t mtu = ssl_get_current_mtu( ssl );
+
+    if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN )
+        return( mtu );
+
+    return( MBEDTLS_SSL_OUT_BUFFER_LEN );
+}
+
+static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
+{
+    size_t const bytes_written = ssl->out_left;
+    size_t const mtu           = ssl_get_maximum_datagram_size( ssl );
+
+    /* Double-check that the write-index hasn't gone
+     * past what we can transmit in a single datagram. */
+    if( bytes_written > mtu )
+    {
+        /* Should never happen... */
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    return( (int) ( mtu - bytes_written ) );
+}
+
+static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+{
+    int ret;
+    size_t remaining, expansion;
+    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+    if( max_len > mfl )
+        max_len = mfl;
+
+    /* By the standard (RFC 6066 Sect. 4), the MFL extension
+     * only limits the maximum record payload size, so in theory
+     * we would be allowed to pack multiple records of payload size
+     * MFL into a single datagram. However, this would mean that there's
+     * no way to explicitly communicate MTU restrictions to the peer.
+     *
+     * The following reduction of max_len makes sure that we never
+     * write datagrams larger than MFL + Record Expansion Overhead.
+     */
+    if( max_len <= ssl->out_left )
+        return( 0 );
+
+    max_len -= ssl->out_left;
+#endif
+
+    ret = ssl_get_remaining_space_in_datagram( ssl );
+    if( ret < 0 )
+        return( ret );
+    remaining = (size_t) ret;
+
+    ret = mbedtls_ssl_get_record_expansion( ssl );
+    if( ret < 0 )
+        return( ret );
+    expansion = (size_t) ret;
+
+    if( remaining <= expansion )
+        return( 0 );
+
+    remaining -= expansion;
+    if( remaining >= max_len )
+        remaining = max_len;
+
+    return( (int) remaining );
+}
+
 /*
  * Double the retransmit timeout value, within the allowed range,
  * returning -1 if the maximum value has already been reached.
@@ -108,6 +205,18 @@
     if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
         return( -1 );
 
+    /* Implement the final paragraph of RFC 6347 section 4.1.1.1
+     * in the following way: after the initial transmission and a first
+     * retransmission, back off to a temporary estimated MTU of 508 bytes.
+     * This value is guaranteed to be deliverable (if not guaranteed to be
+     * delivered) of any compliant IPv4 (and IPv6) network, and should work
+     * on most non-IP stacks too. */
+    if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
+    {
+        ssl->handshake->mtu = 508;
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+    }
+
     new_timeout = 2 * ssl->handshake->retransmit_timeout;
 
     /* Avoid arithmetic overflow and range overflow */
@@ -1345,14 +1454,6 @@
     MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                       ssl->out_msg, ssl->out_msglen );
 
-    if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
-                                    (unsigned) ssl->out_msglen,
-                                    MBEDTLS_SSL_OUT_CONTENT_LEN ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-
     /*
      * Add MAC before if needed
      */
@@ -1626,6 +1727,8 @@
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
         if( auth_done == 0 )
         {
+            unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+
             /*
              * MAC(MAC_write_key, seq_num +
              *     TLSCipherText.type +
@@ -1648,10 +1751,12 @@
             mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
             mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc,
                              ssl->out_iv, ssl->out_msglen );
-            mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc,
-                             ssl->out_iv + ssl->out_msglen );
+            mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
             mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc );
 
+            memcpy( ssl->out_iv + ssl->out_msglen, mac,
+                    ssl->transform_out->maclen );
+
             ssl->out_msglen += ssl->transform_out->maclen;
             auth_done++;
         }
@@ -2644,7 +2749,7 @@
 int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
 {
     int ret;
-    unsigned char *buf, i;
+    unsigned char *buf;
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
 
@@ -2667,8 +2772,7 @@
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
                        mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
 
-        buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) +
-              ssl->out_msglen - ssl->out_left;
+        buf = ssl->out_hdr - ssl->out_left;
         ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
 
         MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
@@ -2687,16 +2791,17 @@
         ssl->out_left -= ret;
     }
 
-    for( i = 8; i > ssl_ep_len( ssl ); i-- )
-        if( ++ssl->out_ctr[i - 1] != 0 )
-            break;
-
-    /* The loop goes to its end iff the counter is wrapping */
-    if( i == ssl_ep_len( ssl ) )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
-        return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+        ssl->out_hdr = ssl->out_buf;
     }
+    else
+#endif
+    {
+        ssl->out_hdr = ssl->out_buf + 8;
+    }
+    ssl_update_out_pointers( ssl, ssl->transform_out );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
 
@@ -2713,6 +2818,9 @@
 static int ssl_flight_append( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_flight_item *msg;
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
+    MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
+                           ssl->out_msg, ssl->out_msglen );
 
     /* Allocate space for current message */
     if( ( msg = mbedtls_calloc( 1, sizeof(  mbedtls_ssl_flight_item ) ) ) == NULL )
@@ -2746,6 +2854,7 @@
         cur->next = msg;
     }
 
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
     return( 0 );
 }
 
@@ -2794,19 +2903,12 @@
     ssl->handshake->alt_transform_out = tmp_transform;
 
     /* Swap epoch + sequence_number */
-    memcpy( tmp_out_ctr,                 ssl->out_ctr,                8 );
-    memcpy( ssl->out_ctr,                ssl->handshake->alt_out_ctr, 8 );
+    memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
+    memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
     memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
 
     /* Adjust to the newly activated transform */
-    if( ssl->transform_out != NULL &&
-        ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-    {
-        ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen -
-                                     ssl->transform_out->fixed_ivlen;
-    }
-    else
-        ssl->out_msg = ssl->out_iv;
+    ssl_update_out_pointers( ssl, ssl->transform_out );
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_activate != NULL )
@@ -2822,20 +2924,38 @@
 
 /*
  * Retransmit the current flight of messages.
+ */
+int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+{
+    int ret = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+
+    ret = mbedtls_ssl_flight_transmit( ssl );
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+
+    return( ret );
+}
+
+/*
+ * Transmit or retransmit the current flight of messages.
  *
  * Need to remember the current message in case flush_output returns
  * WANT_WRITE, causing us to exit this function and come back later.
  * This function must be called until state is no longer SENDING.
  */
-int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+    int ret;
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
 
     if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
 
         ssl->handshake->cur_msg = ssl->handshake->flight;
+        ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
         ssl_swap_epochs( ssl );
 
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
@@ -2843,33 +2963,129 @@
 
     while( ssl->handshake->cur_msg != NULL )
     {
-        int ret;
-        mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg;
+        size_t max_frag_len;
+        const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
+
+        int const is_finished =
+            ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
+              cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
+
+        uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
+            SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
 
         /* Swap epochs before sending Finished: we can't do it after
          * sending ChangeCipherSpec, in case write returns WANT_READ.
          * Must be done before copying, may change out_msg pointer */
-        if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
-            cur->p[0] == MBEDTLS_SSL_HS_FINISHED )
+        if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
         {
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
             ssl_swap_epochs( ssl );
         }
 
-        memcpy( ssl->out_msg, cur->p, cur->len );
-        ssl->out_msglen = cur->len;
-        ssl->out_msgtype = cur->type;
+        ret = ssl_get_remaining_payload_in_datagram( ssl );
+        if( ret < 0 )
+            return( ret );
+        max_frag_len = (size_t) ret;
 
-        ssl->handshake->cur_msg = cur->next;
+        /* CCS is copied as is, while HS messages may need fragmentation */
+        if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+        {
+            if( max_frag_len == 0 )
+            {
+                if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+                    return( ret );
 
-        MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 );
+                continue;
+            }
 
-        if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+            memcpy( ssl->out_msg, cur->p, cur->len );
+            ssl->out_msglen  = cur->len;
+            ssl->out_msgtype = cur->type;
+
+            /* Update position inside current message */
+            ssl->handshake->cur_msg_p += cur->len;
+        }
+        else
+        {
+            const unsigned char * const p = ssl->handshake->cur_msg_p;
+            const size_t hs_len = cur->len - 12;
+            const size_t frag_off = p - ( cur->p + 12 );
+            const size_t rem_len = hs_len - frag_off;
+            size_t cur_hs_frag_len, max_hs_frag_len;
+
+            if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
+            {
+                if( is_finished )
+                    ssl_swap_epochs( ssl );
+
+                if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+                    return( ret );
+
+                continue;
+            }
+            max_hs_frag_len = max_frag_len - 12;
+
+            cur_hs_frag_len = rem_len > max_hs_frag_len ?
+                max_hs_frag_len : rem_len;
+
+            if( frag_off == 0 && cur_hs_frag_len != hs_len )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
+                                            (unsigned) cur_hs_frag_len,
+                                            (unsigned) max_hs_frag_len ) );
+            }
+
+            /* Messages are stored with handshake headers as if not fragmented,
+             * copy beginning of headers then fill fragmentation fields.
+             * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
+            memcpy( ssl->out_msg, cur->p, 6 );
+
+            ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
+            ssl->out_msg[7] = ( ( frag_off >>  8 ) & 0xff );
+            ssl->out_msg[8] = ( ( frag_off       ) & 0xff );
+
+            ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
+            ssl->out_msg[10] = ( ( cur_hs_frag_len >>  8 ) & 0xff );
+            ssl->out_msg[11] = ( ( cur_hs_frag_len       ) & 0xff );
+
+            MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+            /* Copy the handshake message content and set records fields */
+            memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
+            ssl->out_msglen = cur_hs_frag_len + 12;
+            ssl->out_msgtype = cur->type;
+
+            /* Update position inside current message */
+            ssl->handshake->cur_msg_p += cur_hs_frag_len;
+        }
+
+        /* If done with the current message move to the next one if any */
+        if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
+        {
+            if( cur->next != NULL )
+            {
+                ssl->handshake->cur_msg = cur->next;
+                ssl->handshake->cur_msg_p = cur->next->p + 12;
+            }
+            else
+            {
+                ssl->handshake->cur_msg = NULL;
+                ssl->handshake->cur_msg_p = NULL;
+            }
+        }
+
+        /* Actually send the message out */
+        if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
             return( ret );
         }
     }
 
+    if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+        return( ret );
+
+    /* Update state and set timer */
     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
     else
@@ -2878,7 +3094,7 @@
         ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
 
     return( 0 );
 }
@@ -2896,6 +3112,12 @@
     /* The next incoming flight will start with this msg_seq */
     ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
 
+    /* We don't want to remember CCS's across flight boundaries. */
+    ssl->handshake->buffering.seen_ccs = 0;
+
+    /* Clear future message buffering structure. */
+    ssl_buffering_free( ssl );
+
     /* Cancel timer */
     ssl_set_timer( ssl, 0 );
 
@@ -2927,43 +3149,100 @@
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 /*
- * Record layer functions
+ * Handshake layer functions
  */
 
 /*
- * Write current record.
- * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg.
+ * Write (DTLS: or queue) current handshake (including CCS) message.
+ *
+ *  - fill in handshake headers
+ *  - update handshake checksum
+ *  - DTLS: save message for resending
+ *  - then pass to the record layer
+ *
+ * DTLS: except for HelloRequest, messages are only queued, and will only be
+ * actually sent when calling flight_transmit() or resend().
+ *
+ * Inputs:
+ *  - ssl->out_msglen: 4 + actual handshake message len
+ *      (4 is the size of handshake headers for TLS)
+ *  - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
+ *  - ssl->out_msg + 4: the handshake message body
+ *
+ * Outputs, ie state before passing to flight_append() or write_record():
+ *   - ssl->out_msglen: the length of the record contents
+ *      (including handshake headers but excluding record headers)
+ *   - ssl->out_msg: the record contents (handshake headers + content)
  */
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
 {
-    int ret, done = 0, out_msg_type;
-    size_t len = ssl->out_msglen;
+    int ret;
+    const size_t hs_len = ssl->out_msglen - 4;
+    const unsigned char hs_type = ssl->out_msg[0];
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
+
+    /*
+     * Sanity checks
+     */
+    if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&
+        ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+    {
+        /* In SSLv3, the client might send a NoCertificate alert. */
+#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
+        if( ! ( ssl->minor_ver      == MBEDTLS_SSL_MINOR_VERSION_0 &&
+                ssl->out_msgtype    == MBEDTLS_SSL_MSG_ALERT       &&
+                ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
+#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        }
+    }
+
+    if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+        hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
+        ssl->handshake == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake != NULL &&
         ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
     {
-        ; /* Skip special handshake treatment when resending */
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
-    else
 #endif
+
+    /* Double-check that we did not exceed the bounds
+     * of the outgoing record buffer.
+     * This should never fail as the various message
+     * writing functions must obey the bounds of the
+     * outgoing record buffer, but better be safe.
+     *
+     * Note: We deliberately do not check for the MTU or MFL here.
+     */
+    if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
+                                    "size %u, maximum %u",
+                                    (unsigned) ssl->out_msglen,
+                                    (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /*
+     * Fill handshake headers
+     */
     if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
     {
-        out_msg_type = ssl->out_msg[0];
-
-        if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
-            ssl->handshake == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
-        ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >>  8 );
-        ssl->out_msg[3] = (unsigned char)( ( len - 4 )       );
+        ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
+        ssl->out_msg[2] = (unsigned char)( hs_len >>  8 );
+        ssl->out_msg[3] = (unsigned char)( hs_len       );
 
         /*
          * DTLS has additional fields in the Handshake layer,
@@ -2980,17 +3259,16 @@
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
                               "size %u, maximum %u",
-                               (unsigned) ( ssl->in_hslen - 4 ),
+                               (unsigned) ( hs_len ),
                                (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
                 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
             }
 
-            memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 );
+            memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
             ssl->out_msglen += 8;
-            len += 8;
 
             /* Write message_seq and update it, except for HelloRequest */
-            if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+            if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
             {
                 ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
                 ssl->out_msg[5] = ( ssl->handshake->out_msg_seq      ) & 0xFF;
@@ -3002,23 +3280,23 @@
                 ssl->out_msg[5] = 0;
             }
 
-            /* We don't fragment, so frag_offset = 0 and frag_len = len */
+            /* Handshake hashes are computed without fragmentation,
+             * so set frag_offset = 0 and frag_len = hs_len for now */
             memset( ssl->out_msg + 6, 0x00, 3 );
             memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
         }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-        if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
-            ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
+        /* Update running hashes of handshake messages seen */
+        if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+            ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
     }
 
-    /* Save handshake and CCS messages for resending */
+    /* Either send now, or just save to be sent (and resent) later */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake != NULL &&
-        ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING &&
-        ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ||
-          ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) )
+        ( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
+          hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) )
     {
         if( ( ret = ssl_flight_append( ssl ) ) != 0 )
         {
@@ -3026,7 +3304,40 @@
             return( ret );
         }
     }
+    else
 #endif
+    {
+        if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+            return( ret );
+        }
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
+
+    return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+
+/*
+ * Write current record.
+ *
+ * Uses:
+ *  - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
+ *  - ssl->out_msglen: length of the record content (excl headers)
+ *  - ssl->out_msg: record content
+ */
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
+{
+    int ret, done = 0;
+    size_t len = ssl->out_msglen;
+    uint8_t flush = force_flush;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->transform_out != NULL &&
@@ -3060,10 +3371,14 @@
 #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
     if( !done )
     {
+        unsigned i;
+        size_t protected_record_size;
+
         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                            ssl->conf->transport, ssl->out_hdr + 1 );
 
+        memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
         ssl->out_len[0] = (unsigned char)( len >> 8 );
         ssl->out_len[1] = (unsigned char)( len      );
 
@@ -3080,18 +3395,76 @@
             ssl->out_len[1] = (unsigned char)( len      );
         }
 
-        ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen;
+        protected_record_size = len + mbedtls_ssl_hdr_len( ssl );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        /* In case of DTLS, double-check that we don't exceed
+         * the remaining space in the datagram. */
+        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+        {
+            ret = ssl_get_remaining_space_in_datagram( ssl );
+            if( ret < 0 )
+                return( ret );
+
+            if( protected_record_size > (size_t) ret )
+            {
+                /* Should never happen */
+                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            }
+        }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
-                            "version = [%d:%d], msglen = %d",
-                       ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
-                     ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) );
+                                    "version = [%d:%d], msglen = %d",
+                                    ssl->out_hdr[0], ssl->out_hdr[1],
+                                    ssl->out_hdr[2], len ) );
 
         MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
-                       ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen );
+                               ssl->out_hdr, protected_record_size );
+
+        ssl->out_left += protected_record_size;
+        ssl->out_hdr  += protected_record_size;
+        ssl_update_out_pointers( ssl, ssl->transform_out );
+
+        for( i = 8; i > ssl_ep_len( ssl ); i-- )
+            if( ++ssl->cur_out_ctr[i - 1] != 0 )
+                break;
+
+        /* The loop goes to its end iff the counter is wrapping */
+        if( i == ssl_ep_len( ssl ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+            return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+        }
     }
 
-    if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        flush == SSL_DONT_FORCE_FLUSH )
+    {
+        size_t remaining;
+        ret = ssl_get_remaining_payload_in_datagram( ssl );
+        if( ret < 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
+                                   ret );
+            return( ret );
+        }
+
+        remaining = (size_t) ret;
+        if( remaining == 0 )
+        {
+            flush = SSL_FORCE_FLUSH;
+        }
+        else
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    if( ( flush == SSL_FORCE_FLUSH ) &&
+        ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
         return( ret );
@@ -3103,6 +3476,52 @@
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
+{
+    if( ssl->in_msglen < ssl->in_hslen ||
+        memcmp( ssl->in_msg + 6, "\0\0\0",        3 ) != 0 ||
+        memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
+    {
+        return( 1 );
+    }
+    return( 0 );
+}
+
+static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
+{
+    return( ( ssl->in_msg[9] << 16  ) |
+            ( ssl->in_msg[10] << 8  ) |
+              ssl->in_msg[11] );
+}
+
+static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
+{
+    return( ( ssl->in_msg[6] << 16 ) |
+            ( ssl->in_msg[7] << 8  ) |
+              ssl->in_msg[8] );
+}
+
+static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
+{
+    uint32_t msg_len, frag_off, frag_len;
+
+    msg_len  = ssl_get_hs_total_len( ssl );
+    frag_off = ssl_get_hs_frag_off( ssl );
+    frag_len = ssl_get_hs_frag_len( ssl );
+
+    if( frag_off > msg_len )
+        return( -1 );
+
+    if( frag_len > msg_len - frag_off )
+        return( -1 );
+
+    if( frag_len + 12 > ssl->in_msglen )
+        return( -1 );
+
+    return( 0 );
+}
+
 /*
  * Mark bits in bitmask (used for DTLS HS reassembly)
  */
@@ -3164,162 +3583,30 @@
     return( 0 );
 }
 
-/*
- * Reassemble fragmented DTLS handshake messages.
- *
- * Use a temporary buffer for reassembly, divided in two parts:
- * - the first holds the reassembled message (including handshake header),
- * - the second holds a bitmask indicating which parts of the message
- *   (excluding headers) have been received so far.
- */
-static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
+/* msg_len does not include the handshake header */
+static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
+                                              unsigned add_bitmap )
 {
-    unsigned char *msg, *bitmask;
-    size_t frag_len, frag_off;
-    size_t msg_len = ssl->in_hslen - 12; /* Without headers */
+    size_t alloc_len;
 
-    if( ssl->handshake == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) );
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-    }
+    alloc_len  = 12;                                 /* Handshake header */
+    alloc_len += msg_len;                            /* Content buffer   */
 
-    /*
-     * For first fragment, check size and allocate buffer
-     */
-    if( ssl->handshake->hs_msg == NULL )
-    {
-        size_t alloc_len;
+    if( add_bitmap )
+        alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap       */
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
-                            msg_len ) );
-
-        if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
-
-        /* The bitmask needs one bit per byte of message excluding header */
-        alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 );
-
-        ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len );
-        if( ssl->handshake->hs_msg == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) );
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-        }
-
-        /* Prepare final header: copy msg_type, length and message_seq,
-         * then add standardised fragment_offset and fragment_length */
-        memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 );
-        memset( ssl->handshake->hs_msg + 6, 0, 3 );
-        memcpy( ssl->handshake->hs_msg + 9,
-                ssl->handshake->hs_msg + 1, 3 );
-    }
-    else
-    {
-        /* Make sure msg_type and length are consistent */
-        if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-        }
-    }
-
-    msg = ssl->handshake->hs_msg + 12;
-    bitmask = msg + msg_len;
-
-    /*
-     * Check and copy current fragment
-     */
-    frag_off = ( ssl->in_msg[6]  << 16 ) |
-               ( ssl->in_msg[7]  << 8  ) |
-                 ssl->in_msg[8];
-    frag_len = ( ssl->in_msg[9]  << 16 ) |
-               ( ssl->in_msg[10] << 8  ) |
-                 ssl->in_msg[11];
-
-    if( frag_off + frag_len > msg_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d",
-                          frag_off, frag_len, msg_len ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-    }
-
-    if( frag_len + 12 > ssl->in_msglen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d",
-                          frag_len, ssl->in_msglen ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
-                        frag_off, frag_len ) );
-
-    memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
-    ssl_bitmask_set( bitmask, frag_off, frag_len );
-
-    /*
-     * Do we have the complete message by now?
-     * If yes, finalize it, else ask to read the next record.
-     */
-    if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
-        return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
-
-    if( frag_len + 12 < ssl->in_msglen )
-    {
-        /*
-         * We'got more handshake messages in the same record.
-         * This case is not handled now because no know implementation does
-         * that and it's hard to test, so we prefer to fail cleanly for now.
-         */
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) );
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-    }
-
-    if( ssl->in_left > ssl->next_record_offset )
-    {
-        /*
-         * We've got more data in the buffer after the current record,
-         * that we don't want to overwrite. Move it before writing the
-         * reassembled message, and adjust in_left and next_record_offset.
-         */
-        unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset;
-        unsigned char *new_remain = ssl->in_msg + ssl->in_hslen;
-        size_t remain_len = ssl->in_left - ssl->next_record_offset;
-
-        /* First compute and check new lengths */
-        ssl->next_record_offset = new_remain - ssl->in_hdr;
-        ssl->in_left = ssl->next_record_offset + remain_len;
-
-        if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN -
-                           (size_t)( ssl->in_hdr - ssl->in_buf ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-        }
-
-        memmove( new_remain, cur_remain, remain_len );
-    }
-
-    memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
-
-    mbedtls_free( ssl->handshake->hs_msg );
-    ssl->handshake->hs_msg = NULL;
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message",
-                   ssl->in_msg, ssl->in_hslen );
-
-    return( 0 );
+    return( alloc_len );
 }
+
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
+{
+    return( ( ssl->in_msg[1] << 16 ) |
+            ( ssl->in_msg[2] << 8  ) |
+              ssl->in_msg[3] );
+}
+
 int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
 {
     if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
@@ -3329,10 +3616,7 @@
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
     }
 
-    ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + (
-                    ( ssl->in_msg[1] << 16 ) |
-                    ( ssl->in_msg[2] << 8  ) |
-                      ssl->in_msg[3] );
+    ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
                         " %d, type = %d, hslen = %d",
@@ -3344,12 +3628,26 @@
         int ret;
         unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
 
+        if( ssl_check_hs_header( ssl ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+
         if( ssl->handshake != NULL &&
             ( ( ssl->state   != MBEDTLS_SSL_HANDSHAKE_OVER &&
                 recv_msg_seq != ssl->handshake->in_msg_seq ) ||
               ( ssl->state  == MBEDTLS_SSL_HANDSHAKE_OVER &&
                 ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
         {
+            if( recv_msg_seq > ssl->handshake->in_msg_seq )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
+                                            recv_msg_seq,
+                                            ssl->handshake->in_msg_seq ) );
+                return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+            }
+
             /* Retransmit only on last message from previous flight, to avoid
              * too many retransmissions.
              * Besides, No sane server ever retransmits HelloVerifyRequest */
@@ -3379,20 +3677,14 @@
         }
         /* Wait until message completion to increment in_msg_seq */
 
-        /* Reassemble if current message is fragmented or reassembly is
-         * already in progress */
-        if( ssl->in_msglen < ssl->in_hslen ||
-            memcmp( ssl->in_msg + 6, "\0\0\0",        3 ) != 0 ||
-            memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ||
-            ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) )
+        /* Message reassembly is handled alongside buffering of future
+         * messages; the commonality is that both handshake fragments and
+         * future messages cannot be forwarded immediately to the
+         * handshake logic layer. */
+        if( ssl_hs_is_proper_fragment( ssl ) == 1 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
-
-            if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret );
-                return( ret );
-            }
+            return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
         }
     }
     else
@@ -3409,9 +3701,9 @@
 
 void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
 {
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
-        ssl->handshake != NULL )
+    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
     {
         ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
     }
@@ -3421,7 +3713,29 @@
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake != NULL )
     {
-        ssl->handshake->in_msg_seq++;
+        unsigned offset;
+        mbedtls_ssl_hs_buffer *hs_buf;
+
+        /* Increment handshake sequence number */
+        hs->in_msg_seq++;
+
+        /*
+         * Clear up handshake buffering and reassembly structure.
+         */
+
+        /* Free first entry */
+        ssl_buffering_free_slot( ssl, 0 );
+
+        /* Shift all other entries */
+        for( offset = 0, hs_buf = &hs->buffering.hs[0];
+             offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
+             offset++, hs_buf++ )
+        {
+            *hs_buf = *(hs_buf + 1);
+        }
+
+        /* Create a fresh last entry */
+        memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
     }
 #endif
 }
@@ -3822,7 +4136,16 @@
             }
             else
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+            {
+                /* Consider buffering the record. */
+                if( rec_epoch == (unsigned int) ssl->in_epoch + 1 )
+                {
+                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
+                    return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+                }
+
                 return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+            }
         }
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
@@ -3835,15 +4158,6 @@
         }
 #endif
 
-        /* Drop unexpected ChangeCipherSpec messages */
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
-            ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
-            ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
-            return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
-        }
-
         /* Drop unexpected ApplicationData records,
          * except at the beginning of renegotiations */
         if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
@@ -3980,7 +4294,14 @@
  * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
  *
  */
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
+
+/* Helper functions for mbedtls_ssl_read_record(). */
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
+
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+                             unsigned update_hs_digest )
 {
     int ret;
 
@@ -3990,17 +4311,53 @@
     {
         do {
 
-            do ret = mbedtls_ssl_read_record_layer( ssl );
-            while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
+            ret = ssl_consume_current_message( ssl );
             if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
                 return( ret );
+
+            if( ssl_record_is_in_progress( ssl ) == 0 )
+            {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+                int have_buffered = 0;
+
+                /* We only check for buffered messages if the
+                 * current datagram is fully consumed. */
+                if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+                    ssl_next_record_is_in_datagram( ssl ) == 0 )
+                {
+                    if( ssl_load_buffered_message( ssl ) == 0 )
+                        have_buffered = 1;
+                }
+
+                if( have_buffered == 0 )
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+                {
+                    ret = ssl_get_next_record( ssl );
+                    if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
+                        continue;
+
+                    if( ret != 0 )
+                    {
+                        MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
+                        return( ret );
+                    }
+                }
             }
 
             ret = mbedtls_ssl_handle_message_type( ssl );
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+            if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+            {
+                /* Buffer future message */
+                ret = ssl_buffer_message( ssl );
+                if( ret != 0 )
+                    return( ret );
+
+                ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+            }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
         } while( MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||
                  MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
 
@@ -4010,14 +4367,15 @@
             return( ret );
         }
 
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+            update_hs_digest == 1 )
         {
             mbedtls_ssl_update_handshake_status( ssl );
         }
     }
     else
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
         ssl->keep_current_message = 0;
     }
 
@@ -4026,13 +4384,350 @@
     return( 0 );
 }
 
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
 {
-    int ret;
+    if( ssl->in_left > ssl->next_record_offset )
+        return( 1 );
 
+    return( 0 );
+}
+
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
+{
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    mbedtls_ssl_hs_buffer * hs_buf;
+    int ret = 0;
+
+    if( hs == NULL )
+        return( -1 );
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+
+    if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
+        ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+    {
+        /* Check if we have seen a ChangeCipherSpec before.
+         * If yes, synthesize a CCS record. */
+        if( !hs->buffering.seen_ccs )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
+            ret = -1;
+            goto exit;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
+        ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+        ssl->in_msglen = 1;
+        ssl->in_msg[0] = 1;
+
+        /* As long as they are equal, the exact value doesn't matter. */
+        ssl->in_left            = 0;
+        ssl->next_record_offset = 0;
+
+        hs->buffering.seen_ccs = 0;
+        goto exit;
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    /* Debug only */
+    {
+        unsigned offset;
+        for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+        {
+            hs_buf = &hs->buffering.hs[offset];
+            if( hs_buf->is_valid == 1 )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
+                            hs->in_msg_seq + offset,
+                            hs_buf->is_complete ? "fully" : "partially" ) );
+            }
+        }
+    }
+#endif /* MBEDTLS_DEBUG_C */
+
+    /* Check if we have buffered and/or fully reassembled the
+     * next handshake message. */
+    hs_buf = &hs->buffering.hs[0];
+    if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
+    {
+        /* Synthesize a record containing the buffered HS message. */
+        size_t msg_len = ( hs_buf->data[1] << 16 ) |
+                         ( hs_buf->data[2] << 8  ) |
+                           hs_buf->data[3];
+
+        /* Double-check that we haven't accidentally buffered
+         * a message that doesn't fit into the input buffer. */
+        if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
+        MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
+                               hs_buf->data, msg_len + 12 );
+
+        ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+        ssl->in_hslen   = msg_len + 12;
+        ssl->in_msglen  = msg_len + 12;
+        memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
+
+        ret = 0;
+        goto exit;
+    }
+    else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
+                                    hs->in_msg_seq ) );
+    }
+
+    ret = -1;
+
+exit:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
+    return( ret );
+}
+
+static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
+                                  size_t desired )
+{
+    int offset;
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
+                                (unsigned) desired ) );
+
+    /* Get rid of future records epoch first, if such exist. */
+    ssl_free_buffered_record( ssl );
+
+    /* Check if we have enough space available now. */
+    if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                     hs->buffering.total_bytes_buffered ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
+        return( 0 );
+    }
+
+    /* We don't have enough space to buffer the next expected handshake
+     * message. Remove buffers used for future messages to gain space,
+     * starting with the most distant one. */
+    for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
+         offset >= 0; offset-- )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
+                                    offset ) );
+
+        ssl_buffering_free_slot( ssl, (uint8_t) offset );
+
+        /* Check if we have enough space available now. */
+        if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                         hs->buffering.total_bytes_buffered ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
+            return( 0 );
+        }
+    }
+
+    return( -1 );
+}
+
+static int ssl_buffer_message( mbedtls_ssl_context *ssl )
+{
+    int ret = 0;
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+    if( hs == NULL )
+        return( 0 );
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
+
+    switch( ssl->in_msgtype )
+    {
+        case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
+
+            hs->buffering.seen_ccs = 1;
+            break;
+
+        case MBEDTLS_SSL_MSG_HANDSHAKE:
+        {
+            unsigned recv_msg_seq_offset;
+            unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+            mbedtls_ssl_hs_buffer *hs_buf;
+            size_t msg_len = ssl->in_hslen - 12;
+
+            /* We should never receive an old handshake
+             * message - double-check nonetheless. */
+            if( recv_msg_seq < ssl->handshake->in_msg_seq )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            }
+
+            recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
+            if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+            {
+                /* Silently ignore -- message too far in the future */
+                MBEDTLS_SSL_DEBUG_MSG( 2,
+                 ( "Ignore future HS message with sequence number %u, "
+                   "buffering window %u - %u",
+                   recv_msg_seq, ssl->handshake->in_msg_seq,
+                   ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
+
+                goto exit;
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
+                                        recv_msg_seq, recv_msg_seq_offset ) );
+
+            hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
+
+            /* Check if the buffering for this seq nr has already commenced. */
+            if( !hs_buf->is_valid )
+            {
+                size_t reassembly_buf_sz;
+
+                hs_buf->is_fragmented =
+                    ( ssl_hs_is_proper_fragment( ssl ) == 1 );
+
+                /* We copy the message back into the input buffer
+                 * after reassembly, so check that it's not too large.
+                 * This is an implementation-specific limitation
+                 * and not one from the standard, hence it is not
+                 * checked in ssl_check_hs_header(). */
+                if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+                {
+                    /* Ignore message */
+                    goto exit;
+                }
+
+                /* Check if we have enough space to buffer the message. */
+                if( hs->buffering.total_bytes_buffered >
+                    MBEDTLS_SSL_DTLS_MAX_BUFFERING )
+                {
+                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+                }
+
+                reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
+                                                       hs_buf->is_fragmented );
+
+                if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                                          hs->buffering.total_bytes_buffered ) )
+                {
+                    if( recv_msg_seq_offset > 0 )
+                    {
+                        /* If we can't buffer a future message because
+                         * of space limitations -- ignore. */
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+                             (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                        goto exit;
+                    }
+                    else
+                    {
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+                             (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                    }
+
+                    if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
+                    {
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
+                             (unsigned) msg_len,
+                             (unsigned) reassembly_buf_sz,
+                             MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                        ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+                        goto exit;
+                    }
+                }
+
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
+                                            msg_len ) );
+
+                hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
+                if( hs_buf->data == NULL )
+                {
+                    ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+                    goto exit;
+                }
+                hs_buf->data_len = reassembly_buf_sz;
+
+                /* Prepare final header: copy msg_type, length and message_seq,
+                 * then add standardised fragment_offset and fragment_length */
+                memcpy( hs_buf->data, ssl->in_msg, 6 );
+                memset( hs_buf->data + 6, 0, 3 );
+                memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
+
+                hs_buf->is_valid = 1;
+
+                hs->buffering.total_bytes_buffered += reassembly_buf_sz;
+            }
+            else
+            {
+                /* Make sure msg_type and length are consistent */
+                if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
+                {
+                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
+                    /* Ignore */
+                    goto exit;
+                }
+            }
+
+            if( !hs_buf->is_complete )
+            {
+                size_t frag_len, frag_off;
+                unsigned char * const msg = hs_buf->data + 12;
+
+                /*
+                 * Check and copy current fragment
+                 */
+
+                /* Validation of header fields already done in
+                 * mbedtls_ssl_prepare_handshake_record(). */
+                frag_off = ssl_get_hs_frag_off( ssl );
+                frag_len = ssl_get_hs_frag_len( ssl );
+
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
+                                            frag_off, frag_len ) );
+                memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
+
+                if( hs_buf->is_fragmented )
+                {
+                    unsigned char * const bitmask = msg + msg_len;
+                    ssl_bitmask_set( bitmask, frag_off, frag_len );
+                    hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
+                                                               msg_len ) == 0 );
+                }
+                else
+                {
+                    hs_buf->is_complete = 1;
+                }
+
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
+                                   hs_buf->is_complete ? "" : "not yet " ) );
+            }
+
+            break;
+        }
+
+        default:
+            /* We don't buffer other types of messages. */
+            break;
+    }
+
+exit:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
+    return( ret );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
+{
     /*
-     * Step A
-     *
      * Consume last content-layer message and potentially
      * update in_msglen which keeps track of the contents'
      * consumption state.
@@ -4114,20 +4809,161 @@
         ssl->in_msglen = 0;
     }
 
-    /*
-     * Step B
-     *
-     * Fetch and decode new record if current one is fully consumed.
-     *
-     */
+    return( 0 );
+}
 
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
+{
     if( ssl->in_msglen > 0 )
+        return( 1 );
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
+{
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    if( hs == NULL )
+        return;
+
+    if( hs->buffering.future_record.data != NULL )
     {
-        /* There's something left to be processed in the current record. */
+        hs->buffering.total_bytes_buffered -=
+            hs->buffering.future_record.len;
+
+        mbedtls_free( hs->buffering.future_record.data );
+        hs->buffering.future_record.data = NULL;
+    }
+}
+
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
+{
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    unsigned char * rec;
+    size_t rec_len;
+    unsigned rec_epoch;
+
+    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+        return( 0 );
+
+    if( hs == NULL )
+        return( 0 );
+
+    rec       = hs->buffering.future_record.data;
+    rec_len   = hs->buffering.future_record.len;
+    rec_epoch = hs->buffering.future_record.epoch;
+
+    if( rec == NULL )
+        return( 0 );
+
+    /* Only consider loading future records if the
+     * input buffer is empty. */
+    if( ssl_next_record_is_in_datagram( ssl ) == 1 )
+        return( 0 );
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
+
+    if( rec_epoch != ssl->in_epoch )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
+
+    /* Double-check that the record is not too large */
+    if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN -
+        (size_t)( ssl->in_hdr - ssl->in_buf ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    memcpy( ssl->in_hdr, rec, rec_len );
+    ssl->in_left = rec_len;
+    ssl->next_record_offset = 0;
+
+    ssl_free_buffered_record( ssl );
+
+exit:
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
+    return( 0 );
+}
+
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl )
+{
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    size_t const rec_hdr_len = 13;
+    size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen;
+
+    /* Don't buffer future records outside handshakes. */
+    if( hs == NULL )
+        return( 0 );
+
+    /* Only buffer handshake records (we are only interested
+     * in Finished messages). */
+    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
+        return( 0 );
+
+    /* Don't buffer more than one future epoch record. */
+    if( hs->buffering.future_record.data != NULL )
+        return( 0 );
+
+    /* Don't buffer record if there's not enough buffering space remaining. */
+    if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                         hs->buffering.total_bytes_buffered ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+                        (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                        (unsigned) hs->buffering.total_bytes_buffered ) );
         return( 0 );
     }
 
-    /* Current record either fully processed or to be discarded. */
+    /* Buffer record */
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
+                                ssl->in_epoch + 1 ) );
+    MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr,
+                           rec_hdr_len + ssl->in_msglen );
+
+    /* ssl_parse_record_header() only considers records
+     * of the next epoch as candidates for buffering. */
+    hs->buffering.future_record.epoch = ssl->in_epoch + 1;
+    hs->buffering.future_record.len   = total_buf_sz;
+
+    hs->buffering.future_record.data =
+        mbedtls_calloc( 1, hs->buffering.future_record.len );
+    if( hs->buffering.future_record.data == NULL )
+    {
+        /* If we run out of RAM trying to buffer a
+         * record from the next epoch, just ignore. */
+        return( 0 );
+    }
+
+    memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz );
+
+    hs->buffering.total_bytes_buffered += total_buf_sz;
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_get_next_record( mbedtls_ssl_context *ssl )
+{
+    int ret;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    /* We might have buffered a future record; if so,
+     * and if the epoch matches now, load it.
+     * On success, this call will set ssl->in_left to
+     * the length of the buffered record, so that
+     * the calls to ssl_fetch_input() below will
+     * essentially be no-ops. */
+    ret = ssl_load_buffered_record( ssl );
+    if( ret != 0 )
+        return( ret );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
     if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
     {
@@ -4141,6 +4977,16 @@
         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
             ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
         {
+            if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+            {
+                ret = ssl_buffer_future_record( ssl );
+                if( ret != 0 )
+                    return( ret );
+
+                /* Fall through to handling of unexpected records */
+                ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+            }
+
             if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
             {
                 /* Skip unexpected record (but not whole datagram) */
@@ -4272,6 +5118,39 @@
         }
     }
 
+    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+    {
+        if( ssl->in_msglen != 1 )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
+                           ssl->in_msglen ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->in_msg[0] != 1 )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
+                                        ssl->in_msg[0] ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+            ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC    &&
+            ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+        {
+            if( ssl->handshake == NULL )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
+                return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
+            return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+        }
+#endif
+    }
+
     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
     {
         if( ssl->in_msglen != 2 )
@@ -4373,7 +5252,7 @@
     ssl->out_msg[0] = level;
     ssl->out_msg[1] = message;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
         return( ret );
@@ -4542,9 +5421,9 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -4553,60 +5432,16 @@
     return( ret );
 }
 
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+/*
+ * Once the certificate message is read, parse it into a cert chain and
+ * perform basic checks, but leave actual verification to the caller
+ */
+static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
 {
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    int ret;
     size_t i, n;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
-    int authmode = ssl->conf->authmode;
     uint8_t alert;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
-        authmode = ssl->handshake->sni_authmode;
-#endif
-
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-        authmode == MBEDTLS_SSL_VERIFY_NONE )
-    {
-        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-        ssl->state++;
-        return( 0 );
-    }
-#endif
-
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
-    {
-        /* mbedtls_ssl_read_record may have sent an alert already. We
-           let it decide whether to alert. */
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    ssl->state++;
-
 #if defined(MBEDTLS_SSL_SRV_C)
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
     /*
@@ -4626,10 +5461,7 @@
                one. The client should know what's going on, so we
                don't send an alert. */
             ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
-            if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
-                return( 0 );
-            else
-                return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+            return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
@@ -4650,10 +5482,7 @@
                one. The client should know what's going on, so we
                don't send an alert. */
             ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
-            if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
-                return( 0 );
-            else
-                return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+            return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -4803,6 +5632,94 @@
     }
 #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
 
+    return( 0 );
+}
+
+int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+{
+    int ret;
+    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+          ssl->transform_negotiate->ciphersuite_info;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+                       ? ssl->handshake->sni_authmode
+                       : ssl->conf->authmode;
+#else
+    const int authmode = ssl->conf->authmode;
+#endif
+    void *rs_ctx = NULL;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+        authmode == MBEDTLS_SSL_VERIFY_NONE )
+    {
+        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+
+        ssl->state++;
+        return( 0 );
+    }
+#endif
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
+    {
+        goto crt_verify;
+    }
+#endif
+
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+    {
+        /* mbedtls_ssl_read_record may have sent an alert already. We
+           let it decide whether to alert. */
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
+    {
+#if defined(MBEDTLS_SSL_SRV_C)
+        if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
+            authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+        {
+            ret = 0;
+        }
+#endif
+
+        ssl->state++;
+        return( ret );
+    }
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    if( ssl->handshake->ecrs_enabled)
+        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+
+crt_verify:
+    if( ssl->handshake->ecrs_enabled)
+        rs_ctx = &ssl->handshake->ecrs_ctx;
+#endif
+
     if( authmode != MBEDTLS_SSL_VERIFY_NONE )
     {
         mbedtls_x509_crt *ca_chain;
@@ -4824,19 +5741,24 @@
         /*
          * Main check: verify certificate
          */
-        ret = mbedtls_x509_crt_verify_with_profile(
+        ret = mbedtls_x509_crt_verify_restartable(
                                 ssl->session_negotiate->peer_cert,
                                 ca_chain, ca_crl,
                                 ssl->conf->cert_profile,
                                 ssl->hostname,
                                &ssl->session_negotiate->verify_result,
-                                ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+                                ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
 
         if( ret != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
         }
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+        if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+            return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
+#endif
+
         /*
          * Secondary checks: always done, but change 'ret' only if it was 0
          */
@@ -4889,6 +5811,8 @@
 
         if( ret != 0 )
         {
+            uint8_t alert;
+
             /* The certificate may have been rejected for several reasons.
                Pick one and send the corresponding alert. Which alert to send
                may be a subject of debate in some cases. */
@@ -4931,6 +5855,8 @@
 #endif /* MBEDTLS_DEBUG_C */
     }
 
+    ssl->state++;
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
 
     return( ret );
@@ -4955,9 +5881,9 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -4972,7 +5898,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -4986,13 +5912,8 @@
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
-    if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
-    }
+    /* CCS records are only accepted if they have length 1 and content '1',
+     * so we don't need to check this here. */
 
     /*
      * Switch to our negotiated transform and session parameters for inbound
@@ -5022,16 +5943,7 @@
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     memset( ssl->in_ctr, 0, 8 );
 
-    /*
-     * Set the in_msg pointer to the correct location based on IV length
-     */
-    if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-    {
-        ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen -
-                      ssl->transform_negotiate->fixed_ivlen;
-    }
-    else
-        ssl->in_msg = ssl->in_iv;
+    ssl_update_in_pointers( ssl, ssl->transform_negotiate );
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_activate != NULL )
@@ -5482,16 +6394,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
 
-    /*
-     * Set the out_msg pointer to the correct location based on IV length
-     */
-    if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-    {
-        ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen -
-                       ssl->transform_negotiate->fixed_ivlen;
-    }
-    else
-        ssl->out_msg = ssl->out_iv;
+    ssl_update_out_pointers( ssl, ssl->transform_negotiate );
 
     ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
 
@@ -5543,14 +6446,14 @@
 
         /* Remember current epoch settings for resending */
         ssl->handshake->alt_transform_out = ssl->transform_out;
-        memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 );
+        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
 
         /* Set sequence_number to zero */
-        memset( ssl->out_ctr + 2, 0, 6 );
+        memset( ssl->cur_out_ctr + 2, 0, 6 );
 
         /* Increment epoch */
         for( i = 2; i > 0; i-- )
-            if( ++ssl->out_ctr[i - 1] != 0 )
+            if( ++ssl->cur_out_ctr[i - 1] != 0 )
                 break;
 
         /* The loop goes to its end iff the counter is wrapping */
@@ -5562,7 +6465,7 @@
     }
     else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->out_ctr, 0, 8 );
+    memset( ssl->cur_out_ctr, 0, 8 );
 
     ssl->transform_out = ssl->transform_negotiate;
     ssl->session_out = ssl->session_negotiate;
@@ -5583,12 +6486,21 @@
         mbedtls_ssl_send_flight_completed( ssl );
 #endif
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+        return( ret );
+    }
+#endif
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
 
     return( 0 );
@@ -5610,7 +6522,7 @@
 
     ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
 
-    if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
         return( ret );
@@ -5722,6 +6634,10 @@
 #endif
 #endif
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
+#endif
+
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
     handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
 #endif
@@ -5841,6 +6757,78 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
 
+/* Once ssl->out_hdr as the address of the beginning of the
+ * next outgoing record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ *       (entering MAC computation) in the 8 bytes before ssl->out_hdr,
+ *       and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+                                     mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+    {
+        ssl->out_ctr = ssl->out_hdr +  3;
+        ssl->out_len = ssl->out_hdr + 11;
+        ssl->out_iv  = ssl->out_hdr + 13;
+    }
+    else
+#endif
+    {
+        ssl->out_ctr = ssl->out_hdr - 8;
+        ssl->out_len = ssl->out_hdr + 3;
+        ssl->out_iv  = ssl->out_hdr + 5;
+    }
+
+    /* Adjust out_msg to make space for explicit IV, if used. */
+    if( transform != NULL &&
+        ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+    {
+        ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
+    }
+    else
+        ssl->out_msg = ssl->out_iv;
+}
+
+/* Once ssl->in_hdr as the address of the beginning of the
+ * next incoming record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ *       (entering MAC computation) in the 8 bytes before ssl->in_hdr,
+ *       and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+                                    mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+    {
+        ssl->in_ctr = ssl->in_hdr +  3;
+        ssl->in_len = ssl->in_hdr + 11;
+        ssl->in_iv  = ssl->in_hdr + 13;
+    }
+    else
+#endif
+    {
+        ssl->in_ctr = ssl->in_hdr - 8;
+        ssl->in_len = ssl->in_hdr + 3;
+        ssl->in_iv  = ssl->in_hdr + 5;
+    }
+
+    /* Offset in_msg from in_iv to allow space for explicit IV, if used. */
+    if( transform != NULL &&
+        ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+    {
+        ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen;
+    }
+    else
+        ssl->in_msg = ssl->in_iv;
+}
+
 /*
  * Initialize an SSL context
  */
@@ -5852,6 +6840,28 @@
 /*
  * Setup an SSL context
  */
+
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
+{
+    /* Set the incoming and outgoing record pointers. */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+    {
+        ssl->out_hdr = ssl->out_buf;
+        ssl->in_hdr  = ssl->in_buf;
+    }
+    else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    {
+        ssl->out_hdr = ssl->out_buf + 8;
+        ssl->in_hdr  = ssl->in_buf  + 8;
+    }
+
+    /* Derive other internal pointers. */
+    ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
+    ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ );
+}
+
 int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
                        const mbedtls_ssl_config *conf )
 {
@@ -5862,57 +6872,55 @@
     /*
      * Prepare base structures
      */
+
+    /* Set to NULL in case of an error condition */
+    ssl->out_buf = NULL;
+
     ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN );
     if( ssl->in_buf == NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto error;
     }
 
     ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN );
     if( ssl->out_buf == NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) );
-        mbedtls_free( ssl->in_buf );
-        ssl->in_buf = NULL;
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto error;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        ssl->out_hdr = ssl->out_buf;
-        ssl->out_ctr = ssl->out_buf +  3;
-        ssl->out_len = ssl->out_buf + 11;
-        ssl->out_iv  = ssl->out_buf + 13;
-        ssl->out_msg = ssl->out_buf + 13;
-
-        ssl->in_hdr = ssl->in_buf;
-        ssl->in_ctr = ssl->in_buf +  3;
-        ssl->in_len = ssl->in_buf + 11;
-        ssl->in_iv  = ssl->in_buf + 13;
-        ssl->in_msg = ssl->in_buf + 13;
-    }
-    else
-#endif
-    {
-        ssl->out_ctr = ssl->out_buf;
-        ssl->out_hdr = ssl->out_buf +  8;
-        ssl->out_len = ssl->out_buf + 11;
-        ssl->out_iv  = ssl->out_buf + 13;
-        ssl->out_msg = ssl->out_buf + 13;
-
-        ssl->in_ctr = ssl->in_buf;
-        ssl->in_hdr = ssl->in_buf +  8;
-        ssl->in_len = ssl->in_buf + 11;
-        ssl->in_iv  = ssl->in_buf + 13;
-        ssl->in_msg = ssl->in_buf + 13;
-    }
+    ssl_reset_in_out_pointers( ssl );
 
     if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
-        return( ret );
+        goto error;
 
     return( 0 );
+
+error:
+    mbedtls_free( ssl->in_buf );
+    mbedtls_free( ssl->out_buf );
+
+    ssl->conf = NULL;
+
+    ssl->in_buf = NULL;
+    ssl->out_buf = NULL;
+
+    ssl->in_hdr = NULL;
+    ssl->in_ctr = NULL;
+    ssl->in_len = NULL;
+    ssl->in_iv = NULL;
+    ssl->in_msg = NULL;
+
+    ssl->out_hdr = NULL;
+    ssl->out_ctr = NULL;
+    ssl->out_len = NULL;
+    ssl->out_iv = NULL;
+    ssl->out_msg = NULL;
+
+    return( ret );
 }
 
 /*
@@ -5926,6 +6934,11 @@
 {
     int ret;
 
+#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) ||     \
+    !defined(MBEDTLS_SSL_SRV_C)
+    ((void) partial);
+#endif
+
     ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
 
     /* Cancel any possibly running timer */
@@ -5942,12 +6955,10 @@
     ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;
 
     ssl->in_offt = NULL;
+    ssl_reset_in_out_pointers( ssl );
 
-    ssl->in_msg = ssl->in_buf + 13;
     ssl->in_msgtype = 0;
     ssl->in_msglen = 0;
-    if( partial == 0 )
-        ssl->in_left = 0;
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     ssl->next_record_offset = 0;
     ssl->in_epoch = 0;
@@ -5961,7 +6972,6 @@
 
     ssl->keep_current_message = 0;
 
-    ssl->out_msg = ssl->out_buf + 13;
     ssl->out_msgtype = 0;
     ssl->out_msglen = 0;
     ssl->out_left = 0;
@@ -5970,6 +6980,8 @@
         ssl->split_done = 0;
 #endif
 
+    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
+
     ssl->transform_in = NULL;
     ssl->transform_out = NULL;
 
@@ -5977,8 +6989,14 @@
     ssl->session_out = NULL;
 
     memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
     if( partial == 0 )
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+    {
+        ssl->in_left = 0;
         memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
+    }
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_reset != NULL )
@@ -6011,7 +7029,9 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
     if( partial == 0 )
+#endif
     {
         mbedtls_free( ssl->cli_id );
         ssl->cli_id = NULL;
@@ -6062,7 +7082,15 @@
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max )
+
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+                                       unsigned allow_packing )
+{
+    ssl->disable_datagram_packing = !allow_packing;
+}
+
+void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
+                                         uint32_t min, uint32_t max )
 {
     conf->hs_timeout_min = min;
     conf->hs_timeout_max = max;
@@ -6112,6 +7140,13 @@
     ssl->f_recv_timeout = f_recv_timeout;
 }
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu )
+{
+    ssl->mtu = mtu;
+}
+#endif
+
 void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
 {
     conf->read_timeout   = timeout;
@@ -6775,7 +7810,7 @@
 
     /*
      * In all other cases, the rest of the message can be dropped.
-     * As in ssl_read_record_layer, this needs to be adapted if
+     * As in ssl_get_next_record, this needs to be adapted if
      * we implement support for multiple alerts in single records.
      */
 
@@ -6842,8 +7877,9 @@
 
 int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
 {
-    size_t transform_expansion;
+    size_t transform_expansion = 0;
     const mbedtls_ssl_transform *transform = ssl->transform_out;
+    unsigned block_size;
 
     if( transform == NULL )
         return( (int) mbedtls_ssl_hdr_len( ssl ) );
@@ -6857,13 +7893,31 @@
     {
         case MBEDTLS_MODE_GCM:
         case MBEDTLS_MODE_CCM:
+        case MBEDTLS_MODE_CHACHAPOLY:
         case MBEDTLS_MODE_STREAM:
             transform_expansion = transform->minlen;
             break;
 
         case MBEDTLS_MODE_CBC:
-            transform_expansion = transform->maclen
-                      + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc );
+
+            block_size = mbedtls_cipher_get_block_size(
+                &transform->cipher_ctx_enc );
+
+            /* Expansion due to the addition of the MAC. */
+            transform_expansion += transform->maclen;
+
+            /* Expansion due to the addition of CBC padding;
+             * Theoretically up to 256 bytes, but we never use
+             * more than the block size of the underlying cipher. */
+            transform_expansion += block_size;
+
+            /* For TLS 1.1 or higher, an explicit IV is added
+             * after the record header. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+                transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
             break;
 
         default:
@@ -6884,19 +7938,89 @@
      */
     max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
 
-    /*
-     * Check if a smaller max length was negotiated
-     */
+    /* Check if a smaller max length was negotiated */
     if( ssl->session_out != NULL &&
         ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
     {
         max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
     }
 
-    return max_len;
+    /* During a handshake, use the value being negotiated */
+    if( ssl->session_negotiate != NULL &&
+        ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len )
+    {
+        max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
+    }
+
+    return( max_len );
 }
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
+{
+    /* Return unlimited mtu for client hello messages to avoid fragmentation. */
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+        ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
+          ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
+        return ( 0 );
+
+    if( ssl->handshake == NULL || ssl->handshake->mtu == 0 )
+        return( ssl->mtu );
+
+    if( ssl->mtu == 0 )
+        return( ssl->handshake->mtu );
+
+    return( ssl->mtu < ssl->handshake->mtu ?
+            ssl->mtu : ssl->handshake->mtu );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl )
+{
+    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+    !defined(MBEDTLS_SSL_PROTO_DTLS)
+    (void) ssl;
+#endif
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+    if( max_len > mfl )
+        max_len = mfl;
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl_get_current_mtu( ssl ) != 0 )
+    {
+        const size_t mtu = ssl_get_current_mtu( ssl );
+        const int ret = mbedtls_ssl_get_record_expansion( ssl );
+        const size_t overhead = (size_t) ret;
+
+        if( ret < 0 )
+            return( ret );
+
+        if( mtu <= overhead )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) );
+            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        if( max_len > mtu - overhead )
+            max_len = mtu - overhead;
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) &&        \
+    !defined(MBEDTLS_SSL_PROTO_DTLS)
+    ((void) ssl);
+#endif
+
+    return( (int) max_len );
+}
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl )
 {
@@ -6984,9 +8108,9 @@
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_REQUEST;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
         return( ret );
     }
 
@@ -7116,7 +8240,7 @@
 
     in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
                         ssl->conf->renego_period + ep_len, 8 - ep_len );
-    out_ctr_cmp = memcmp( ssl->out_ctr + ep_len,
+    out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
                           ssl->conf->renego_period + ep_len, 8 - ep_len );
 
     if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
@@ -7151,7 +8275,7 @@
         if( ssl->handshake != NULL &&
             ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
         {
-            if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+            if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
                 return( ret );
         }
     }
@@ -7200,7 +8324,7 @@
             ssl_set_timer( ssl, ssl->conf->read_timeout );
         }
 
-        if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+        if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
         {
             if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
                 return( 0 );
@@ -7215,7 +8339,7 @@
             /*
              * OpenSSL sends empty messages to randomize the IV
              */
-            if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+            if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
             {
                 if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
                     return( 0 );
@@ -7448,12 +8572,15 @@
 static int ssl_write_real( mbedtls_ssl_context *ssl,
                            const unsigned char *buf, size_t len )
 {
-    int ret;
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
-#else
-    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+    int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
+    const size_t max_len = (size_t) ret;
+
+    if( ret < 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
+        return( ret );
+    }
+
     if( len > max_len )
     {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -7494,7 +8621,7 @@
         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
         memcpy( ssl->out_msg, buf, len );
 
-        if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+        if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
             return( ret );
@@ -7646,6 +8773,41 @@
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_buffering_free( mbedtls_ssl_context *ssl )
+{
+    unsigned offset;
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+    if( hs == NULL )
+        return;
+
+    ssl_free_buffered_record( ssl );
+
+    for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+        ssl_buffering_free_slot( ssl, offset );
+}
+
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+                                     uint8_t slot )
+{
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+    mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
+
+    if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+        return;
+
+    if( hs_buf->is_valid == 1 )
+    {
+        hs->buffering.total_bytes_buffered -= hs_buf->data_len;
+        mbedtls_free( hs_buf->data );
+        memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+    }
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
 void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -7723,10 +8885,14 @@
     }
 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+    mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     mbedtls_free( handshake->verify_cookie );
-    mbedtls_free( handshake->hs_msg );
     ssl_flight_free( handshake->flight );
+    ssl_buffering_free( ssl );
 #endif
 
     mbedtls_platform_zeroize( handshake,
diff --git a/library/threading.c b/library/threading.c
index 7a32e67..7c90c7c 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -19,6 +19,14 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -29,6 +37,36 @@
 
 #include "mbedtls/threading.h"
 
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+
+#if !defined(_WIN32) && (defined(unix) || \
+    defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+    defined(__MACH__)))
+#include <unistd.h>
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+        * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
+       ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+         _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define THREADING_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
+             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+                _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
 #if defined(MBEDTLS_THREADING_PTHREAD)
 static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
 {
@@ -114,6 +152,9 @@
 #if defined(MBEDTLS_FS_IO)
     mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
 #endif
+#if defined(THREADING_USE_GMTIME)
+    mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
+#endif
 }
 
 /*
@@ -124,6 +165,9 @@
 #if defined(MBEDTLS_FS_IO)
     mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
 #endif
+#if defined(THREADING_USE_GMTIME)
+    mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
+#endif
 }
 #endif /* MBEDTLS_THREADING_ALT */
 
@@ -136,5 +180,8 @@
 #if defined(MBEDTLS_FS_IO)
 mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
 #endif
+#if defined(THREADING_USE_GMTIME)
+mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
+#endif
 
 #endif /* MBEDTLS_THREADING_C */
diff --git a/library/version_features.c b/library/version_features.c
index 777b603..f1798a7 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -339,6 +339,9 @@
 #if defined(MBEDTLS_ECP_NIST_OPTIM)
     "MBEDTLS_ECP_NIST_OPTIM",
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    "MBEDTLS_ECP_RESTARTABLE",
+#endif /* MBEDTLS_ECP_RESTARTABLE */
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
     "MBEDTLS_ECDSA_DETERMINISTIC",
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
diff --git a/library/x509.c b/library/x509.c
index 2e6795f..52b5b64 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -29,10 +29,6 @@
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
-/* Ensure gmtime_r is available even with -std=c99; must be included before
- * config.h, which pulls in glibc's features.h. Harmless on other platforms. */
-#define _POSIX_C_SOURCE 200112L
-
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -67,6 +63,7 @@
 #include "mbedtls/platform_time.h"
 #endif
 #if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_util.h"
 #include <time.h>
 #endif
 
@@ -901,11 +898,7 @@
     int ret = 0;
 
     tt = mbedtls_time( NULL );
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-    lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL;
-#else
-    lt = gmtime_r( &tt, &tm_buf );
-#endif
+    lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
 
     if( lt == NULL )
         ret = -1;
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 290c1eb..25aaff3 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -163,6 +163,9 @@
 static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
                                       mbedtls_md_type_t md_alg )
 {
+    if( md_alg == MBEDTLS_MD_NONE )
+        return( -1 );
+
     if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
         return( 0 );
 
@@ -176,6 +179,9 @@
 static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
                                       mbedtls_pk_type_t pk_alg )
 {
+    if( pk_alg == MBEDTLS_PK_NONE )
+        return( -1 );
+
     if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
         return( 0 );
 
@@ -208,6 +214,9 @@
     {
         const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
 
+        if( gid == MBEDTLS_ECP_DP_NONE )
+            return( -1 );
+
         if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
             return( 0 );
 
@@ -219,6 +228,23 @@
 }
 
 /*
+ * Reset (init or clear) a verify_chain
+ */
+static void x509_crt_verify_chain_reset(
+    mbedtls_x509_crt_verify_chain *ver_chain )
+{
+    size_t i;
+
+    for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
+    {
+        ver_chain->items[i].crt = NULL;
+        ver_chain->items[i].flags = -1;
+    }
+
+    ver_chain->len = 0;
+}
+
+/*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
 static int x509_get_version( unsigned char **p,
@@ -570,18 +596,14 @@
         end_ext_data = *p + len;
 
         /* Get extension ID */
-        extn_oid.tag = **p;
-
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
+        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
+                                          MBEDTLS_ASN1_OID ) ) != 0 )
             return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
 
+        extn_oid.tag = MBEDTLS_ASN1_OID;
         extn_oid.p = *p;
         *p += extn_oid.len;
 
-        if( ( end - *p ) < 1 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_OUT_OF_DATA );
-
         /* Get optional critical */
         if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
             ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
@@ -1868,7 +1890,8 @@
  * Check the signature of a certificate by its parent
  */
 static int x509_crt_check_signature( const mbedtls_x509_crt *child,
-                                     mbedtls_x509_crt *parent )
+                                     mbedtls_x509_crt *parent,
+                                     mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
     const mbedtls_md_info_t *md_info;
     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
@@ -1880,14 +1903,24 @@
         return( -1 );
     }
 
-    if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
-                child->sig_md, hash, mbedtls_md_get_size( md_info ),
-                child->sig.p, child->sig.len ) != 0 )
-    {
+    /* Skip expensive computation on obvious mismatch */
+    if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
         return( -1 );
-    }
 
-    return( 0 );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
+    {
+        return( mbedtls_pk_verify_restartable( &parent->pk,
+                    child->sig_md, hash, mbedtls_md_get_size( md_info ),
+                    child->sig.p, child->sig.len, &rs_ctx->pk ) );
+    }
+#else
+    (void) rs_ctx;
+#endif
+
+    return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
+                child->sig_md, hash, mbedtls_md_get_size( md_info ),
+                child->sig.p, child->sig.len ) );
 }
 
 /*
@@ -1934,6 +1967,7 @@
  *  1. subject name matches child's issuer
  *  2. if necessary, the CA bit is set and key usage allows signing certs
  *  3. for trusted roots, the signature is correct
+ *     (for intermediates, the signature is checked and the result reported)
  *  4. pathlen constraints are satisfied
  *
  * If there's a suitable candidate which is also time-valid, return the first
@@ -1956,23 +1990,54 @@
  * Arguments:
  *  - [in] child: certificate for which we're looking for a parent
  *  - [in] candidates: chained list of potential parents
+ *  - [out] r_parent: parent found (or NULL)
+ *  - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
  *  - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
  *         of the chain, 0 otherwise
  *  - [in] path_cnt: number of intermediates seen so far
  *  - [in] self_cnt: number of self-signed intermediates seen so far
  *         (will never be greater than path_cnt)
+ *  - [in-out] rs_ctx: context for restarting operations
  *
  * Return value:
- *  - the first suitable parent found (see above regarding time-validity)
- *  - NULL if no suitable parent was found
+ *  - 0 on success
+ *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
-static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
-                                                  mbedtls_x509_crt *candidates,
-                                                  int top,
-                                                  size_t path_cnt,
-                                                  size_t self_cnt )
+static int x509_crt_find_parent_in(
+                        mbedtls_x509_crt *child,
+                        mbedtls_x509_crt *candidates,
+                        mbedtls_x509_crt **r_parent,
+                        int *r_signature_is_good,
+                        int top,
+                        unsigned path_cnt,
+                        unsigned self_cnt,
+                        mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    mbedtls_x509_crt *parent, *badtime_parent = NULL;
+    int ret;
+    mbedtls_x509_crt *parent, *fallback_parent;
+    int signature_is_good, fallback_signature_is_good;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /* did we have something in progress? */
+    if( rs_ctx != NULL && rs_ctx->parent != NULL )
+    {
+        /* restore saved state */
+        parent = rs_ctx->parent;
+        fallback_parent = rs_ctx->fallback_parent;
+        fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
+
+        /* clear saved state */
+        rs_ctx->parent = NULL;
+        rs_ctx->fallback_parent = NULL;
+        rs_ctx->fallback_signature_is_good = 0;
+
+        /* resume where we left */
+        goto check_signature;
+    }
+#endif
+
+    fallback_parent = NULL;
+    fallback_signature_is_good = 0;
 
     for( parent = candidates; parent != NULL; parent = parent->next )
     {
@@ -1988,17 +2053,38 @@
         }
 
         /* Signature */
-        if( top && x509_crt_check_signature( child, parent ) != 0 )
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+check_signature:
+#endif
+        ret = x509_crt_check_signature( child, parent, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
         {
-            continue;
+            /* save state */
+            rs_ctx->parent = parent;
+            rs_ctx->fallback_parent = fallback_parent;
+            rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
+
+            return( ret );
         }
+#else
+        (void) ret;
+#endif
+
+        signature_is_good = ret == 0;
+        if( top && ! signature_is_good )
+            continue;
 
         /* optional time check */
         if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
             mbedtls_x509_time_is_future( &parent->valid_from ) )
         {
-            if( badtime_parent == NULL )
-                badtime_parent = parent;
+            if( fallback_parent == NULL )
+            {
+                fallback_parent = parent;
+                fallback_signature_is_good = signature_is_good;
+            }
 
             continue;
         }
@@ -2006,10 +2092,18 @@
         break;
     }
 
-    if( parent == NULL )
-        parent = badtime_parent;
+    if( parent != NULL )
+    {
+        *r_parent = parent;
+        *r_signature_is_good = signature_is_good;
+    }
+    else
+    {
+        *r_parent = fallback_parent;
+        *r_signature_is_good = fallback_signature_is_good;
+    }
 
-    return( parent );
+    return( 0 );
 }
 
 /*
@@ -2021,34 +2115,78 @@
  * Arguments:
  *  - [in] child: certificate for which we're looking for a parent, followed
  *         by a chain of possible intermediates
- *  - [in] trust_ca: locally trusted CAs
- *  - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
- *  - [in] path_cnt: number of intermediates seen so far
- *  - [in] self_cnt: number of self-signed intermediates seen so far
+ *  - [in] trust_ca: list of locally trusted certificates
+ *  - [out] parent: parent found (or NULL)
+ *  - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
+ *  - [out] signature_is_good: 1 if child signature by parent is valid, or 0
+ *  - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
+ *  - [in] self_cnt: number of self-signed certs in the chain so far
  *         (will always be no greater than path_cnt)
+ *  - [in-out] rs_ctx: context for restarting operations
  *
  * Return value:
- *  - the first suitable parent found (see find_parent_in() for "suitable")
- *  - NULL if no suitable parent was found
+ *  - 0 on success
+ *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
-static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
-                                               mbedtls_x509_crt *trust_ca,
-                                               int *parent_is_trusted,
-                                               size_t path_cnt,
-                                               size_t self_cnt )
+static int x509_crt_find_parent(
+                        mbedtls_x509_crt *child,
+                        mbedtls_x509_crt *trust_ca,
+                        mbedtls_x509_crt **parent,
+                        int *parent_is_trusted,
+                        int *signature_is_good,
+                        unsigned path_cnt,
+                        unsigned self_cnt,
+                        mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
-    mbedtls_x509_crt *parent;
+    int ret;
+    mbedtls_x509_crt *search_list;
 
-    /* Look for a parent in trusted CAs */
     *parent_is_trusted = 1;
-    parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
 
-    if( parent != NULL )
-        return( parent );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /* restore then clear saved state if we have some stored */
+    if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
+    {
+        *parent_is_trusted = rs_ctx->parent_is_trusted;
+        rs_ctx->parent_is_trusted = -1;
+    }
+#endif
 
-    /* Look for a parent upwards the chain */
-    *parent_is_trusted = 0;
-    return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
+    while( 1 ) {
+        search_list = *parent_is_trusted ? trust_ca : child->next;
+
+        ret = x509_crt_find_parent_in( child, search_list,
+                                       parent, signature_is_good,
+                                       *parent_is_trusted,
+                                       path_cnt, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+        {
+            /* save state */
+            rs_ctx->parent_is_trusted = *parent_is_trusted;
+            return( ret );
+        }
+#else
+        (void) ret;
+#endif
+
+        /* stop here if found or already in second iteration */
+        if( *parent != NULL || *parent_is_trusted == 0 )
+            break;
+
+        /* prepare second iteration */
+        *parent_is_trusted = 0;
+    }
+
+    /* extra precaution against mistakes in the caller */
+    if( parent == NULL )
+    {
+        *parent_is_trusted = 0;
+        *signature_is_good = 0;
+    }
+
+    return( 0 );
 }
 
 /*
@@ -2097,11 +2235,24 @@
  * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
  *   -> return that chain with NOT_TRUSTED set on Ciq
  *
+ * Tests for (aspects of) this function should include at least:
+ * - trusted EE
+ * - EE -> trusted root
+ * - EE -> intermedate CA -> trusted root
+ * - if relevant: EE untrusted
+ * - if relevant: EE -> intermediate, untrusted
+ * with the aspect under test checked at each relevant level (EE, int, root).
+ * For some aspects longer chains are required, but usually length 2 is
+ * enough (but length 1 is not in general).
+ *
  * Arguments:
  *  - [in] crt: the cert list EE, C1, ..., Cn
  *  - [in] trust_ca: the trusted list R1, ..., Rp
  *  - [in] ca_crl, profile: as in verify_with_profile()
- *  - [out] ver_chain, chain_len: the built and verified chain
+ *  - [out] ver_chain: the built and verified chain
+ *      Only valid when return value is 0, may contain garbage otherwise!
+ *      Restart note: need not be the same when calling again to resume.
+ *  - [in-out] rs_ctx: context for restarting operations
  *
  * Return value:
  *  - non-zero if the chain could not be fully built and examined
@@ -2113,24 +2264,50 @@
                 mbedtls_x509_crt *trust_ca,
                 mbedtls_x509_crl *ca_crl,
                 const mbedtls_x509_crt_profile *profile,
-                x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
-                size_t *chain_len )
+                mbedtls_x509_crt_verify_chain *ver_chain,
+                mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
+    /* Don't initialize any of those variables here, so that the compiler can
+     * catch potential issues with jumping ahead when restarting */
+    int ret;
     uint32_t *flags;
+    mbedtls_x509_crt_verify_chain_item *cur;
     mbedtls_x509_crt *child;
     mbedtls_x509_crt *parent;
-    int parent_is_trusted = 0;
-    int child_is_trusted = 0;
-    size_t self_cnt = 0;
+    int parent_is_trusted;
+    int child_is_trusted;
+    int signature_is_good;
+    unsigned self_cnt;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /* resume if we had an operation in progress */
+    if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
+    {
+        /* restore saved state */
+        *ver_chain = rs_ctx->ver_chain; /* struct copy */
+        self_cnt = rs_ctx->self_cnt;
+
+        /* restore derived state */
+        cur = &ver_chain->items[ver_chain->len - 1];
+        child = cur->crt;
+        flags = &cur->flags;
+
+        goto find_parent;
+    }
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
     child = crt;
-    *chain_len = 0;
+    self_cnt = 0;
+    parent_is_trusted = 0;
+    child_is_trusted = 0;
 
     while( 1 ) {
         /* Add certificate to the verification chain */
-        ver_chain[*chain_len].crt = child;
-        flags = &ver_chain[*chain_len].flags;
-        ++*chain_len;
+        cur = &ver_chain->items[ver_chain->len];
+        cur->crt = child;
+        cur->flags = 0;
+        ver_chain->len++;
+        flags = &cur->flags;
 
         /* Check time-validity (all certificates) */
         if( mbedtls_x509_time_is_past( &child->valid_to ) )
@@ -2151,15 +2328,33 @@
             *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
 
         /* Special case: EE certs that are locally trusted */
-        if( *chain_len == 1 &&
+        if( ver_chain->len == 1 &&
             x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
         {
             return( 0 );
         }
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+find_parent:
+#endif
         /* Look for a parent in trusted CAs or up the chain */
-        parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
-                                       *chain_len - 1, self_cnt );
+        ret = x509_crt_find_parent( child, trust_ca, &parent,
+                                       &parent_is_trusted, &signature_is_good,
+                                       ver_chain->len - 1, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+        {
+            /* save state */
+            rs_ctx->in_progress = x509_crt_rs_find_parent;
+            rs_ctx->self_cnt = self_cnt;
+            rs_ctx->ver_chain = *ver_chain; /* struct copy */
+
+            return( ret );
+        }
+#else
+        (void) ret;
+#endif
 
         /* No parent? We're done here */
         if( parent == NULL )
@@ -2171,7 +2366,7 @@
         /* Count intermediate self-issued (not necessarily self-signed) certs.
          * These can occur with some strategies for key rollover, see [SIRO],
          * and should be excluded from max_pathlen checks. */
-        if( *chain_len != 1 &&
+        if( ver_chain->len != 1 &&
             x509_name_cmp( &child->issuer, &child->subject ) == 0 )
         {
             self_cnt++;
@@ -2180,14 +2375,14 @@
         /* path_cnt is 0 for the first intermediate CA,
          * and if parent is trusted it's not an intermediate CA */
         if( ! parent_is_trusted &&
-            *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
+            ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
         {
             /* return immediately to avoid overflow the chain array */
             return( MBEDTLS_ERR_X509_FATAL_ERROR );
         }
 
-        /* if parent is trusted, the signature was checked by find_parent() */
-        if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
+        /* signature was checked while searching parent */
+        if( ! signature_is_good )
             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
 
         /* check size of signing key */
@@ -2205,6 +2400,7 @@
         child = parent;
         parent = NULL;
         child_is_trusted = parent_is_trusted;
+        signature_is_good = 0;
     }
 }
 
@@ -2273,21 +2469,22 @@
  */
 static int x509_crt_merge_flags_with_cb(
            uint32_t *flags,
-           x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
-           size_t chain_len,
+           const mbedtls_x509_crt_verify_chain *ver_chain,
            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
            void *p_vrfy )
 {
     int ret;
-    size_t i;
+    unsigned i;
     uint32_t cur_flags;
+    const mbedtls_x509_crt_verify_chain_item *cur;
 
-    for( i = chain_len; i != 0; --i )
+    for( i = ver_chain->len; i != 0; --i )
     {
-        cur_flags = ver_chain[i-1].flags;
+        cur = &ver_chain->items[i-1];
+        cur_flags = cur->flags;
 
         if( NULL != f_vrfy )
-            if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
+            if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
                 return( ret );
 
         *flags |= cur_flags;
@@ -2297,7 +2494,7 @@
 }
 
 /*
- * Verify the certificate validity
+ * Verify the certificate validity (default profile, not restartable)
  */
 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
                      mbedtls_x509_crt *trust_ca,
@@ -2306,19 +2503,13 @@
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy )
 {
-    return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
-                &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
+    return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+                &mbedtls_x509_crt_profile_default, cn, flags,
+                f_vrfy, p_vrfy, NULL ) );
 }
 
 /*
- * Verify the certificate validity, with profile
- *
- * This function:
- *  - checks the requested CN (if any)
- *  - checks the type and size of the EE cert's key,
- *    as that isn't done as part of chain building/verification currently
- *  - builds and verifies the chain
- *  - then calls the callback and merges the flags
+ * Verify the certificate validity (user-chosen profile, not restartable)
  */
 int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
                      mbedtls_x509_crt *trust_ca,
@@ -2328,15 +2519,37 @@
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy )
 {
+    return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+                profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
+}
+
+/*
+ * Verify the certificate validity, with profile, restartable version
+ *
+ * This function:
+ *  - checks the requested CN (if any)
+ *  - checks the type and size of the EE cert's key,
+ *    as that isn't done as part of chain building/verification currently
+ *  - builds and verifies the chain
+ *  - then calls the callback and merges the flags
+ */
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+                     mbedtls_x509_crt *trust_ca,
+                     mbedtls_x509_crl *ca_crl,
+                     const mbedtls_x509_crt_profile *profile,
+                     const char *cn, uint32_t *flags,
+                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy,
+                     mbedtls_x509_crt_restart_ctx *rs_ctx )
+{
     int ret;
     mbedtls_pk_type_t pk_type;
-    x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
-    size_t chain_len;
-    uint32_t *ee_flags = &ver_chain[0].flags;
+    mbedtls_x509_crt_verify_chain ver_chain;
+    uint32_t ee_flags;
 
     *flags = 0;
-    memset( ver_chain, 0, sizeof( ver_chain ) );
-    chain_len = 0;
+    ee_flags = 0;
+    x509_crt_verify_chain_reset( &ver_chain );
 
     if( profile == NULL )
     {
@@ -2346,28 +2559,36 @@
 
     /* check name if requested */
     if( cn != NULL )
-        x509_crt_verify_name( crt, cn, ee_flags );
+        x509_crt_verify_name( crt, cn, &ee_flags );
 
     /* Check the type and size of the key */
     pk_type = mbedtls_pk_get_type( &crt->pk );
 
     if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
-        *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+        ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
 
     if( x509_profile_check_key( profile, &crt->pk ) != 0 )
-        *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+        ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
 
     /* Check the chain */
     ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
-                                 ver_chain, &chain_len );
+                                 &ver_chain, rs_ctx );
+
     if( ret != 0 )
         goto exit;
 
+    /* Merge end-entity flags */
+    ver_chain.items[0].flags |= ee_flags;
+
     /* Build final flags, calling callback on the way if any */
-    ret = x509_crt_merge_flags_with_cb( flags,
-                                        ver_chain, chain_len, f_vrfy, p_vrfy );
+    ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
 
 exit:
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+        mbedtls_x509_crt_restart_free( rs_ctx );
+#endif
+
     /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
      * the SSL module for authmode optional, but non-zero return from the
      * callback means a fatal error so it shouldn't be ignored */
@@ -2478,4 +2699,36 @@
     while( cert_cur != NULL );
 }
 
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
+{
+    mbedtls_pk_restart_init( &ctx->pk );
+
+    ctx->parent = NULL;
+    ctx->fallback_parent = NULL;
+    ctx->fallback_signature_is_good = 0;
+
+    ctx->parent_is_trusted = -1;
+
+    ctx->in_progress = x509_crt_rs_none;
+    ctx->self_cnt = 0;
+    x509_crt_verify_chain_reset( &ctx->ver_chain );
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_pk_restart_free( &ctx->pk );
+    mbedtls_x509_crt_restart_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/programs/README.md b/programs/README.md
new file mode 100644
index 0000000..eb25a7f
--- /dev/null
+++ b/programs/README.md
@@ -0,0 +1,125 @@
+Mbed TLS sample programs
+========================
+
+This subdirectory mostly contains sample programs that illustrate specific features of the library, as well as a few test and support programs.
+
+## Symmetric cryptography (AES) examples
+
+* [`aes/aescrypt2.c`](aes/aescrypt2.c): file encryption and authentication with a key derived from a low-entropy secret, demonstrating the low-level AES interface, the digest interface and HMAC.  
+  Warning: this program illustrates how to use low-level functions in the library. It should not be taken as an example of how to build a secure encryption mechanism. To derive a key from a low-entropy secret such as a password, use a standard key stretching mechanism such as PBKDF2 (provided by the `pkcs5` module). To encrypt and authenticate data, use a standard mode such as GCM or CCM (both available as library module).
+
+* [`aes/crypt_and_hash.c`](aes/crypt_and_hash.c): file encryption and authentication, demonstrating the generic cipher interface and the generic hash interface.
+
+## Hash (digest) examples
+
+* [`hash/generic_sum.c`](hash/generic_sum.c): file hash calculator and verifier, demonstrating the message digest (`md`) interface.
+
+* [`hash/hello.c`](hash/hello.c): hello-world program for MD5.
+
+## Public-key cryptography examples
+
+### Generic public-key cryptography (`pk`) examples
+
+* [`pkey/gen_key.c`](pkey/gen_key.c): generates a key for any of the supported public-key algorithms (RSA or ECC) and writes it to a file that can be used by the other pk sample programs.
+
+* [`pkey/key_app.c`](pkey/key_app.c): loads a PEM or DER public key or private key file and dumps its content.
+
+* [`pkey/key_app_writer.c`](pkey/key_app_writer.c): loads a PEM or DER public key or private key file and writes it to a new PEM or DER file.
+
+* [`pkey/pk_encrypt.c`](pkey/pk_encrypt.c), [`pkey/pk_decrypt.c`](pkey/pk_decrypt.c): loads a PEM or DER public/private key file and uses the key to encrypt/decrypt a short string through the generic public-key interface.
+
+* [`pkey/pk_sign.c`](pkey/pk_sign.c), [`pkey/pk_verify.c`](pkey/pk_verify.c): loads a PEM or DER private/public key file and uses the key to sign/verify a short string.
+
+### ECDSA and RSA signature examples
+
+* [`pkey/ecdsa.c`](pkey/ecdsa.c): generates an ECDSA key, signs a fixed message and verifies the signature.
+
+* [`pkey/rsa_encrypt.c`](pkey/rsa_encrypt.c), [`pkey/rsa_decrypt.c`](pkey/rsa_decrypt.c): loads an RSA public/private key and uses it to encrypt/decrypt a short string through the low-level RSA interface.
+
+* [`pkey/rsa_genkey.c`](pkey/rsa_genkey.c): generates an RSA key and writes it to a file that can be used with the other RSA sample programs.
+
+* [`pkey/rsa_sign.c`](pkey/rsa_sign.c), [`pkey/rsa_verify.c`](pkey/rsa_verify.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSA PKCS#1 v1.5 algorithm.
+
+* [`pkey/rsa_sign_pss.c`](pkey/rsa_sign_pss.c), [`pkey/rsa_verify_pss.c`](pkey/rsa_verify_pss.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSASSA-PSS algorithm.
+
+### Diffie-Hellman key exchange examples
+
+* [`pkey/dh_client.c`](pkey/dh_client.c), [`pkey/dh_server.c`](pkey/dh_server.c): secure channel demonstrators (client, server). This pair of programs illustrates how to set up a secure channel using RSA for authentication and Diffie-Hellman to generate a shared AES session key.
+
+* [`pkey/ecdh_curve25519.c`](pkey/ecdh_curve25519.c): demonstration of a elliptic curve Diffie-Hellman (ECDH) key agreement.
+
+### Bignum (`mpi`) usage examples
+
+* [`pkey/dh_genprime.c`](pkey/dh_genprime.c): shows how to use the bignum (`mpi`) interface to generate Diffie-Hellman parameters.
+
+* [`pkey/mpi_demo.c`](pkey/mpi_demo.c): demonstrates operations on big integers.
+
+## Random number generator (RNG) examples
+
+* [`random/gen_entropy.c`](random/gen_entropy.c): shows how to use the default entropy sources to generate random data.  
+  Note: most applications should only use the entropy generator to seed a cryptographic pseudorandom generator, as illustrated by `random/gen_random_ctr_drbg.c`.
+
+* [`random/gen_random_ctr_drbg.c`](random/gen_random_ctr_drbg.c): shows how to use the default entropy sources to seed a pseudorandom generator, and how to use the resulting random generator to generate random data.
+
+* [`random/gen_random_havege.c`](random/gen_random_havege.c): demonstrates the HAVEGE entropy collector.
+
+## SSL/TLS examples
+
+### SSL/TLS sample applications
+
+* [`ssl/dtls_client.c`](ssl/dtls_client.c): a simple DTLS client program, which sends one datagram to the server and reads one datagram in response.
+
+* [`ssl/dtls_server.c`](ssl/dtls_server.c): a simple DTLS server program, which expects one datagram from the client and writes one datagram in response. This program supports DTLS cookies for hello verification.
+
+* [`ssl/mini_client.c`](ssl/mini_client.c): a minimalistic SSL client, which sends a short string and disconnects. This is primarily intended as a benchmark; for a better example of a typical TLS client, see `ssl/ssl_client1.c`.
+
+* [`ssl/ssl_client1.c`](ssl/ssl_client1.c): a simple HTTPS client that sends a fixed request and displays the response.
+
+* [`ssl/ssl_fork_server.c`](ssl/ssl_fork_server.c): a simple HTTPS server using one process per client to send a fixed response. This program requires a Unix/POSIX environment implementing the `fork` system call.
+
+* [`ssl/ssl_mail_client.c`](ssl/ssl_mail_client.c): a simple SMTP-over-TLS or SMTP-STARTTLS client. This client sends an email with fixed content.
+
+* [`ssl/ssl_pthread_server.c`](ssl/ssl_pthread_server.c): a simple HTTPS server using one thread per client to send a fixed response. This program requires the pthread library.
+
+* [`ssl/ssl_server.c`](ssl/ssl_server.c): a simple HTTPS server that sends a fixed response. It serves a single client at a time.
+
+### SSL/TLS feature demonstrators
+
+Note: unlike most of the other programs under the `programs/` directory, these two programs are not intended as a basis for writing an application. They combine most of the features supported by the library, and most applications require only a few features. To write a new application, we recommended that you start with `ssl_client1.c` or `ssl_server.c`, and then look inside `ssl/ssl_client2.c` or `ssl/ssl_server2.c` to see how to use the specific features that your application needs.
+
+* [`ssl/ssl_client2.c`](ssl/ssl_client2.c): an HTTPS client that sends a fixed request and displays the response, with options to select TLS protocol features and Mbed TLS library features.
+
+* [`ssl/ssl_server2.c`](ssl/ssl_server2.c): an HTTPS server that sends a fixed response, with options to select TLS protocol features and Mbed TLS library features.
+
+In addition to providing options for testing client-side features, the `ssl_client2` program has options that allow you to trigger certain behaviors in the server. For example, there are options to select ciphersuites, or to force a renegotiation. These options are useful for testing the corresponding features in a TLS server. Likewise, `ssl_server2` has options to activate certain behaviors that are useful for testing a TLS client.
+
+## Test utilities
+
+* [`test/benchmark.c`](test/benchmark.c): benchmark for cryptographic algorithms.
+
+* [`test/selftest.c`](test/selftest.c): runs the self-test function in each library module.
+
+* [`test/ssl_cert_test.c`](test/ssl_cert_test.c): demonstrates how to verify X.509 certificates, and (for RSA keys only) how to check that each certificate matches the corresponding private key. This program requires some test data which is not provided.
+
+* [`test/udp_proxy.c`](test/udp_proxy.c): a UDP proxy that can inject certain failures (delay, duplicate, drop). Useful for testing DTLS.
+
+* [`test/zeroize.c`](test/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`tests/scripts/test_zeroize.gdb`](tests/scripts/test_zeroize.gdb).
+
+## Development utilities
+
+* [`util/pem2der.c`](util/pem2der.c): a PEM to DER converter. Mbed TLS can read PEM files directly, but this utility can be useful for interacting with other tools or with minimal Mbed TLS builds that lack PEM support.
+
+* [`util/strerror.c`](util/strerror.c): prints the error description corresponding to an integer status returned by an Mbed TLS function.
+
+## X.509 certificate examples
+
+* [`x509/cert_app.c`](x509/cert_app.c): connects to a TLS server and verifies its certificate chain.
+
+* [`x509/cert_req.c`](x509/cert_req.c): generates a certificate signing request (CSR) for a private key.
+
+* [`x509/cert_write.c`](x509/cert_write.c): signs a certificate signing request, or self-signs a certificate.
+
+* [`x509/crl_app.c`](x509/crl_app.c): loads and dumps a certificate revocation list (CRL).
+
+* [`x509/req_app.c`](x509/req_app.c): loads and dumps a certificate signing request (CSR).
+
diff --git a/programs/pkey/pk_decrypt.c b/programs/pkey/pk_decrypt.c
index 00bd71e..1d8c959 100644
--- a/programs/pkey/pk_decrypt.c
+++ b/programs/pkey/pk_decrypt.c
@@ -73,7 +73,10 @@
     const char *pers = "mbedtls_pk_decrypt";
     ((void) argv);
 
+    mbedtls_pk_init( &pk );
+    mbedtls_entropy_init( &entropy );
     mbedtls_ctr_drbg_init( &ctr_drbg );
+
     memset(result, 0, sizeof( result ) );
 
     if( argc != 2 )
@@ -90,20 +93,18 @@
     mbedtls_printf( "\n  . Seeding the random number generator..." );
     fflush( stdout );
 
-    mbedtls_entropy_init( &entropy );
-    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
-                               (const unsigned char *) pers,
-                               strlen( pers ) ) ) != 0 )
+    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+                                       &entropy, (const unsigned char *) pers,
+                                       strlen( pers ) ) ) != 0 )
     {
-        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
+        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
+                        -ret );
         goto exit;
     }
 
     mbedtls_printf( "\n  . Reading private key from '%s'", argv[1] );
     fflush( stdout );
 
-    mbedtls_pk_init( &pk );
-
     if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret );
@@ -116,14 +117,16 @@
     if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL )
     {
         mbedtls_printf( "\n  ! Could not open %s\n\n", "result-enc.txt" );
+        ret = 1;
         goto exit;
     }
 
     i = 0;
-
     while( fscanf( f, "%02X", &c ) > 0 &&
            i < (int) sizeof( buf ) )
+    {
         buf[i++] = (unsigned char) c;
+    }
 
     fclose( f );
 
@@ -136,7 +139,8 @@
     if( ( ret = mbedtls_pk_decrypt( &pk, buf, i, result, &olen, sizeof(result),
                             mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
     {
-        mbedtls_printf( " failed\n  ! mbedtls_pk_decrypt returned -0x%04x\n", -ret );
+        mbedtls_printf( " failed\n  ! mbedtls_pk_decrypt returned -0x%04x\n",
+                        -ret );
         goto exit;
     }
 
@@ -147,13 +151,15 @@
     exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
-    mbedtls_ctr_drbg_free( &ctr_drbg );
+
+    mbedtls_pk_free( &pk );
     mbedtls_entropy_free( &entropy );
+    mbedtls_ctr_drbg_free( &ctr_drbg );
 
 #if defined(MBEDTLS_ERROR_C)
     if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
-        mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
+        mbedtls_strerror( ret, (char *) buf, sizeof( buf ) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
     }
 #endif
diff --git a/programs/pkey/pk_encrypt.c b/programs/pkey/pk_encrypt.c
index 400619c..22dedba 100644
--- a/programs/pkey/pk_encrypt.c
+++ b/programs/pkey/pk_encrypt.c
@@ -73,6 +73,8 @@
     const char *pers = "mbedtls_pk_encrypt";
 
     mbedtls_ctr_drbg_init( &ctr_drbg );
+    mbedtls_entropy_init( &entropy );
+    mbedtls_pk_init( &pk );
 
     if( argc != 3 )
     {
@@ -88,20 +90,18 @@
     mbedtls_printf( "\n  . Seeding the random number generator..." );
     fflush( stdout );
 
-    mbedtls_entropy_init( &entropy );
-    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
-                               (const unsigned char *) pers,
-                               strlen( pers ) ) ) != 0 )
+    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+                                       &entropy, (const unsigned char *) pers,
+                                       strlen( pers ) ) ) != 0 )
     {
-        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret );
+        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
+                        -ret );
         goto exit;
     }
 
     mbedtls_printf( "\n  . Reading public key from '%s'", argv[1] );
     fflush( stdout );
 
-    mbedtls_pk_init( &pk );
-
     if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret );
@@ -126,7 +126,8 @@
                             buf, &olen, sizeof(buf),
                             mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
     {
-        mbedtls_printf( " failed\n  ! mbedtls_pk_encrypt returned -0x%04x\n", -ret );
+        mbedtls_printf( " failed\n  ! mbedtls_pk_encrypt returned -0x%04x\n",
+                        -ret );
         goto exit;
     }
 
@@ -135,13 +136,17 @@
      */
     if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL )
     {
-        mbedtls_printf( " failed\n  ! Could not create %s\n\n", "result-enc.txt" );
+        mbedtls_printf( " failed\n  ! Could not create %s\n\n",
+                        "result-enc.txt" );
+        ret = 1;
         goto exit;
     }
 
     for( i = 0; i < olen; i++ )
+    {
         mbedtls_fprintf( f, "%02X%s", buf[i],
                  ( i + 1 ) % 16 == 0 ? "\r\n" : " " );
+    }
 
     fclose( f );
 
@@ -150,13 +155,15 @@
     exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
-    mbedtls_ctr_drbg_free( &ctr_drbg );
+
+    mbedtls_pk_free( &pk );
     mbedtls_entropy_free( &entropy );
+    mbedtls_ctr_drbg_free( &ctr_drbg );
 
 #if defined(MBEDTLS_ERROR_C)
     if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
-        mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
+        mbedtls_strerror( ret, (char *) buf, sizeof( buf ) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
     }
 #endif
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index f271bad..c29ab34 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -60,9 +60,18 @@
 #include "mbedtls/certs.h"
 #include "mbedtls/timing.h"
 
+/* Uncomment out the following line to default to IPv4 and disable IPv6 */
+//#define FORCE_IPV4
+
 #define SERVER_PORT "4433"
 #define SERVER_NAME "localhost"
-#define SERVER_ADDR "127.0.0.1" /* forces IPv4 */
+
+#ifdef FORCE_IPV4
+#define SERVER_ADDR "127.0.0.1"     /* Forces IPv4 */
+#else
+#define SERVER_ADDR "::1"
+#endif
+
 #define MESSAGE     "Echo this"
 
 #define READ_TIMEOUT_MS 1000
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index 9d0dda4..b4ad6b5 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -34,6 +34,15 @@
 #define mbedtls_time_t     time_t
 #endif
 
+/* Uncomment out the following line to default to IPv4 and disable IPv6 */
+//#define FORCE_IPV4
+
+#ifdef FORCE_IPV4
+#define BIND_IP     "0.0.0.0"     /* Forces IPv4 */
+#else
+#define BIND_IP     "::"
+#endif
+
 #if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ||    \
     !defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) ||          \
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||        \
@@ -170,7 +179,7 @@
     printf( "  . Bind on udp/*/4433 ..." );
     fflush( stdout );
 
-    if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
+    if( ( ret = mbedtls_net_bind( &listen_fd, BIND_IP, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
     {
         printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 0dd9e3f..15c778d 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -83,6 +83,7 @@
 #define DFL_PSK                 ""
 #define DFL_PSK_IDENTITY        "Client_identity"
 #define DFL_ECJPAKE_PW          NULL
+#define DFL_EC_MAX_OPS          -1
 #define DFL_FORCE_CIPHER        0
 #define DFL_RENEGOTIATION       MBEDTLS_SSL_RENEGOTIATION_DISABLED
 #define DFL_ALLOW_LEGACY        -2
@@ -106,6 +107,8 @@
 #define DFL_TRANSPORT           MBEDTLS_SSL_TRANSPORT_STREAM
 #define DFL_HS_TO_MIN           0
 #define DFL_HS_TO_MAX           0
+#define DFL_DTLS_MTU            -1
+#define DFL_DGRAM_PACKING        1
 #define DFL_FALLBACK            -1
 #define DFL_EXTENDED_MS         -1
 #define DFL_ETM                 -1
@@ -198,7 +201,11 @@
 #define USAGE_DTLS \
     "    dtls=%%d             default: 0 (TLS)\n"                           \
     "    hs_timeout=%%d-%%d    default: (library default: 1000-60000)\n"    \
-    "                        range of DTLS handshake timeouts in millisecs\n"
+    "                        range of DTLS handshake timeouts in millisecs\n" \
+    "    mtu=%%d              default: (library default: unlimited)\n"  \
+    "    dgram_packing=%%d    default: 1 (allowed)\n"                   \
+    "                        allow or forbid packing of multiple\n" \
+    "                        records within a single datgram.\n"
 #else
 #define USAGE_DTLS ""
 #endif
@@ -239,6 +246,13 @@
 #define USAGE_ECJPAKE ""
 #endif
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+#define USAGE_ECRESTART \
+    "    ec_max_ops=%%s       default: library default (restart disabled)\n"
+#else
+#define USAGE_ECRESTART ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_client2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -268,6 +282,7 @@
     "\n"                                                    \
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
+    USAGE_ECRESTART                                         \
     "\n"                                                    \
     "    allow_legacy=%%d     default: (library default: no)\n"   \
     USAGE_RENEGO                                            \
@@ -321,6 +336,7 @@
     const char *psk;            /* the pre-shared key                       */
     const char *psk_identity;   /* the pre-shared key identity              */
     const char *ecjpake_pw;     /* the EC J-PAKE password                   */
+    int ec_max_ops;             /* EC consecutive operations limit          */
     int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
     int renegotiation;          /* enable / disable renegotiation           */
     int allow_legacy;           /* allow legacy renegotiation               */
@@ -345,7 +361,9 @@
     int transport;              /* TLS or DTLS?                             */
     uint32_t hs_to_min;         /* Initial value of DTLS handshake timer    */
     uint32_t hs_to_max;         /* Max value of DTLS handshake timer        */
+    int dtls_mtu;               /* UDP Maximum tranport unit for DTLS       */
     int fallback;               /* is this a fallback connection?           */
+    int dgram_packing;          /* allow/forbid datagram packing            */
     int extended_ms;            /* negotiate extended master secret?        */
     int etm;                    /* negotiate encrypt then mac?              */
 } opt;
@@ -594,6 +612,7 @@
     opt.psk                 = DFL_PSK;
     opt.psk_identity        = DFL_PSK_IDENTITY;
     opt.ecjpake_pw          = DFL_ECJPAKE_PW;
+    opt.ec_max_ops          = DFL_EC_MAX_OPS;
     opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
     opt.renegotiation       = DFL_RENEGOTIATION;
     opt.allow_legacy        = DFL_ALLOW_LEGACY;
@@ -617,9 +636,11 @@
     opt.transport           = DFL_TRANSPORT;
     opt.hs_to_min           = DFL_HS_TO_MIN;
     opt.hs_to_max           = DFL_HS_TO_MAX;
+    opt.dtls_mtu            = DFL_DTLS_MTU;
     opt.fallback            = DFL_FALLBACK;
     opt.extended_ms         = DFL_EXTENDED_MS;
     opt.etm                 = DFL_ETM;
+    opt.dgram_packing       = DFL_DGRAM_PACKING;
 
     for( i = 1; i < argc; i++ )
     {
@@ -693,6 +714,8 @@
             opt.psk_identity = q;
         else if( strcmp( p, "ecjpake_pw" ) == 0 )
             opt.ecjpake_pw = q;
+        else if( strcmp( p, "ec_max_ops" ) == 0 )
+            opt.ec_max_ops = atoi( q );
         else if( strcmp( p, "force_ciphersuite" ) == 0 )
         {
             opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q );
@@ -927,6 +950,21 @@
             if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min )
                 goto usage;
         }
+        else if( strcmp( p, "mtu" ) == 0 )
+        {
+            opt.dtls_mtu = atoi( q );
+            if( opt.dtls_mtu < 0 )
+                goto usage;
+        }
+        else if( strcmp( p, "dgram_packing" ) == 0 )
+        {
+            opt.dgram_packing = atoi( q );
+            if( opt.dgram_packing != 0 &&
+                opt.dgram_packing != 1 )
+            {
+                goto usage;
+            }
+        }
         else if( strcmp( p, "recsplit" ) == 0 )
         {
             opt.recsplit = atoi( q );
@@ -1327,6 +1365,9 @@
     if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
         mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min,
                                             opt.hs_to_max );
+
+    if( opt.dgram_packing != DFL_DGRAM_PACKING )
+        mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
@@ -1485,11 +1526,21 @@
                              mbedtls_net_send, mbedtls_net_recv,
                              opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL );
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( opt.dtls_mtu != DFL_DTLS_MTU )
+        mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu );
+#endif
+
 #if defined(MBEDTLS_TIMING_C)
     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                             mbedtls_timing_get_delay );
 #endif
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( opt.ec_max_ops != DFL_EC_MAX_OPS )
+        mbedtls_ecp_set_max_ops( opt.ec_max_ops );
+#endif
+
     mbedtls_printf( " ok\n" );
 
     /*
@@ -1501,7 +1552,8 @@
     while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
     {
         if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
-            ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+            ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+            ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
         {
             mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n",
                             -ret );
@@ -1517,6 +1569,11 @@
             goto exit;
         }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+        if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+            continue;
+#endif
+
         /* For event-driven IO, wait for socket to become available */
         if( opt.event == 1 /* level triggered IO */ )
         {
@@ -1609,13 +1666,19 @@
         while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 )
         {
             if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
-                ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+                ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
             {
                 mbedtls_printf( " failed\n  ! mbedtls_ssl_renegotiate returned %d\n\n",
                                 ret );
                 goto exit;
             }
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+                continue;
+#endif
+
             /* For event-driven IO, wait for socket to become available */
             if( opt.event == 1 /* level triggered IO */ )
             {
@@ -1676,7 +1739,8 @@
                                               len - written ) ) < 0 )
             {
                 if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
-                    ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+                    ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+                    ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
                 {
                     mbedtls_printf( " failed\n  ! mbedtls_ssl_write returned -0x%x\n\n",
                                     -ret );
@@ -1705,6 +1769,11 @@
         {
             ret = mbedtls_ssl_write( &ssl, buf, len );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+                continue;
+#endif
+
             if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
                 ret != MBEDTLS_ERR_SSL_WANT_WRITE )
                 break;
@@ -1765,6 +1834,11 @@
             memset( buf, 0, sizeof( buf ) );
             ret = mbedtls_ssl_read( &ssl, buf, len );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+                continue;
+#endif
+
             if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
                 ret == MBEDTLS_ERR_SSL_WANT_WRITE )
             {
@@ -1825,6 +1899,11 @@
         {
             ret = mbedtls_ssl_read( &ssl, buf, len );
 
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+            if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+                continue;
+#endif
+
             if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
                 ret != MBEDTLS_ERR_SSL_WANT_WRITE )
                 break;
@@ -1887,7 +1966,8 @@
         while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
         {
             if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
-                ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+                ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
             {
                 mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n",
                                 -ret );
@@ -1985,7 +2065,8 @@
         while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
         {
             if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
-                ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+                ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
             {
                 mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n",
                                 -ret );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 7654a64..4eac51f 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -103,6 +103,7 @@
 
 #define DFL_SERVER_ADDR         NULL
 #define DFL_SERVER_PORT         "4433"
+#define DFL_RESPONSE_SIZE       -1
 #define DFL_DEBUG_LEVEL         0
 #define DFL_NBIO                0
 #define DFL_EVENT               0
@@ -150,7 +151,9 @@
 #define DFL_ANTI_REPLAY         -1
 #define DFL_HS_TO_MIN           0
 #define DFL_HS_TO_MAX           0
+#define DFL_DTLS_MTU            -1
 #define DFL_BADMAC_LIMIT        -1
+#define DFL_DGRAM_PACKING        1
 #define DFL_EXTENDED_MS         -1
 #define DFL_ETM                 -1
 
@@ -175,7 +178,7 @@
  * You will need to adapt the mbedtls_ssl_get_bytes_avail() test in ssl-opt.sh
  * if you change this value to something outside the range <= 100 or > 500
  */
-#define IO_BUF_LEN      200
+#define DFL_IO_BUF_LEN      200
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 #if defined(MBEDTLS_FS_IO)
@@ -297,7 +300,11 @@
 #define USAGE_DTLS \
     "    dtls=%%d             default: 0 (TLS)\n"                           \
     "    hs_timeout=%%d-%%d    default: (library default: 1000-60000)\n"    \
-    "                        range of DTLS handshake timeouts in millisecs\n"
+    "                        range of DTLS handshake timeouts in millisecs\n" \
+    "    mtu=%%d              default: (library default: unlimited)\n"  \
+    "    dgram_packing=%%d    default: 1 (allowed)\n"                   \
+    "                        allow or forbid packing of multiple\n" \
+    "                        records within a single datgram.\n"
 #else
 #define USAGE_DTLS ""
 #endif
@@ -350,6 +357,11 @@
     "    server_addr=%%s      default: (all interfaces)\n"  \
     "    server_port=%%d      default: 4433\n"              \
     "    debug_level=%%d      default: 0 (disabled)\n"      \
+    "    buffer_size=%%d      default: 200 \n" \
+    "                         (minimum: 1, max: 16385)\n" \
+    "    response_size=%%d    default: about 152 (basic response)\n" \
+    "                          (minimum: 0, max: 16384)\n" \
+    "                          increases buffer_size if bigger\n"\
     "    nbio=%%d             default: 0 (blocking I/O)\n"  \
     "                        options: 1 (non-blocking), 2 (added delays)\n" \
     "    event=%%d            default: 0 (loop)\n"                            \
@@ -425,6 +437,8 @@
     int nbio;                   /* should I/O be blocking?                  */
     int event;                  /* loop or event-driven IO? level or edge triggered? */
     uint32_t read_timeout;      /* timeout on mbedtls_ssl_read() in milliseconds    */
+    int response_size;          /* pad response with header to requested size */
+    uint16_t buffer_size;       /* IO buffer size */
     const char *ca_file;        /* the file with the CA certificate(s)      */
     const char *ca_path;        /* the path with the CA certificate(s) reside */
     const char *crt_file;       /* the file with the server certificate     */
@@ -470,6 +484,8 @@
     int anti_replay;            /* Use anti-replay for DTLS? -1 for default */
     uint32_t hs_to_min;         /* Initial value of DTLS handshake timer    */
     uint32_t hs_to_max;         /* Max value of DTLS handshake timer        */
+    int dtls_mtu;               /* UDP Maximum tranport unit for DTLS       */
+    int dgram_packing;          /* allow/forbid datagram packing            */
     int badmac_limit;           /* Limit of records with bad MAC            */
 } opt;
 
@@ -1158,7 +1174,7 @@
 {
     int ret = 0, len, written, frags, exchanges_left;
     int version_suites[4][2];
-    unsigned char buf[IO_BUF_LEN];
+    unsigned char* buf = 0;
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
     unsigned char psk[MBEDTLS_PSK_MAX_LEN];
     size_t psk_len = 0;
@@ -1289,10 +1305,12 @@
         goto exit;
     }
 
+    opt.buffer_size         = DFL_IO_BUF_LEN;
     opt.server_addr         = DFL_SERVER_ADDR;
     opt.server_port         = DFL_SERVER_PORT;
     opt.debug_level         = DFL_DEBUG_LEVEL;
     opt.event               = DFL_EVENT;
+    opt.response_size       = DFL_RESPONSE_SIZE;
     opt.nbio                = DFL_NBIO;
     opt.read_timeout        = DFL_READ_TIMEOUT;
     opt.ca_file             = DFL_CA_FILE;
@@ -1338,6 +1356,8 @@
     opt.anti_replay         = DFL_ANTI_REPLAY;
     opt.hs_to_min           = DFL_HS_TO_MIN;
     opt.hs_to_max           = DFL_HS_TO_MAX;
+    opt.dtls_mtu            = DFL_DTLS_MTU;
+    opt.dgram_packing       = DFL_DGRAM_PACKING;
     opt.badmac_limit        = DFL_BADMAC_LIMIT;
     opt.extended_ms         = DFL_EXTENDED_MS;
     opt.etm                 = DFL_ETM;
@@ -1383,6 +1403,20 @@
         }
         else if( strcmp( p, "read_timeout" ) == 0 )
             opt.read_timeout = atoi( q );
+        else if( strcmp( p, "buffer_size" ) == 0 )
+        {
+            opt.buffer_size = atoi( q );
+            if( opt.buffer_size < 1 || opt.buffer_size > MBEDTLS_SSL_MAX_CONTENT_LEN + 1 )
+                goto usage;
+        }
+        else if( strcmp( p, "response_size" ) == 0 )
+        {
+            opt.response_size = atoi( q );
+            if( opt.response_size < 0 || opt.response_size > MBEDTLS_SSL_MAX_CONTENT_LEN )
+                goto usage;
+            if( opt.buffer_size < opt.response_size )
+                opt.buffer_size = opt.response_size;
+        }
         else if( strcmp( p, "ca_file" ) == 0 )
             opt.ca_file = q;
         else if( strcmp( p, "ca_path" ) == 0 )
@@ -1684,6 +1718,21 @@
             if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min )
                 goto usage;
         }
+        else if( strcmp( p, "mtu" ) == 0 )
+        {
+            opt.dtls_mtu = atoi( q );
+            if( opt.dtls_mtu < 0 )
+                goto usage;
+        }
+        else if( strcmp( p, "dgram_packing" ) == 0 )
+        {
+            opt.dgram_packing = atoi( q );
+            if( opt.dgram_packing != 0 &&
+                opt.dgram_packing != 1 )
+            {
+                goto usage;
+            }
+        }
         else if( strcmp( p, "sni" ) == 0 )
         {
             opt.sni = q;
@@ -1704,6 +1753,13 @@
 #if defined(MBEDTLS_DEBUG_C)
     mbedtls_debug_set_threshold( opt.debug_level );
 #endif
+    buf = mbedtls_calloc( 1, opt.buffer_size + 1 );
+    if( buf == NULL )
+    {
+        mbedtls_printf( "Could not allocate %u bytes\n", opt.buffer_size );
+        ret = 3;
+        goto exit;
+    }
 
     if( opt.force_ciphersuite[0] > 0 )
     {
@@ -2155,6 +2211,9 @@
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
         mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max );
+
+    if( opt.dgram_packing != DFL_DGRAM_PACKING )
+        mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
@@ -2473,6 +2532,11 @@
         mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv,
                              opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL );
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( opt.dtls_mtu != DFL_DTLS_MTU )
+        mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu );
+#endif
+
 #if defined(MBEDTLS_TIMING_C)
     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                             mbedtls_timing_get_delay );
@@ -2712,8 +2776,8 @@
         do
         {
             int terminated = 0;
-            len = sizeof( buf ) - 1;
-            memset( buf, 0, sizeof( buf ) );
+            len = opt.buffer_size - 1;
+            memset( buf, 0, opt.buffer_size );
             ret = mbedtls_ssl_read( &ssl, buf, len );
 
             if( mbedtls_status_is_ssl_in_progress( ret ) )
@@ -2813,8 +2877,8 @@
     }
     else /* Not stream, so datagram */
     {
-        len = sizeof( buf ) - 1;
-        memset( buf, 0, sizeof( buf ) );
+        len = opt.buffer_size - 1;
+        memset( buf, 0, opt.buffer_size );
 
         do
         {
@@ -2912,6 +2976,25 @@
     len = sprintf( (char *) buf, HTTP_RESPONSE,
                    mbedtls_ssl_get_ciphersuite( &ssl ) );
 
+    /* Add padding to the response to reach opt.response_size in length */
+    if( opt.response_size != DFL_RESPONSE_SIZE &&
+        len < opt.response_size )
+    {
+        memset( buf + len, 'B', opt.response_size - len );
+        len += opt.response_size - len;
+    }
+
+    /* Truncate if response size is smaller than the "natural" size */
+    if( opt.response_size != DFL_RESPONSE_SIZE &&
+        len > opt.response_size )
+    {
+        len = opt.response_size;
+
+        /* Still end with \r\n unless that's really not possible */
+        if( len >= 2 ) buf[len - 2] = '\r';
+        if( len >= 1 ) buf[len - 1] = '\n';
+    }
+
     if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM )
     {
         for( written = 0, frags = 0; written < len; written += ret, frags++ )
@@ -3070,6 +3153,7 @@
     mbedtls_memory_buffer_alloc_free();
 #endif
 
+    mbedtls_free( buf );
     mbedtls_printf( " done.\n" );
 
 #if defined(_WIN32)
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 5277ceb..e7d29c3 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -700,7 +700,6 @@
             mbedtls_exit(1);
         TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)",
                 mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
@@ -708,7 +707,6 @@
                                              MBEDTLS_HMAC_DRBG_PR_ON );
         TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)",
                 mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
 #endif
 
 #if defined(MBEDTLS_SHA256_C)
@@ -719,7 +717,6 @@
             mbedtls_exit(1);
         TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)",
                 mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
@@ -727,8 +724,8 @@
                                              MBEDTLS_HMAC_DRBG_PR_ON );
         TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)",
                 mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
 #endif
+        mbedtls_hmac_drbg_free( &hmac_drbg );
     }
 #endif
 
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index 55e0f24..41739d0 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -40,6 +40,8 @@
 #define mbedtls_time            time
 #define mbedtls_time_t          time_t
 #define mbedtls_printf          printf
+#define mbedtls_calloc          calloc
+#define mbedtls_free            free
 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
 #endif /* MBEDTLS_PLATFORM_C */
@@ -106,6 +108,21 @@
     "    delay=%%d            default: 0 (no delayed packets)\n"            \
     "                        delay about 1:N packets randomly\n"            \
     "    delay_ccs=0/1       default: 0 (don't delay ChangeCipherSpec)\n"   \
+    "    delay_cli=%%s        Handshake message from client that should be\n"\
+    "                        delayed. Possible values are 'ClientHello',\n" \
+    "                        'Certificate', 'CertificateVerify', and\n"     \
+    "                        'ClientKeyExchange'.\n"                        \
+    "                        May be used multiple times, even for the same\n"\
+    "                        message, in which case the respective message\n"\
+    "                        gets delayed multiple times.\n"                 \
+    "    delay_srv=%%s        Handshake message from server that should be\n"\
+    "                        delayed. Possible values are 'HelloRequest',\n"\
+    "                        'ServerHello', 'ServerHelloDone', 'Certificate'\n"\
+    "                        'ServerKeyExchange', 'NewSessionTicket',\n"\
+    "                        'HelloVerifyRequest' and ''CertificateRequest'.\n"\
+    "                        May be used multiple times, even for the same\n"\
+    "                        message, in which case the respective message\n"\
+    "                        gets delayed multiple times.\n"                 \
     "    drop=%%d             default: 0 (no dropped packets)\n"            \
     "                        drop about 1:N packets randomly\n"             \
     "    mtu=%%d              default: 0 (unlimited)\n"                     \
@@ -121,6 +138,9 @@
 /*
  * global options
  */
+
+#define MAX_DELAYED_HS 10
+
 static struct options
 {
     const char *server_addr;    /* address to forward packets to            */
@@ -131,6 +151,12 @@
     int duplicate;              /* duplicate 1 in N packets (none if 0)     */
     int delay;                  /* delay 1 packet in N (none if 0)          */
     int delay_ccs;              /* delay ChangeCipherSpec                   */
+    char* delay_cli[MAX_DELAYED_HS];  /* handshake types of messages from
+                                       * client that should be delayed.     */
+    uint8_t delay_cli_cnt;      /* Number of entries in delay_cli.          */
+    char* delay_srv[MAX_DELAYED_HS];  /* handshake types of messages from
+                                       * server that should be delayed.     */
+    uint8_t delay_srv_cnt;      /* Number of entries in delay_srv.          */
     int drop;                   /* drop 1 packet in N (none if 0)           */
     int mtu;                    /* drop packets larger than this            */
     int bad_ad;                 /* inject corrupted ApplicationData record  */
@@ -164,6 +190,11 @@
     opt.pack           = DFL_PACK;
     /* Other members default to 0 */
 
+    opt.delay_cli_cnt = 0;
+    opt.delay_srv_cnt = 0;
+    memset( opt.delay_cli, 0, sizeof( opt.delay_cli ) );
+    memset( opt.delay_srv, 0, sizeof( opt.delay_srv ) );
+
     for( i = 1; i < argc; i++ )
     {
         p = argv[i];
@@ -197,6 +228,43 @@
             if( opt.delay_ccs < 0 || opt.delay_ccs > 1 )
                 exit_usage( p, q );
         }
+        else if( strcmp( p, "delay_cli" ) == 0 ||
+                 strcmp( p, "delay_srv" ) == 0 )
+        {
+            uint8_t *delay_cnt;
+            char **delay_list;
+            size_t len;
+            char *buf;
+
+            if( strcmp( p, "delay_cli" ) == 0 )
+            {
+                delay_cnt  = &opt.delay_cli_cnt;
+                delay_list = opt.delay_cli;
+            }
+            else
+            {
+                delay_cnt  = &opt.delay_srv_cnt;
+                delay_list = opt.delay_srv;
+            }
+
+            if( *delay_cnt == MAX_DELAYED_HS )
+            {
+                mbedtls_printf( " too many uses of %s: only %d allowed\n",
+                                p, MAX_DELAYED_HS );
+                exit_usage( p, NULL );
+            }
+
+            len = strlen( q );
+            buf = mbedtls_calloc( 1, len + 1 );
+            if( buf == NULL )
+            {
+                mbedtls_printf( " Allocation failure\n" );
+                exit( 1 );
+            }
+            memcpy( buf, q, len + 1 );
+
+            delay_list[ (*delay_cnt)++ ] = buf;
+        }
         else if( strcmp( p, "drop" ) == 0 )
         {
             opt.drop = atoi( q );
@@ -488,11 +556,37 @@
     return( 0 );
 }
 
-static packet prev;
+#define MAX_DELAYED_MSG 5
+static size_t prev_len;
+static packet prev[MAX_DELAYED_MSG];
 
 void clear_pending( void )
 {
-    memset( &prev, 0, sizeof( packet ) );
+    memset( &prev, 0, sizeof( prev ) );
+    prev_len = 0;
+}
+
+void delay_packet( packet *delay )
+{
+    if( prev_len == MAX_DELAYED_MSG )
+        return;
+
+    memcpy( &prev[prev_len++], delay, sizeof( packet ) );
+}
+
+int send_delayed()
+{
+    uint8_t offset;
+    int ret;
+    for( offset = 0; offset < prev_len; offset++ )
+    {
+        ret = send_packet( &prev[offset], "delayed" );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    clear_pending();
+    return( 0 );
 }
 
 /*
@@ -540,6 +634,10 @@
     packet cur;
     size_t id;
 
+    uint8_t delay_idx;
+    char ** delay_list;
+    uint8_t delay_list_len;
+
     /* receive packet */
     if( ( ret = mbedtls_net_recv( src, cur.buf, sizeof( cur.buf ) ) ) <= 0 )
     {
@@ -555,6 +653,37 @@
 
     id = cur.len % sizeof( dropped );
 
+    if( strcmp( way, "S <- C" ) == 0 )
+    {
+        delay_list     = opt.delay_cli;
+        delay_list_len = opt.delay_cli_cnt;
+    }
+    else
+    {
+        delay_list     = opt.delay_srv;
+        delay_list_len = opt.delay_srv_cnt;
+    }
+
+    /* Check if message type is in the list of messages
+     * that should be delayed */
+    for( delay_idx = 0; delay_idx < delay_list_len; delay_idx++ )
+    {
+        if( delay_list[ delay_idx ] == NULL )
+            continue;
+
+        if( strcmp( delay_list[ delay_idx ], cur.type ) == 0 )
+        {
+            /* Delay message */
+            delay_packet( &cur );
+
+            /* Remove entry from list */
+            mbedtls_free( delay_list[delay_idx] );
+            delay_list[delay_idx] = NULL;
+
+            return( 0 );
+        }
+    }
+
     /* do we want to drop, delay, or forward it? */
     if( ( opt.mtu != 0 &&
           cur.len > (unsigned) opt.mtu ) ||
@@ -574,12 +703,11 @@
                strcmp( cur.type, "ApplicationData" ) != 0 &&
                ! ( opt.protect_hvr &&
                    strcmp( cur.type, "HelloVerifyRequest" ) == 0 ) &&
-               prev.dst == NULL &&
                cur.len != (size_t) opt.protect_len &&
                dropped[id] < DROP_MAX &&
                rand() % opt.delay == 0 ) )
     {
-        memcpy( &prev, &cur, sizeof( packet ) );
+        delay_packet( &cur );
     }
     else
     {
@@ -587,14 +715,10 @@
         if( ( ret = send_packet( &cur, "forwarded" ) ) != 0 )
             return( ret );
 
-        /* send previously delayed message if any */
-        if( prev.dst != NULL )
-        {
-            ret = send_packet( &prev, "delayed" );
-            memset( &prev, 0, sizeof( packet ) );
-            if( ret != 0 )
-                return( ret );
-        }
+        /* send previously delayed messages if any */
+        ret = send_delayed();
+        if( ret != 0 )
+            return( ret );
     }
 
     return( 0 );
@@ -604,6 +728,7 @@
 {
     int ret = 1;
     int exit_code = MBEDTLS_EXIT_FAILURE;
+    uint8_t delay_idx;
 
     mbedtls_net_context listen_fd, client_fd, server_fd;
 
@@ -798,6 +923,12 @@
     }
 #endif
 
+    for( delay_idx = 0; delay_idx < MAX_DELAYED_HS; delay_idx++ )
+    {
+        mbedtls_free( opt.delay_cli + delay_idx );
+        mbedtls_free( opt.delay_srv + delay_idx );
+    }
+
     mbedtls_net_free( &client_fd );
     mbedtls_net_free( &server_fd );
     mbedtls_net_free( &listen_fd );
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 09a91e0..fa99461 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -164,7 +164,7 @@
     const char *issuer_key;     /* filename of the issuer key file      */
     const char *subject_pwd;    /* password for the subject key file    */
     const char *issuer_pwd;     /* password for the issuer key file     */
-    const char *output_file;    /* where to store the constructed key file  */
+    const char *output_file;    /* where to store the constructed CRT   */
     const char *subject_name;   /* subject name for certificate         */
     const char *issuer_name;    /* issuer name for certificate          */
     const char *not_before;     /* validity period not before           */
@@ -770,7 +770,7 @@
     }
 
     /*
-     * 1.2. Writing the request
+     * 1.2. Writing the certificate
      */
     mbedtls_printf( "  . Writing the certificate..." );
     fflush( stdout );
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index ac171ed4a..0c1f7e1 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -32,7 +32,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
-                            NET OID PADLOCK PBKDF2 POLY1305 RIPEMD160
+                            NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160
                             SHA1 SHA256 SHA512 THREADING XTEA );
 my @high_level_modules = qw( CIPHER DHM ECP MD
                              PEM PK PKCS12 PKCS5
diff --git a/tests/.jenkins/Jenkinsfile b/tests/.jenkins/Jenkinsfile
new file mode 100644
index 0000000..ed04053
--- /dev/null
+++ b/tests/.jenkins/Jenkinsfile
@@ -0,0 +1 @@
+mbedtls.run_job()
diff --git a/tests/Makefile b/tests/Makefile
index 4d2edd4..b6e49bf 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -105,7 +105,7 @@
 
 clean:
 ifndef WINDOWS
-	rm -rf $(APPS) *.c *.datax TESTS
+	rm -rf $(BINARIES) *.c *.datax TESTS
 else
 	del /Q /F *.c *.exe *.datax
 ifneq ($(wildcard TESTS/.*),)
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 4a24352..df2c034 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -113,7 +113,7 @@
 	$(FAKETIME) -f +3653d $(OPENSSL) x509 -req -extfile $(cli_crt_extensions_file) -extensions cli-rsa -CA $(test_ca_int_rsa1) -CAkey test-int-ca.key -set_serial 16 -days 3653 -sha256 -in server7.csr | cat - $(test_ca_int_rsa1) > $@
 all_final += server7-future.crt
 server7-badsign.crt: server7.crt $(test_ca_int_rsa1)
-	{ head -n-2 server7.crt; tail -n-2 server7.crt | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; cat test-int-ca.crt; } > server7-badsign.crt
+	{ head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; cat $(test_ca_int_rsa1); } > $@
 all_final += server7-badsign.crt
 server7_int-ca-exp.crt: server7.crt test-int-ca-exp.crt
 	cat server7.crt test-int-ca-exp.crt > $@
@@ -128,6 +128,19 @@
 	$(FAKETIME) '2015-09-01 14:08:43' $(OPENSSL) req -x509 -new -subj "/C=UK/O=mbed TLS/CN=mbed TLS Test intermediate CA 3" -set_serial 77 -config $(test_ca_config_file) -extensions noext_ca -days 3650 -sha256 -key $< -out $@
 all_final += server5-ss-forgeca.crt
 
+server10-badsign.crt: server10.crt
+	{ head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@
+all_final += server10-badsign.crt
+server10-bs_int3.pem: server10-badsign.crt test-int-ca3.crt
+	cat server10-badsign.crt test-int-ca3.crt > $@
+all_final += server10-bs_int3.pem
+test-int-ca3-badsign.crt: test-int-ca3.crt
+	{ head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@
+all_final += test-int-ca3-badsign.crt
+server10_int3-bs.pem: server10.crt test-int-ca3-badsign.crt
+	cat server10.crt test-int-ca3-badsign.crt > $@
+all_final += server10-bs_int3-bs.pem
+
 rsa_pkcs1_2048_public.pem: server8.key
 	$(OPENSSL)  rsa -in $< -outform PEM -RSAPublicKey_out -out $@
 all_final += rsa_pkcs1_2048_public.pem
diff --git a/tests/data_files/Readme-x509.txt b/tests/data_files/Readme-x509.txt
index b56346a..6f54ed0 100644
--- a/tests/data_files/Readme-x509.txt
+++ b/tests/data_files/Readme-x509.txt
@@ -16,11 +16,13 @@
 Two intermediate CAs are signed by them:
 - test-int-ca.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate CA"
   uses RSA-4096, signed by test-ca2
+    - test-int-ca-exp.crt is a copy that is expired
 - test-int-ca2.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate EC CA"
-  uses an EC key with NIST P-256, signed by test-ca
+  uses an EC key with NIST P-384, signed by test-ca
 
 A third intermediate CA is signed by test-int-ca2.crt:
 - test-int-ca3.crt "C=UK, O=mbed TLS, CN=mbed TLS Test intermediate CA 3"
+  uses an EC key with NIST P-256, signed by test-int-ca2
 
 Finally, other CAs for specific purposes:
 - enco-ca-prstr.pem: has its CN encoded as a printable string, but child cert
@@ -65,21 +67,41 @@
 - server2*.crt: 1 R L: misc
 - server3.crt: 1 E L: EC cert signed by RSA CA
 - server4.crt: 2 R L: RSA cert signed by EC CA
-- server5*.crt: 2* E L: misc *(except server5-selfsigned)
+- server5*.crt: 2* E L: misc *(except -selfsigned and -ss-*)
     -sha*: hashes
-    -eku*: extendeKeyUsage (cli/srv = www client/server, cs = codesign, etc)
-    -ku*: keyUsage (ds = signatures, ke/ka = key exchange/agreement)
+    .eku*: extendeKeyUsage (cli/srv = www client/server, cs = codesign, etc)
+    .ku*: keyUsage (ds = signatures, ke/ka = key exchange/agreement)
+    .req*: CSR, not certificate
+    -der*: trailing bytes in der (?)
+    -badsign.crt: S5 with corrupted signature
+    -expired.crt: S5 with "not after" date in the past
+    -future.crt: S5 with "not before" date in the future
+    -selfsigned.crt: Self-signed cert with S5 key
+    -ss-expired.crt: Self-signed cert with S5 key, expired
+    -ss-forgeca.crt: Copy of test-int-ca3 self-signed with S5 key
 - server6-ss-child.crt: O E: "child" of non-CA server5-selfsigned
 - server6.crt, server6.pem: 2 E L C: revoked
-- server7*.crt: I1 E L P1*: EC signed by RSA signed by EC
-    *P1 except 7.crt, P2 _int-ca_ca2.crt
-    *_space: with PEM error(s)
-    _spurious: has spurious cert in its chain (S7 + I2 + I1)
+- server7.crt: I1 E L P1(usually): EC signed by RSA signed by EC
+    -badsign.crt: S7 with corrupted signature + I1
+    -expired.crt: S7 with "not after" date in the past + I1
+    -future.crt: S7 with "not before" date in the future + I1
+    _int-ca-exp.crt: S7 + expired I1
+    _int-ca.crt: S7 + I1
+    _int-ca_ca2.crt: S7 + I1 + 2
+    _all_space.crt: S7 + I1 both with misplaced spaces (invalid PEM)
+    _pem_space.crt: S7 with misplace space (invalid PEM) + I1
+    _trailing_space.crt: S7 + I1 both with trainling space (valid PEM)
+    _spurious_int-ca.crt: S7 + I2(spurious) + I1
 - server8*.crt: I2 R L: RSA signed by EC signed by RSA (P1 for _int-ca2)
 - server9*.crt: 1 R C* L P1*: signed using RSASSA-PSS
     *CRL for: 9.crt, -badsign, -with-ca (P1)
-- server10*.crt: I3 E L P2/P3
-    _spurious: S10 + I3 + I1(spurious) + I2
+- server10.crt: I3 E L
+    -badsign.crt: S10 with corrupted signature
+    -bs_int3.pem: S10-badsign + I3
+    _int3-bs.pem: S10 + I3-badsign
+    _int3_int-ca2.crt: S10 + I3 + I2
+    _int3_int-ca2_ca.crt: S10 + I3 + I2 + 1
+    _int3_spurious_int-ca2.crt: S10 + I3 + I1(spurious) + I2
 
 Certificate revocation lists
 ----------------------------
diff --git a/tests/data_files/server10-badsign.crt b/tests/data_files/server10-badsign.crt
new file mode 100644
index 0000000..eca171f
--- /dev/null
+++ b/tests/data_files/server10-badsign.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G
+A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp
+YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD
+VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq
+oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY
+Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io
+rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ
+AzO3pJx7WJAApZuBX10=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server10-bs_int3.pem b/tests/data_files/server10-bs_int3.pem
new file mode 100644
index 0000000..b84cee7
--- /dev/null
+++ b/tests/data_files/server10-bs_int3.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G
+A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp
+YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD
+VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq
+oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY
+Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io
+rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ
+AzO3pJx7WJAApZuBX10=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G
+A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp
+YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG
+A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU
+ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9
+2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo
+ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt
+Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt
+pz590JvGWfM=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server10.crt b/tests/data_files/server10.crt
new file mode 100644
index 0000000..96a4040
--- /dev/null
+++ b/tests/data_files/server10.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G
+A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp
+YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD
+VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq
+oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY
+Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io
+rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ
+AzO3pJx7WJAApZuBX1Q=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server10_int3-bs.pem b/tests/data_files/server10_int3-bs.pem
new file mode 100644
index 0000000..a9e0615
--- /dev/null
+++ b/tests/data_files/server10_int3-bs.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G
+A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp
+YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD
+VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq
+oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY
+Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io
+rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ
+AzO3pJx7WJAApZuBX1Q=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G
+A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp
+YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG
+A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU
+ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9
+2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo
+ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt
+Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt
+pz590JvGWf0=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-int-ca3-badsign.crt b/tests/data_files/test-int-ca3-badsign.crt
new file mode 100644
index 0000000..2087056
--- /dev/null
+++ b/tests/data_files/test-int-ca3-badsign.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G
+A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp
+YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG
+A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU
+ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9
+2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo
+ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt
+Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt
+pz590JvGWf0=
+-----END CERTIFICATE-----
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index ca9c93e..54c7504 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -38,7 +38,6 @@
 #   * G++
 #   * arm-gcc and mingw-gcc
 #   * ArmCC 5 and ArmCC 6, unless invoked with --no-armcc
-#   * Yotta build dependencies, unless invoked with --no-yotta
 #   * OpenSSL and GnuTLS command line tools, recent enough for the
 #     interoperability tests. If they don't support SSLv3 then a legacy
 #     version of these tools must be present as well (search for LEGACY
@@ -96,7 +95,6 @@
 FORCE=0
 KEEP_GOING=0
 RUN_ARMCC=1
-YOTTA=1
 
 # Default commands, can be overriden by the environment
 : ${OPENSSL:="openssl"}
@@ -130,12 +128,10 @@
      --no-force         Refuse to overwrite modified files (default).
      --no-keep-going    Stop at the first error (default).
      --no-memory        No additional memory tests (default).
-     --no-yotta         Skip yotta module build.
      --out-of-source-dir=<path>  Directory used for CMake out-of-source build tests.
      --random-seed      Use a random seed value for randomized tests (default).
   -r|--release-test     Run this script in release mode. This fixes the seed value to 1.
   -s|--seed             Integer seed value to use for this test run.
-     --yotta            Build yotta module (on by default).
 
 Tool path options:
      --armc5-bin-dir=<ARMC5_bin_dir_path>       ARM Compiler 5 bin directory.
@@ -160,7 +156,7 @@
     command make clean
 
     # Remove CMake artefacts
-    find . -name .git -prune -o -name yotta -prune -o \
+    find . -name .git -prune \
            -iname CMakeFiles -exec rm -rf {} \+ -o \
            \( -iname cmake_install.cmake -o \
               -iname CTestTestfile.cmake -o \
@@ -253,7 +249,6 @@
         --no-force) FORCE=0;;
         --no-keep-going) KEEP_GOING=0;;
         --no-memory) MEMORY=0;;
-        --no-yotta) YOTTA=0;;
         --openssl) shift; OPENSSL="$1";;
         --openssl-legacy) shift; OPENSSL_LEGACY="$1";;
         --openssl-next) shift; OPENSSL_NEXT="$1";;
@@ -261,7 +256,6 @@
         --random-seed) unset SEED;;
         --release-test|-r) SEED=1;;
         --seed|-s) shift; SEED="$1";;
-        --yotta) YOTTA=1;;
         *)
             echo >&2 "Unknown option: $1"
             echo >&2 "Run $0 --help for usage."
@@ -272,20 +266,10 @@
 done
 
 if [ $FORCE -eq 1 ]; then
-    if [ $YOTTA -eq 1 ]; then
-        rm -rf yotta/module "$OUT_OF_SOURCE_DIR"
-    fi
     git checkout-index -f -q $CONFIG_H
     cleanup
 else
 
-    if [ $YOTTA -ne 0 ] && [ -d yotta/module ]; then
-        err_msg "Warning - there is an existing yotta module in the directory 'yotta/module'"
-        echo "You can either delete your work and retry, or force the test to overwrite the"
-        echo "test by rerunning the script as: $0 --force"
-        exit 1
-    fi
-
     if [ -d "$OUT_OF_SOURCE_DIR" ]; then
         echo "Warning - there is an existing directory at '$OUT_OF_SOURCE_DIR'" >&2
         echo "You can either delete this directory manually, or force the test by rerunning"
@@ -436,25 +420,25 @@
     ARMC6_CC="$ARMC6_CC" RUN_ARMCC="$RUN_ARMCC" scripts/output_env.sh
 
 msg "test: recursion.pl" # < 1s
-tests/scripts/recursion.pl library/*.c
+record_status tests/scripts/recursion.pl library/*.c
 
 msg "test: freshness of generated source files" # < 1s
-tests/scripts/check-generated-files.sh
+record_status tests/scripts/check-generated-files.sh
 
 msg "test: doxygen markup outside doxygen blocks" # < 1s
-tests/scripts/check-doxy-blocks.pl
+record_status tests/scripts/check-doxy-blocks.pl
 
 msg "test: check-files.py" # < 1s
 cleanup
-tests/scripts/check-files.py
+record_status tests/scripts/check-files.py
 
 msg "test/build: declared and exported names" # < 3s
 cleanup
-tests/scripts/check-names.sh
+record_status tests/scripts/check-names.sh
 
 msg "test: doxygen warnings" # ~ 3s
 cleanup
-tests/scripts/doxygen.sh
+record_status tests/scripts/doxygen.sh
 
 
 
@@ -462,14 +446,6 @@
 #### Build and test many configurations and targets
 ################################################################
 
-if [ $RUN_ARMCC -ne 0 ] && [ $YOTTA -ne 0 ]; then
-    # Note - use of yotta is deprecated, and yotta also requires armcc to be on the
-    # path, and uses whatever version of armcc it finds there.
-    msg "build: create and build yotta module" # ~ 30s
-    cleanup
-    record_status tests/scripts/yotta-build.sh
-fi
-
 msg "build: cmake, gcc, ASan" # ~ 1 min 50s
 cleanup
 CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
@@ -531,10 +507,10 @@
 make test
 
 msg "test: RSA_NO_CRT - RSA-related part of ssl-opt.sh (ASan build)" # ~ 5s
-tests/ssl-opt.sh -f RSA
+if_build_succeeded tests/ssl-opt.sh -f RSA
 
 msg "test: RSA_NO_CRT - RSA-related part of compat.sh (ASan build)" # ~ 3 min
-tests/compat.sh -t RSA
+if_build_succeeded tests/compat.sh -t RSA
 
 msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
 cleanup
@@ -558,6 +534,26 @@
 msg "test: small SSL_IN_CONTENT_LEN - ssl-opt.sh MFL tests"
 if_build_succeeded tests/ssl-opt.sh -f "Max fragment"
 
+msg "build: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #0"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_SSL_DTLS_MAX_BUFFERING 1000
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #0 - ssl-opt.sh specific reordering test"
+if_build_succeeded tests/ssl-opt.sh -f "DTLS reordering: Buffer out-of-order hs msg before reassembling next, free buffered msg"
+
+msg "build: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #1"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_SSL_DTLS_MAX_BUFFERING 240
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #1 - ssl-opt.sh specific reordering test"
+if_build_succeeded tests/ssl-opt.sh -f "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket"
+
 msg "build: cmake, full config, clang" # ~ 50s
 cleanup
 cp "$CONFIG_H" "$CONFIG_BAK"
@@ -1043,7 +1039,6 @@
         cleanup
         make programs CC="$compiler" DEBUG=1 CFLAGS="$optimization_flag"
         if_build_succeeded gdb -x tests/scripts/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
-        if_build_succeeded [ -s test_zeroize.log ]
         if_build_succeeded grep "The buffer was correctly zeroized" test_zeroize.log
         if_build_succeeded not grep -i "error" test_zeroize.log
         rm -f test_zeroize.log
@@ -1051,10 +1046,10 @@
 done
 
 msg "Lint: Python scripts"
-tests/scripts/check-python-files.sh
+record_status tests/scripts/check-python-files.sh
 
 msg "uint test: generate_test_code.py"
-./tests/scripts/test_generate_test_code.py
+record_status ./tests/scripts/test_generate_test_code.py
 
 ################################################################
 #### Termination
diff --git a/tests/scripts/check-files.py b/tests/scripts/check-files.py
index f560d03..ed67872 100755
--- a/tests/scripts/check-files.py
+++ b/tests/scripts/check-files.py
@@ -155,6 +155,11 @@
             ".c", ".h", ".sh", ".pl", ".py", ".md", ".function", ".data",
             "Makefile", "CMakeLists.txt", "ChangeLog"
         )
+        self.excluded_directories = ['.git', 'mbed-os']
+        self.excluded_paths = list(map(os.path.normpath, [
+            'cov-int',
+            'examples',
+        ]))
         self.issues_to_check = [
             PermissionIssueTracker(),
             EndOfFileNewlineIssueTracker(),
@@ -179,12 +184,19 @@
             console = logging.StreamHandler()
             self.logger.addHandler(console)
 
+    def prune_branch(self, root, d):
+        if d in self.excluded_directories:
+            return True
+        if os.path.normpath(os.path.join(root, d)) in self.excluded_paths:
+            return True
+        return False
+
     def check_files(self):
-        for root, dirs, files in sorted(os.walk(".")):
+        for root, dirs, files in os.walk("."):
+            dirs[:] = sorted(d for d in dirs if not self.prune_branch(root, d))
             for filename in sorted(files):
                 filepath = os.path.join(root, filename)
-                if (os.path.join("yotta", "module") in filepath or
-                        not filepath.endswith(self.files_to_check)):
+                if not filepath.endswith(self.files_to_check):
                     continue
                 for issue_to_check in self.issues_to_check:
                     if issue_to_check.should_check_file(filepath):
diff --git a/tests/scripts/check-names.sh b/tests/scripts/check-names.sh
index 4c66440..f18a162 100755
--- a/tests/scripts/check-names.sh
+++ b/tests/scripts/check-names.sh
@@ -40,7 +40,7 @@
 for THING in actual-macros enum-consts; do
     printf "Names of $THING: "
     test -r $THING
-    BAD=$( grep -v '^MBEDTLS_[0-9A-Z_]*[0-9A-Z]$\|^YOTTA_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
+    BAD=$( grep -v '^MBEDTLS_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
     if [ "x$BAD" = "x" ]; then
         echo "PASS"
     else
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 6279358..6fe6abf 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -35,8 +35,9 @@
 
 # All test suites = executable files, excluding source files, debug
 # and profiling information, etc. We can't just grep {! /\./} because
-#some of our test cases' base names contain a dot.
+# some of our test cases' base names contain a dot.
 my @suites = grep { -x $_ || /\.exe$/ } glob 'test_suite_*';
+@suites = grep { !/\.c$/ && !/\.data$/ && -f } @suites;
 die "$0: no test suite found\n" unless @suites;
 
 # in case test suites are linked dynamically
diff --git a/tests/scripts/test_zeroize.gdb b/tests/scripts/test_zeroize.gdb
index 617ab55..77c812a 100644
--- a/tests/scripts/test_zeroize.gdb
+++ b/tests/scripts/test_zeroize.gdb
@@ -41,6 +41,9 @@
 # number does not need to be updated often.
 
 set confirm off
+# We don't need to turn off ASLR, so don't try.
+set disable-randomization off
+
 file ./programs/test/zeroize
 break zeroize.c:100
 
diff --git a/tests/scripts/yotta-build.sh b/tests/scripts/yotta-build.sh
deleted file mode 100755
index 4bae34a..0000000
--- a/tests/scripts/yotta-build.sh
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/sh
-
-# yotta-build.sh
-#
-# This file is part of mbed TLS (https://tls.mbed.org)
-#
-# Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
-#
-# Purpose
-#
-# To run test builds of the yotta module for all supported targets.
-
-set -eu
-
-check_tools()
-{
-    for TOOL in "$@"; do
-        if ! `hash "$TOOL" >/dev/null 2>&1`; then
-            echo "$TOOL not found!" >&2
-            exit 1
-        fi
-    done
-}
-
-yotta_build()
-{
-    TARGET=$1
-
-    echo; echo "*** $TARGET (release) ***"
-    yt -t $TARGET build
-
-    echo; echo "*** $TARGET (debug) ***"
-    yt -t $TARGET build -d
-}
-
-# Make sure the tools we need are available.
-check_tools "arm-none-eabi-gcc" "armcc" "yotta"
-
-yotta/create-module.sh
-cd yotta/module
-yt update || true # needs network
-
-if uname -a | grep 'Linux.*x86' >/dev/null; then
-    yotta_build x86-linux-native
-fi
-if uname -a | grep 'Darwin.*x86' >/dev/null; then
-    yotta_build x86-osx-native
-fi
-
-# armcc build tests.
-yotta_build frdm-k64f-armcc
-#yotta_build nordic-nrf51822-16k-armcc
-
-# arm-none-eabi-gcc build tests.
-yotta_build frdm-k64f-gcc
-#yotta_build st-nucleo-f401re-gcc # dirent
-#yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
-#yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform
-#yotta_build bbc-microbit-classic-gcc # fails in minar-platform
-#yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4
-#yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 937a27b..ce9aee2 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -41,6 +41,28 @@
 G_CLI="echo 'GET / HTTP/1.0' | $GNUTLS_CLI --x509cafile data_files/test-ca_cat12.crt"
 TCP_CLIENT="$PERL scripts/tcp_client.pl"
 
+# alternative versions of OpenSSL and GnuTLS (no default path)
+
+if [ -n "${OPENSSL_LEGACY:-}" ]; then
+    O_LEGACY_SRV="$OPENSSL_LEGACY s_server -www -cert data_files/server5.crt -key data_files/server5.key"
+    O_LEGACY_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_LEGACY s_client"
+else
+    O_LEGACY_SRV=false
+    O_LEGACY_CLI=false
+fi
+
+if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
+    G_NEXT_SRV="$GNUTLS_NEXT_SERV --x509certfile data_files/server5.crt --x509keyfile data_files/server5.key"
+else
+    G_NEXT_SRV=false
+fi
+
+if [ -n "${GNUTLS_NEXT_CLI:-}" ]; then
+    G_NEXT_CLI="echo 'GET / HTTP/1.0' | $GNUTLS_NEXT_CLI --x509cafile data_files/test-ca_cat12.crt"
+else
+    G_NEXT_CLI=false
+fi
+
 TESTS=0
 FAILS=0
 SKIPS=0
@@ -120,6 +142,14 @@
     done
 }
 
+# Skip next test; use this macro to skip tests which are legitimate
+# in theory and expected to be re-introduced at some point, but
+# aren't expected to succeed at the moment due to problems outside
+# our control (such as bugs in other TLS implementations).
+skip_next_test() {
+    SKIP_NEXT="YES"
+}
+
 # skip next test if the flag is not enabled in config.h
 requires_config_enabled() {
     if grep "^#define $1" $CONFIG_H > /dev/null; then :; else
@@ -134,6 +164,27 @@
     fi
 }
 
+get_config_value_or_default() {
+    NAME="$1"
+    DEF_VAL=$( grep ".*#define.*${NAME}" ../include/mbedtls/config.h |
+               sed 's/^.*\s\([0-9]*\)$/\1/' )
+    ../scripts/config.pl get $NAME || echo "$DEF_VAL"
+}
+
+requires_config_value_at_least() {
+    VAL=$( get_config_value_or_default "$1" )
+    if [ "$VAL" -lt "$2" ]; then
+       SKIP_NEXT="YES"
+    fi
+}
+
+requires_config_value_at_most() {
+    VAL=$( get_config_value_or_default "$1" )
+    if [ "$VAL" -gt "$2" ]; then
+       SKIP_NEXT="YES"
+    fi
+}
+
 # skip next test if OpenSSL doesn't support FALLBACK_SCSV
 requires_openssl_with_fallback_scsv() {
     if [ -z "${OPENSSL_HAS_FBSCSV:-}" ]; then
@@ -163,6 +214,34 @@
     fi
 }
 
+# skip next test if GnuTLS-next isn't available
+requires_gnutls_next() {
+    if [ -z "${GNUTLS_NEXT_AVAILABLE:-}" ]; then
+        if ( which "${GNUTLS_NEXT_CLI:-}" && which "${GNUTLS_NEXT_SERV:-}" ) >/dev/null 2>&1; then
+            GNUTLS_NEXT_AVAILABLE="YES"
+        else
+            GNUTLS_NEXT_AVAILABLE="NO"
+        fi
+    fi
+    if [ "$GNUTLS_NEXT_AVAILABLE" = "NO" ]; then
+        SKIP_NEXT="YES"
+    fi
+}
+
+# skip next test if OpenSSL-legacy isn't available
+requires_openssl_legacy() {
+    if [ -z "${OPENSSL_LEGACY_AVAILABLE:-}" ]; then
+        if which "${OPENSSL_LEGACY:-}" >/dev/null 2>&1; then
+            OPENSSL_LEGACY_AVAILABLE="YES"
+        else
+            OPENSSL_LEGACY_AVAILABLE="NO"
+        fi
+    fi
+    if [ "$OPENSSL_LEGACY_AVAILABLE" = "NO" ]; then
+        SKIP_NEXT="YES"
+    fi
+}
+
 # skip next test if IPv6 isn't available on this host
 requires_ipv6() {
     if [ -z "${HAS_IPV6:-}" ]; then
@@ -183,6 +262,21 @@
     fi
 }
 
+# skip next test if it's i686 or uname is not available
+requires_not_i686() {
+    if [ -z "${IS_I686:-}" ]; then
+        IS_I686="YES"
+        if which "uname" >/dev/null 2>&1; then
+            if [ -z "$(uname -a | grep i686)" ]; then
+                IS_I686="NO"
+            fi
+        fi
+    fi
+    if [ "$IS_I686" = "YES" ]; then
+        SKIP_NEXT="YES"
+    fi
+}
+
 # Calculate the input & output maximum content lengths set in the config
 MAX_CONTENT_LEN=$( ../scripts/config.pl get MBEDTLS_SSL_MAX_CONTENT_LEN || echo "16384")
 MAX_IN_LEN=$( ../scripts/config.pl get MBEDTLS_SSL_IN_CONTENT_LEN || echo "$MAX_CONTENT_LEN")
@@ -632,6 +726,9 @@
     if [ "$PRESERVE_LOGS" -gt 0 ]; then
         mv $SRV_OUT o-srv-${TESTS}.log
         mv $CLI_OUT o-cli-${TESTS}.log
+        if [ -n "$PXY_CMD" ]; then
+            mv $PXY_OUT o-pxy-${TESTS}.log
+        fi
     fi
 
     rm -f $SRV_OUT $CLI_OUT $PXY_OUT
@@ -715,7 +812,20 @@
 O_SRV="$O_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
 O_CLI="$O_CLI -connect localhost:+SRV_PORT"
 G_SRV="$G_SRV -p $SRV_PORT"
-G_CLI="$G_CLI -p +SRV_PORT localhost"
+G_CLI="$G_CLI -p +SRV_PORT"
+
+if [ -n "${OPENSSL_LEGACY:-}" ]; then
+    O_LEGACY_SRV="$O_LEGACY_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
+    O_LEGACY_CLI="$O_LEGACY_CLI -connect localhost:+SRV_PORT"
+fi
+
+if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
+    G_NEXT_SRV="$G_NEXT_SRV -p $SRV_PORT"
+fi
+
+if [ -n "${GNUTLS_NEXT_CLI:-}" ]; then
+    G_NEXT_CLI="$G_NEXT_CLI -p +SRV_PORT"
+fi
 
 # Allow SHA-1, because many of our test certificates use it
 P_SRV="$P_SRV allow_sha1=1"
@@ -801,6 +911,22 @@
             -S "SSL - None of the common ciphersuites is usable" \
             -S "SSL - The server has no ciphersuites in common"
 
+# Test empty CA list in CertificateRequest in TLS 1.1 and earlier
+
+requires_gnutls
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+run_test    "CertificateRequest with empty CA list, TLS 1.1 (GnuTLS server)" \
+            "$G_SRV"\
+            "$P_CLI force_version=tls1_1" \
+            0
+
+requires_gnutls
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1
+run_test    "CertificateRequest with empty CA list, TLS 1.0 (GnuTLS server)" \
+            "$G_SRV"\
+            "$P_CLI force_version=tls1" \
+            0
+
 # Tests for SHA-1 support
 
 requires_config_disabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
@@ -849,6 +975,35 @@
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha256.crt" \
             0
 
+# Tests for datagram packing
+run_test    "DTLS: multiple records in same datagram, client and server" \
+            "$P_SRV dtls=1 dgram_packing=1 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=1 debug_level=2" \
+            0 \
+            -c "next record in same datagram" \
+            -s "next record in same datagram"
+
+run_test    "DTLS: multiple records in same datagram, client only" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=1 debug_level=2" \
+            0 \
+            -s "next record in same datagram" \
+            -C "next record in same datagram"
+
+run_test    "DTLS: multiple records in same datagram, server only" \
+            "$P_SRV dtls=1 dgram_packing=1 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
+            0 \
+            -S "next record in same datagram" \
+            -c "next record in same datagram"
+
+run_test    "DTLS: multiple records in same datagram, neither client nor server" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
+            0 \
+            -S "next record in same datagram" \
+            -C "next record in same datagram"
+
 # Tests for Truncated HMAC extension
 
 run_test    "Truncated HMAC: client default, server default" \
@@ -1364,6 +1519,71 @@
             -s "session successfully restored from ticket" \
             -s "a session has been resumed"
 
+# Tests for Session Tickets with DTLS
+
+run_test    "Session resume using tickets, DTLS: basic" \
+            "$P_SRV debug_level=3 dtls=1 tickets=1" \
+            "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \
+            0 \
+            -c "client hello, adding session ticket extension" \
+            -s "found session ticket extension" \
+            -s "server hello, adding session ticket extension" \
+            -c "found session_ticket extension" \
+            -c "parse new session ticket" \
+            -S "session successfully restored from cache" \
+            -s "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using tickets, DTLS: cache disabled" \
+            "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \
+            "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \
+            0 \
+            -c "client hello, adding session ticket extension" \
+            -s "found session ticket extension" \
+            -s "server hello, adding session ticket extension" \
+            -c "found session_ticket extension" \
+            -c "parse new session ticket" \
+            -S "session successfully restored from cache" \
+            -s "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using tickets, DTLS: timeout" \
+            "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0 ticket_timeout=1" \
+            "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 reco_delay=2" \
+            0 \
+            -c "client hello, adding session ticket extension" \
+            -s "found session ticket extension" \
+            -s "server hello, adding session ticket extension" \
+            -c "found session_ticket extension" \
+            -c "parse new session ticket" \
+            -S "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -S "a session has been resumed" \
+            -C "a session has been resumed"
+
+run_test    "Session resume using tickets, DTLS: openssl server" \
+            "$O_SRV -dtls1" \
+            "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \
+            0 \
+            -c "client hello, adding session ticket extension" \
+            -c "found session_ticket extension" \
+            -c "parse new session ticket" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using tickets, DTLS: openssl client" \
+            "$P_SRV dtls=1 debug_level=3 tickets=1" \
+            "( $O_CLI -dtls1 -sess_out $SESSION; \
+               $O_CLI -dtls1 -sess_in $SESSION; \
+               rm -f $SESSION )" \
+            0 \
+            -s "found session ticket extension" \
+            -s "server hello, adding session ticket extension" \
+            -S "session successfully restored from cache" \
+            -s "session successfully restored from ticket" \
+            -s "a session has been resumed"
+
 # Tests for Session Resume based on session-ID and cache
 
 run_test    "Session resume using cache: tickets enabled on client" \
@@ -1459,6 +1679,101 @@
             -C "parse new session ticket" \
             -c "a session has been resumed"
 
+# Tests for Session Resume based on session-ID and cache, DTLS
+
+run_test    "Session resume using cache, DTLS: tickets enabled on client" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0" \
+            "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \
+            0 \
+            -c "client hello, adding session ticket extension" \
+            -s "found session ticket extension" \
+            -S "server hello, adding session ticket extension" \
+            -C "found session_ticket extension" \
+            -C "parse new session ticket" \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: tickets enabled on server" \
+            "$P_SRV dtls=1 debug_level=3 tickets=1" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
+            0 \
+            -C "client hello, adding session ticket extension" \
+            -S "found session ticket extension" \
+            -S "server hello, adding session ticket extension" \
+            -C "found session_ticket extension" \
+            -C "parse new session ticket" \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: cache_max=0" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=0" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
+            0 \
+            -S "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -S "a session has been resumed" \
+            -C "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: cache_max=1" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=1" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
+            0 \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: timeout > delay" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=0" \
+            0 \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: timeout < delay" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=1" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
+            0 \
+            -S "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -S "a session has been resumed" \
+            -C "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: no timeout" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=0" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \
+            0 \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed" \
+            -c "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: openssl client" \
+            "$P_SRV dtls=1 debug_level=3 tickets=0" \
+            "( $O_CLI -dtls1 -sess_out $SESSION; \
+               $O_CLI -dtls1 -sess_in $SESSION; \
+               rm -f $SESSION )" \
+            0 \
+            -s "found session ticket extension" \
+            -S "server hello, adding session ticket extension" \
+            -s "session successfully restored from cache" \
+            -S "session successfully restored from ticket" \
+            -s "a session has been resumed"
+
+run_test    "Session resume using cache, DTLS: openssl server" \
+            "$O_SRV -dtls1" \
+            "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \
+            0 \
+            -C "found session_ticket extension" \
+            -C "parse new session ticket" \
+            -c "a session has been resumed"
+
 # Tests for Max Fragment Length extension
 
 if [ "$MAX_CONTENT_LEN" -lt "4096" ]; then
@@ -2055,7 +2370,7 @@
 requires_gnutls
 run_test    "Renego ext: gnutls client strict, server default" \
             "$P_SRV debug_level=3" \
-            "$G_CLI --priority=NORMAL:%SAFE_RENEGOTIATION" \
+            "$G_CLI --priority=NORMAL:%SAFE_RENEGOTIATION localhost" \
             0 \
             -s "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -s "server hello, secure renegotiation extension"
@@ -2063,7 +2378,7 @@
 requires_gnutls
 run_test    "Renego ext: gnutls client unsafe, server default" \
             "$P_SRV debug_level=3" \
-            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
             -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -S "server hello, secure renegotiation extension"
@@ -2071,7 +2386,7 @@
 requires_gnutls
 run_test    "Renego ext: gnutls client unsafe, server break legacy" \
             "$P_SRV debug_level=3 allow_legacy=-1" \
-            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION" \
+            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION localhost" \
             1 \
             -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -S "server hello, secure renegotiation extension"
@@ -2082,7 +2397,7 @@
 run_test    "DER format: no trailing bytes" \
             "$P_SRV crt_file=data_files/server5-der0.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2090,7 +2405,7 @@
 run_test    "DER format: with a trailing zero byte" \
             "$P_SRV crt_file=data_files/server5-der1a.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2098,7 +2413,7 @@
 run_test    "DER format: with a trailing random byte" \
             "$P_SRV crt_file=data_files/server5-der1b.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2106,7 +2421,7 @@
 run_test    "DER format: with 2 trailing random bytes" \
             "$P_SRV crt_file=data_files/server5-der2.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2114,7 +2429,7 @@
 run_test    "DER format: with 4 trailing random bytes" \
             "$P_SRV crt_file=data_files/server5-der4.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2122,7 +2437,7 @@
 run_test    "DER format: with 8 trailing random bytes" \
             "$P_SRV crt_file=data_files/server5-der8.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -2130,7 +2445,7 @@
 run_test    "DER format: with 9 trailing random bytes" \
             "$P_SRV crt_file=data_files/server5-der9.crt \
              key_file=data_files/server5.key" \
-            "$G_CLI " \
+            "$G_CLI localhost" \
             0 \
             -c "Handshake was completed" \
 
@@ -3695,14 +4010,14 @@
 requires_gnutls
 run_test    "ClientHello without extensions, SHA-1 allowed" \
             "$P_SRV debug_level=3" \
-            "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION" \
+            "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
             -s "dumping 'client hello extensions' (0 bytes)"
 
 requires_gnutls
 run_test    "ClientHello without extensions, SHA-1 forbidden in certificates on server" \
             "$P_SRV debug_level=3 key_file=data_files/server2.key crt_file=data_files/server2.crt allow_sha1=0" \
-            "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION" \
+            "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
             -s "dumping 'client hello extensions' (0 bytes)"
 
@@ -3720,10 +4035,10 @@
             0 \
             -s "Read from client: 500 bytes read (.*+.*)"
 
-# Tests for small packets
+# Tests for small client packets
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
-run_test    "Small packet SSLv3 BlockCipher" \
+run_test    "Small client packet SSLv3 BlockCipher" \
             "$P_SRV min_version=ssl3" \
             "$P_CLI request_size=1 force_version=ssl3 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3731,21 +4046,21 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
-run_test    "Small packet SSLv3 StreamCipher" \
+run_test    "Small client packet SSLv3 StreamCipher" \
             "$P_SRV min_version=ssl3 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=ssl3 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.0 BlockCipher" \
+run_test    "Small client packet TLS 1.0 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.0 BlockCipher, without EtM" \
+run_test    "Small client packet TLS 1.0 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3753,7 +4068,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.0 BlockCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.0 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -3761,21 +4076,21 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.0 StreamCipher" \
+run_test    "Small client packet TLS 1.0 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.0 StreamCipher, without EtM" \
+run_test    "Small client packet TLS 1.0 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -3783,7 +4098,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.0 StreamCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.0 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -3791,21 +4106,21 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
              trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.1 BlockCipher" \
+run_test    "Small client packet TLS 1.1 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.1 BlockCipher, without EtM" \
+run_test    "Small client packet TLS 1.1 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
@@ -3813,7 +4128,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.1 BlockCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.1 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -3821,21 +4136,21 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.1 StreamCipher" \
+run_test    "Small client packet TLS 1.1 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.1 StreamCipher, without EtM" \
+run_test    "Small client packet TLS 1.1 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -3843,7 +4158,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.1 StreamCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.1 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -3851,28 +4166,28 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 BlockCipher" \
+run_test    "Small client packet TLS 1.2 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 BlockCipher, without EtM" \
+run_test    "Small client packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 BlockCipher larger MAC" \
+run_test    "Small client packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
@@ -3880,7 +4195,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.2 BlockCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.2 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -3888,21 +4203,21 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 StreamCipher" \
+run_test    "Small client packet TLS 1.2 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 StreamCipher, without EtM" \
+run_test    "Small client packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -3910,7 +4225,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.2 StreamCipher, truncated MAC" \
+run_test    "Small client packet TLS 1.2 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -3918,31 +4233,31 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
+run_test    "Small client packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 AEAD" \
+run_test    "Small client packet TLS 1.2 AEAD" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
             -s "Read from client: 1 bytes read"
 
-run_test    "Small packet TLS 1.2 AEAD shorter tag" \
+run_test    "Small client packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV" \
             "$P_CLI request_size=1 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
             -s "Read from client: 1 bytes read"
 
-# Tests for small packets in DTLS
+# Tests for small client packets in DTLS
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
-run_test    "Small packet DTLS 1.0" \
+run_test    "Small client packet DTLS 1.0" \
             "$P_SRV dtls=1 force_version=dtls1" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3950,7 +4265,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
-run_test    "Small packet DTLS 1.0, without EtM" \
+run_test    "Small client packet DTLS 1.0, without EtM" \
             "$P_SRV dtls=1 force_version=dtls1 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3959,7 +4274,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet DTLS 1.0, truncated hmac" \
+run_test    "Small client packet DTLS 1.0, truncated hmac" \
             "$P_SRV dtls=1 force_version=dtls1 trunc_hmac=1" \
             "$P_CLI dtls=1 request_size=1 trunc_hmac=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3968,7 +4283,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet DTLS 1.0, without EtM, truncated MAC" \
+run_test    "Small client packet DTLS 1.0, without EtM, truncated MAC" \
             "$P_SRV dtls=1 force_version=dtls1 trunc_hmac=1 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
@@ -3976,7 +4291,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
-run_test    "Small packet DTLS 1.2" \
+run_test    "Small client packet DTLS 1.2" \
             "$P_SRV dtls=1 force_version=dtls1_2" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3984,7 +4299,7 @@
             -s "Read from client: 1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
-run_test    "Small packet DTLS 1.2, without EtM" \
+run_test    "Small client packet DTLS 1.2, without EtM" \
             "$P_SRV dtls=1 force_version=dtls1_2 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -3993,7 +4308,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet DTLS 1.2, truncated hmac" \
+run_test    "Small client packet DTLS 1.2, truncated hmac" \
             "$P_SRV dtls=1 force_version=dtls1_2 trunc_hmac=1" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -4002,13 +4317,302 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Small packet DTLS 1.2, without EtM, truncated MAC" \
+run_test    "Small client packet DTLS 1.2, without EtM, truncated MAC" \
             "$P_SRV dtls=1 force_version=dtls1_2 trunc_hmac=1 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
             0 \
             -s "Read from client: 1 bytes read"
 
+# Tests for small server packets
+
+requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+run_test    "Small server packet SSLv3 BlockCipher" \
+            "$P_SRV response_size=1 min_version=ssl3" \
+            "$P_CLI force_version=ssl3 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+run_test    "Small server packet SSLv3 StreamCipher" \
+            "$P_SRV response_size=1 min_version=ssl3 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=ssl3 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.0 BlockCipher" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.0 BlockCipher, without EtM" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1 etm=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.0 BlockCipher, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.0 StreamCipher" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.0 StreamCipher, without EtM" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.0 StreamCipher, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
+             trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.1 BlockCipher" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.1 BlockCipher, without EtM" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.1 BlockCipher, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.1 StreamCipher" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.1 StreamCipher, without EtM" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.1 StreamCipher, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 BlockCipher" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 BlockCipher, without EtM" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 BlockCipher larger MAC" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.2 BlockCipher, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 StreamCipher" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 StreamCipher, without EtM" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.2 StreamCipher, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 AEAD" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.2 AEAD shorter tag" \
+            "$P_SRV response_size=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+# Tests for small server packets in DTLS
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+run_test    "Small server packet DTLS 1.0" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+run_test    "Small server packet DTLS 1.0, without EtM" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1 etm=0" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet DTLS 1.0, truncated hmac" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1 trunc_hmac=1" \
+            "$P_CLI dtls=1 trunc_hmac=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet DTLS 1.0, without EtM, truncated MAC" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1 trunc_hmac=1 etm=0" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+run_test    "Small server packet DTLS 1.2" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+run_test    "Small server packet DTLS 1.2, without EtM" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 etm=0" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet DTLS 1.2, truncated hmac" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 trunc_hmac=1" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Small server packet DTLS 1.2, without EtM, truncated MAC" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 trunc_hmac=1 etm=0" \
+            "$P_CLI dtls=1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
+            0 \
+            -c "Read from server: 1 bytes read"
+
 # A test for extensions in SSLv3
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
@@ -4019,7 +4623,7 @@
             -S "dumping 'client hello extensions'" \
             -S "server hello, total extension length:"
 
-# Test for large packets
+# Test for large client packets
 
 # How many fragments do we expect to write $1 bytes?
 fragments_for_write() {
@@ -4027,7 +4631,7 @@
 }
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
-run_test    "Large packet SSLv3 BlockCipher" \
+run_test    "Large client packet SSLv3 BlockCipher" \
             "$P_SRV min_version=ssl3" \
             "$P_CLI request_size=16384 force_version=ssl3 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4036,7 +4640,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
-run_test    "Large packet SSLv3 StreamCipher" \
+run_test    "Large client packet SSLv3 StreamCipher" \
             "$P_SRV min_version=ssl3 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=ssl3 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
@@ -4044,7 +4648,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.0 BlockCipher" \
+run_test    "Large client packet TLS 1.0 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4052,7 +4656,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.0 BlockCipher, without EtM" \
+run_test    "Large client packet TLS 1.0 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1 etm=0 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4060,7 +4664,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.0 BlockCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.0 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -4069,21 +4673,21 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1 etm=0 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.0 StreamCipher" \
+run_test    "Large client packet TLS 1.0 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.0 StreamCipher, without EtM" \
+run_test    "Large client packet TLS 1.0 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -4091,7 +4695,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.0 StreamCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.0 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -4099,7 +4703,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
@@ -4107,7 +4711,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.1 BlockCipher" \
+run_test    "Large client packet TLS 1.1 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4115,7 +4719,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.1 BlockCipher, without EtM" \
+run_test    "Large client packet TLS 1.1 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_1 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4123,7 +4727,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.1 BlockCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.1 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -4131,14 +4735,14 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.1 StreamCipher" \
+run_test    "Large client packet TLS 1.1 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
@@ -4146,7 +4750,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.1 StreamCipher, without EtM" \
+run_test    "Large client packet TLS 1.1 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -4155,7 +4759,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.1 StreamCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.1 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -4163,7 +4767,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
@@ -4171,7 +4775,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 BlockCipher" \
+run_test    "Large client packet TLS 1.2 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
@@ -4179,14 +4783,14 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 BlockCipher, without EtM" \
+run_test    "Large client packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 BlockCipher larger MAC" \
+run_test    "Large client packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
@@ -4195,7 +4799,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.2 BlockCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.2 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
@@ -4203,7 +4807,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
@@ -4211,7 +4815,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 StreamCipher" \
+run_test    "Large client packet TLS 1.2 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
@@ -4219,7 +4823,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 StreamCipher, without EtM" \
+run_test    "Large client packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
@@ -4227,7 +4831,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.2 StreamCipher, truncated MAC" \
+run_test    "Large client packet TLS 1.2 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
@@ -4235,7 +4839,7 @@
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
-run_test    "Large packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
+run_test    "Large client packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
@@ -4243,7 +4847,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 AEAD" \
+run_test    "Large client packet TLS 1.2 AEAD" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
@@ -4251,7 +4855,7 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
-run_test    "Large packet TLS 1.2 AEAD shorter tag" \
+run_test    "Large client packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
@@ -4259,6 +4863,386 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
+# Test for large server packets
+requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+run_test    "Large server packet SSLv3 StreamCipher" \
+            "$P_SRV response_size=16384 min_version=ssl3 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=ssl3 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+# Checking next 4 tests logs for 1n-1 split against BEAST too
+requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+run_test    "Large server packet SSLv3 BlockCipher" \
+            "$P_SRV response_size=16384 min_version=ssl3" \
+            "$P_CLI force_version=ssl3 recsplit=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"\
+            -c "16383 bytes read"\
+            -C "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.0 BlockCipher" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1 recsplit=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"\
+            -c "16383 bytes read"\
+            -C "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.0 BlockCipher, without EtM" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1 etm=0 recsplit=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 1 bytes read"\
+            -c "16383 bytes read"\
+            -C "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.0 BlockCipher truncated MAC" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1 recsplit=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -c "Read from server: 1 bytes read"\
+            -c "16383 bytes read"\
+            -C "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.0 StreamCipher truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
+             trunc_hmac=1" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.0 StreamCipher" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.0 StreamCipher, without EtM" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.0 StreamCipher, truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.1 BlockCipher" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.1 BlockCipher, without EtM" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_1 etm=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.1 BlockCipher truncated MAC" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=16384 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.1 StreamCipher" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.1 StreamCipher, without EtM" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.1 StreamCipher truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
+             trunc_hmac=1" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_1 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 BlockCipher" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 BlockCipher, without EtM" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 etm=0 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 BlockCipher larger MAC" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.2 BlockCipher truncated MAC" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA \
+             trunc_hmac=1" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=16384 trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 StreamCipher" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 StreamCipher, without EtM" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.2 StreamCipher truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
+             trunc_hmac=1" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
+run_test    "Large server packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
+            "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
+            0 \
+            -s "16384 bytes written in 1 fragments" \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 AEAD" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.2 AEAD shorter tag" \
+            "$P_SRV response_size=16384" \
+            "$P_CLI force_version=tls1_2 \
+             force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+# Tests for restartable ECC
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, default" \
+            "$P_SRV auth_mode=required" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1" \
+            0 \
+            -C "x509_verify_cert.*4b00" \
+            -C "mbedtls_pk_verify.*4b00" \
+            -C "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=0" \
+            "$P_SRV auth_mode=required" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=0" \
+            0 \
+            -C "x509_verify_cert.*4b00" \
+            -C "mbedtls_pk_verify.*4b00" \
+            -C "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=65535" \
+            "$P_SRV auth_mode=required" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=65535" \
+            0 \
+            -C "x509_verify_cert.*4b00" \
+            -C "mbedtls_pk_verify.*4b00" \
+            -C "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000" \
+            "$P_SRV auth_mode=required" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=1000" \
+            0 \
+            -c "x509_verify_cert.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -c "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000, badsign" \
+            "$P_SRV auth_mode=required \
+             crt_file=data_files/server5-badsign.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=1000" \
+            1 \
+            -c "x509_verify_cert.*4b00" \
+            -C "mbedtls_pk_verify.*4b00" \
+            -C "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00" \
+            -c "! The certificate is not correctly signed by the trusted CA" \
+            -c "! mbedtls_ssl_handshake returned" \
+            -c "X509 - Certificate verification failed"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000, auth_mode=optional badsign" \
+            "$P_SRV auth_mode=required \
+             crt_file=data_files/server5-badsign.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=1000 auth_mode=optional" \
+            0 \
+            -c "x509_verify_cert.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -c "mbedtls_pk_sign.*4b00" \
+            -c "! The certificate is not correctly signed by the trusted CA" \
+            -C "! mbedtls_ssl_handshake returned" \
+            -C "X509 - Certificate verification failed"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \
+            "$P_SRV auth_mode=required \
+             crt_file=data_files/server5-badsign.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             debug_level=1 ec_max_ops=1000 auth_mode=none" \
+            0 \
+            -C "x509_verify_cert.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -c "mbedtls_pk_sign.*4b00" \
+            -C "! The certificate is not correctly signed by the trusted CA" \
+            -C "! mbedtls_ssl_handshake returned" \
+            -C "X509 - Certificate verification failed"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: DTLS, max_ops=1000" \
+            "$P_SRV auth_mode=required dtls=1" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt  \
+             dtls=1 debug_level=1 ec_max_ops=1000" \
+            0 \
+            -c "x509_verify_cert.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -c "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000 no client auth" \
+            "$P_SRV" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             debug_level=1 ec_max_ops=1000" \
+            0 \
+            -c "x509_verify_cert.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00"
+
+requires_config_enabled MBEDTLS_ECP_RESTARTABLE
+run_test    "EC restart: TLS, max_ops=1000, ECDHE-PSK" \
+            "$P_SRV psk=abc123" \
+            "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \
+             psk=abc123 debug_level=1 ec_max_ops=1000" \
+            0 \
+            -C "x509_verify_cert.*4b00" \
+            -C "mbedtls_pk_verify.*4b00" \
+            -C "mbedtls_ecdh_make_public.*4b00" \
+            -C "mbedtls_pk_sign.*4b00"
+
 # Tests of asynchronous private key support in SSL
 
 requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
@@ -4877,6 +5861,958 @@
             -c "found fragmented DTLS handshake message" \
             -C "error"
 
+# Tests for sending fragmented handshake messages with DTLS
+#
+# Use client auth when we need the client to send large messages,
+# and use large cert chains on both sides too (the long chains we have all use
+# both RSA and ECDSA, but ideally we should have long chains with either).
+# Sizes reached (UDP payload):
+# - 2037B for server certificate
+# - 1542B for client certificate
+# - 1013B for newsessionticket
+# - all others below 512B
+# All those tests assume MAX_CONTENT_LEN is at least 2048
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: none (for reference)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=4096" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=4096" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -C "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: server only (max_frag_len)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=2048" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# With the MFL extension, the server has no way of forcing
+# the client to not exceed a certain MTU; hence, the following
+# test can't be replicated with an MTU proxy such as the one
+# `client-initiated, server only (max_frag_len)` below.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: server only (more) (max_frag_len)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=4096" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: client-initiated, server only (max_frag_len)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=none \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=2048" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=1024" \
+             0 \
+            -S "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# While not required by the standard defining the MFL extension
+# (according to which it only applies to records, not to datagrams),
+# Mbed TLS will never send datagrams larger than MFL + { Max record expansion },
+# as otherwise there wouldn't be any means to communicate MTU restrictions
+# to the peer.
+# The next test checks that no datagrams significantly larger than the
+# negotiated MFL are sent.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: client-initiated, server only (max_frag_len), proxy MTU" \
+            -p "$P_PXY mtu=1110" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=none \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=2048" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=1024" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: client-initiated, both (max_frag_len)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=2048" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=1024" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# While not required by the standard defining the MFL extension
+# (according to which it only applies to records, not to datagrams),
+# Mbed TLS will never send datagrams larger than MFL + { Max record expansion },
+# as otherwise there wouldn't be any means to communicate MTU restrictions
+# to the peer.
+# The next test checks that no datagrams significantly larger than the
+# negotiated MFL are sent.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: client-initiated, both (max_frag_len), proxy MTU" \
+            -p "$P_PXY mtu=1110" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=2048" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             max_frag_len=1024" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: none (for reference) (MTU)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             mtu=4096" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             mtu=4096" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -C "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: client (MTU)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=3500-60000 \
+             mtu=4096" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=3500-60000 \
+             mtu=1024" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -C "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: server (MTU)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             mtu=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             mtu=2048" \
+            0 \
+            -S "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: both (MTU=1024)" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             mtu=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=2500-60000 \
+             mtu=1024" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 512 with full config.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: both (MTU=512)" \
+            -p "$P_PXY mtu=512" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=2500-60000 \
+             mtu=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=2500-60000 \
+             mtu=512" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Test for automatic MTU reduction on repeated resend.
+# Forcing ciphersuite for this test to fit the MTU of 508 with full config.
+# The ratio of max/min timeout should ideally equal 4 to accept two
+# retransmissions, but in some cases (like both the server and client using
+# fragmentation and auto-reduction) an extra retransmission might occur,
+# hence the ratio of 8.
+not_with_valgrind
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU: auto-reduction" \
+            -p "$P_PXY mtu=508" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=400-3200" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=400-3200" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 508 with full config.
+only_with_valgrind
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU: auto-reduction" \
+            -p "$P_PXY mtu=508" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-10000" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=250-10000" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# the proxy shouldn't drop or mess up anything, so we shouldn't need to resend
+# OTOH the client might resend if the server is to slow to reset after sending
+# a HelloVerifyRequest, so only check for no retransmission server-side
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: proxy MTU, simple handshake (MTU=1024)" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 512 with full config.
+# the proxy shouldn't drop or mess up anything, so we shouldn't need to resend
+# OTOH the client might resend if the server is to slow to reset after sending
+# a HelloVerifyRequest, so only check for no retransmission server-side
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU, simple handshake (MTU=512)" \
+            -p "$P_PXY mtu=512" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+run_test    "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=1024)" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=10000-60000 \
+             mtu=1024 nbio=2" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=10000-60000 \
+             mtu=1024 nbio=2" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 512 with full config.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=512)" \
+            -p "$P_PXY mtu=512" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=10000-60000 \
+             mtu=512 nbio=2" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=10000-60000 \
+             mtu=512 nbio=2" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 1450 with full config.
+# This ensures things still work after session_reset().
+# It also exercises the "resumed handshake" flow.
+# Since we don't support reading fragmented ClientHello yet,
+# up the MTU to 1450 (larger than ClientHello with session ticket,
+# but still smaller than client's Certificate to ensure fragmentation).
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+# reco_delay avoids races where the client reconnects before the server has
+# resumed listening, which would result in a spurious autoreduction.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU, resumed handshake" \
+            -p "$P_PXY mtu=1450" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=10000-60000 \
+             mtu=1450" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=10000-60000 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             mtu=1450 reconnect=1 reco_delay=1" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+requires_config_enabled MBEDTLS_CHACHAPOLY_C
+run_test    "DTLS fragmenting: proxy MTU, ChachaPoly renego" \
+            -p "$P_PXY mtu=512" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             exchanges=2 renegotiation=1 \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             exchanges=2 renegotiation=1 renegotiate=1 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+run_test    "DTLS fragmenting: proxy MTU, AES-GCM renego" \
+            -p "$P_PXY mtu=512" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             exchanges=2 renegotiation=1 \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             exchanges=2 renegotiation=1 renegotiate=1 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=10000-60000 \
+             mtu=512" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CCM_C
+run_test    "DTLS fragmenting: proxy MTU, AES-CCM renego" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             exchanges=2 renegotiation=1 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             exchanges=2 renegotiation=1 renegotiate=1 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_config_enabled MBEDTLS_SSL_ENCRYPT_THEN_MAC
+run_test    "DTLS fragmenting: proxy MTU, AES-CBC EtM renego" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             exchanges=2 renegotiation=1 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             exchanges=2 renegotiation=1 renegotiate=1 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# An autoreduction on the client-side might happen if the server is
+# slow to reset, therefore omitting '-C "autoreduction"' below.
+not_with_valgrind # spurious autoreduction due to timeout
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+run_test    "DTLS fragmenting: proxy MTU, AES-CBC non-EtM renego" \
+            -p "$P_PXY mtu=1024" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             exchanges=2 renegotiation=1 \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 etm=0 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             exchanges=2 renegotiation=1 renegotiate=1 \
+             hs_timeout=10000-60000 \
+             mtu=1024" \
+            0 \
+            -S "autoreduction" \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 512 with full config.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+client_needs_more_time 2
+run_test    "DTLS fragmenting: proxy MTU + 3d" \
+            -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \
+            "$P_SRV dgram_packing=0 dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-10000 mtu=512" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=250-10000 mtu=512" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# Forcing ciphersuite for this test to fit the MTU of 512 with full config.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_GCM_C
+client_needs_more_time 2
+run_test    "DTLS fragmenting: proxy MTU + 3d, nbio" \
+            -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-10000 mtu=512 nbio=2" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
+             hs_timeout=250-10000 mtu=512 nbio=2" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
+# interop tests for DTLS fragmentating with reliable connection
+#
+# here and below we just want to test that the we fragment in a way that
+# pleases other implementations, so we don't need the peer to fragment
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_gnutls
+run_test    "DTLS fragmenting: gnutls server, DTLS 1.2" \
+            "$G_SRV -u" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             mtu=512 force_version=dtls1_2" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+requires_gnutls
+run_test    "DTLS fragmenting: gnutls server, DTLS 1.0" \
+            "$G_SRV -u" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             mtu=512 force_version=dtls1" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+# We use --insecure for the GnuTLS client because it expects
+# the hostname / IP it connects to to be the name used in the
+# certificate obtained from the server. Here, however, it
+# connects to 127.0.0.1 while our test certificates use 'localhost'
+# as the server name in the certificate. This will make the
+# certifiate validation fail, but passing --insecure makes
+# GnuTLS continue the connection nonetheless.
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_gnutls
+requires_not_i686
+run_test    "DTLS fragmenting: gnutls client, DTLS 1.2" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             mtu=512 force_version=dtls1_2" \
+            "$G_CLI -u --insecure 127.0.0.1" \
+            0 \
+            -s "fragmenting handshake message"
+
+# See previous test for the reason to use --insecure
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+requires_gnutls
+requires_not_i686
+run_test    "DTLS fragmenting: gnutls client, DTLS 1.0" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             mtu=512 force_version=dtls1" \
+            "$G_CLI -u --insecure 127.0.0.1" \
+            0 \
+            -s "fragmenting handshake message"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "DTLS fragmenting: openssl server, DTLS 1.2" \
+            "$O_SRV -dtls1_2 -verify 10" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             mtu=512 force_version=dtls1_2" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+run_test    "DTLS fragmenting: openssl server, DTLS 1.0" \
+            "$O_SRV -dtls1 -verify 10" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             mtu=512 force_version=dtls1" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "DTLS fragmenting: openssl client, DTLS 1.2" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             mtu=512 force_version=dtls1_2" \
+            "$O_CLI -dtls1_2" \
+            0 \
+            -s "fragmenting handshake message"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+run_test    "DTLS fragmenting: openssl client, DTLS 1.0" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             mtu=512 force_version=dtls1" \
+            "$O_CLI -dtls1" \
+            0 \
+            -s "fragmenting handshake message"
+
+# interop tests for DTLS fragmentating with unreliable connection
+#
+# again we just want to test that the we fragment in a way that
+# pleases other implementations, so we don't need the peer to fragment
+requires_gnutls_next
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, gnutls server, DTLS 1.2" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$G_NEXT_SRV -u" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+requires_gnutls_next
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, gnutls server, DTLS 1.0" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$G_NEXT_SRV -u" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+## The two tests below are disabled due to a bug in GnuTLS client that causes
+## handshake failures when the NewSessionTicket message is lost, see
+## https://gitlab.com/gnutls/gnutls/issues/543
+## We can re-enable them when a fixed version fo GnuTLS is available
+## and installed in our CI system.
+skip_next_test
+requires_gnutls
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, gnutls client, DTLS 1.2" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+           "$G_CLI -u --insecure 127.0.0.1" \
+            0 \
+            -s "fragmenting handshake message"
+
+skip_next_test
+requires_gnutls
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, gnutls client, DTLS 1.0" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1" \
+           "$G_CLI -u --insecure 127.0.0.1" \
+            0 \
+            -s "fragmenting handshake message"
+
+## Interop test with OpenSSL might trigger a bug in recent versions (including
+## all versions installed on the CI machines), reported here:
+## Bug report: https://github.com/openssl/openssl/issues/6902
+## They should be re-enabled once a fixed version of OpenSSL is available
+## (this should happen in some 1.1.1_ release according to the ticket).
+skip_next_test
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, openssl server, DTLS 1.2" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$O_SRV -dtls1_2 -verify 10" \
+            "$P_CLI dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+skip_next_test
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, openssl server, DTLS 1.0" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$O_SRV -dtls1 -verify 10" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+             crt_file=data_files/server8_int-ca2.crt \
+             key_file=data_files/server8.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1" \
+            0 \
+            -c "fragmenting handshake message" \
+            -C "error"
+
+skip_next_test
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, openssl client, DTLS 1.2" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$P_SRV dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+            "$O_CLI -dtls1_2" \
+            0 \
+            -s "fragmenting handshake message"
+
+# -nbio is added to prevent s_client from blocking in case of duplicated
+# messages at the end of the handshake
+skip_next_test
+requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
+requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+client_needs_more_time 4
+run_test    "DTLS fragmenting: 3d, openssl client, DTLS 1.0" \
+            -p "$P_PXY drop=8 delay=8 duplicate=8" \
+            "$P_SRV dgram_packing=0 dtls=1 debug_level=2 \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             hs_timeout=250-60000 mtu=512 force_version=dtls1" \
+            "$O_CLI -nbio -dtls1" \
+            0 \
+            -s "fragmenting handshake message"
+
 # Tests for specific things with "unreliable" UDP connection
 
 not_with_valgrind # spurious resend due to timeout
@@ -4898,8 +6834,8 @@
 not_with_valgrind # spurious resend due to timeout
 run_test    "DTLS proxy: duplicate every packet" \
             -p "$P_PXY duplicate=1" \
-            "$P_SRV dtls=1 debug_level=2" \
-            "$P_CLI dtls=1 debug_level=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
             0 \
             -c "replayed record" \
             -s "replayed record" \
@@ -4911,8 +6847,8 @@
 
 run_test    "DTLS proxy: duplicate every packet, server anti-replay off" \
             -p "$P_PXY duplicate=1" \
-            "$P_SRV dtls=1 debug_level=2 anti_replay=0" \
-            "$P_CLI dtls=1 debug_level=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2 anti_replay=0" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
             0 \
             -c "replayed record" \
             -S "replayed record" \
@@ -4925,24 +6861,24 @@
 
 run_test    "DTLS proxy: multiple records in same datagram" \
             -p "$P_PXY pack=50" \
-            "$P_SRV dtls=1 debug_level=2" \
-            "$P_CLI dtls=1 debug_level=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
             0 \
             -c "next record in same datagram" \
             -s "next record in same datagram"
 
 run_test    "DTLS proxy: multiple records in same datagram, duplicate every packet" \
             -p "$P_PXY pack=50 duplicate=1" \
-            "$P_SRV dtls=1 debug_level=2" \
-            "$P_CLI dtls=1 debug_level=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=2" \
             0 \
             -c "next record in same datagram" \
             -s "next record in same datagram"
 
 run_test    "DTLS proxy: inject invalid AD record, default badmac_limit" \
             -p "$P_PXY bad_ad=1" \
-            "$P_SRV dtls=1 debug_level=1" \
-            "$P_CLI dtls=1 debug_level=1 read_timeout=100" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=1" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \
             0 \
             -c "discarding invalid record (mac)" \
             -s "discarding invalid record (mac)" \
@@ -4953,8 +6889,8 @@
 
 run_test    "DTLS proxy: inject invalid AD record, badmac_limit 1" \
             -p "$P_PXY bad_ad=1" \
-            "$P_SRV dtls=1 debug_level=1 badmac_limit=1" \
-            "$P_CLI dtls=1 debug_level=1 read_timeout=100" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=1" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \
             1 \
             -C "discarding invalid record (mac)" \
             -S "discarding invalid record (mac)" \
@@ -4965,8 +6901,8 @@
 
 run_test    "DTLS proxy: inject invalid AD record, badmac_limit 2" \
             -p "$P_PXY bad_ad=1" \
-            "$P_SRV dtls=1 debug_level=1 badmac_limit=2" \
-            "$P_CLI dtls=1 debug_level=1 read_timeout=100" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100" \
             0 \
             -c "discarding invalid record (mac)" \
             -s "discarding invalid record (mac)" \
@@ -4977,8 +6913,8 @@
 
 run_test    "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\
             -p "$P_PXY bad_ad=1" \
-            "$P_SRV dtls=1 debug_level=1 badmac_limit=2 exchanges=2" \
-            "$P_CLI dtls=1 debug_level=1 read_timeout=100 exchanges=2" \
+            "$P_SRV dtls=1 dgram_packing=0 debug_level=1 badmac_limit=2 exchanges=2" \
+            "$P_CLI dtls=1 dgram_packing=0 debug_level=1 read_timeout=100 exchanges=2" \
             1 \
             -c "discarding invalid record (mac)" \
             -s "discarding invalid record (mac)" \
@@ -4989,22 +6925,190 @@
 
 run_test    "DTLS proxy: delay ChangeCipherSpec" \
             -p "$P_PXY delay_ccs=1" \
-            "$P_SRV dtls=1 debug_level=1" \
-            "$P_CLI dtls=1 debug_level=1" \
+            "$P_SRV dtls=1 debug_level=1 dgram_packing=0" \
+            "$P_CLI dtls=1 debug_level=1 dgram_packing=0" \
             0 \
             -c "record from another epoch" \
             -s "record from another epoch" \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
 
+# Tests for reordering support with DTLS
+
+run_test    "DTLS reordering: Buffer out-of-order handshake message on client" \
+            -p "$P_PXY delay_srv=ServerHello" \
+            "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -c "Buffering HS message" \
+            -c "Next handshake message has been buffered - load"\
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load"\
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+run_test    "DTLS reordering: Buffer out-of-order handshake message fragment on client" \
+            -p "$P_PXY delay_srv=ServerHello" \
+            "$P_SRV mtu=512 dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -c "Buffering HS message" \
+            -c "found fragmented DTLS handshake message"\
+            -c "Next handshake message 1 not or only partially bufffered" \
+            -c "Next handshake message has been buffered - load"\
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load"\
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+# The client buffers the ServerKeyExchange before receiving the fragmented
+# Certificate message; at the time of writing, together these are aroudn 1200b
+# in size, so that the bound below ensures that the certificate can be reassembled
+# while keeping the ServerKeyExchange.
+requires_config_value_at_least "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 1300
+run_test    "DTLS reordering: Buffer out-of-order hs msg before reassembling next" \
+            -p "$P_PXY delay_srv=Certificate delay_srv=Certificate" \
+            "$P_SRV mtu=512 dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -c "Buffering HS message" \
+            -c "Next handshake message has been buffered - load"\
+            -C "attempt to make space by freeing buffered messages" \
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load"\
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+# The size constraints ensure that the delayed certificate message can't
+# be reassembled while keeping the ServerKeyExchange message, but it can
+# when dropping it first.
+requires_config_value_at_least "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 900
+requires_config_value_at_most "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 1299
+run_test    "DTLS reordering: Buffer out-of-order hs msg before reassembling next, free buffered msg" \
+            -p "$P_PXY delay_srv=Certificate delay_srv=Certificate" \
+            "$P_SRV mtu=512 dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -c "Buffering HS message" \
+            -c "attempt to make space by freeing buffered future messages" \
+            -c "Enough space available after freeing buffered HS messages" \
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load"\
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+run_test    "DTLS reordering: Buffer out-of-order handshake message on server" \
+            -p "$P_PXY delay_cli=Certificate" \
+            "$P_SRV dgram_packing=0 auth_mode=required cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -C "Buffering HS message" \
+            -C "Next handshake message has been buffered - load"\
+            -s "Buffering HS message" \
+            -s "Next handshake message has been buffered - load" \
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+run_test    "DTLS reordering: Buffer out-of-order CCS message on client"\
+            -p "$P_PXY delay_srv=NewSessionTicket" \
+            "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -C "Buffering HS message" \
+            -C "Next handshake message has been buffered - load"\
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load" \
+            -c "Injecting buffered CCS message" \
+            -c "Remember CCS message" \
+            -S "Injecting buffered CCS message" \
+            -S "Remember CCS message"
+
+run_test    "DTLS reordering: Buffer out-of-order CCS message on server"\
+            -p "$P_PXY delay_cli=ClientKeyExchange" \
+            "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -C "Buffering HS message" \
+            -C "Next handshake message has been buffered - load"\
+            -S "Buffering HS message" \
+            -S "Next handshake message has been buffered - load" \
+            -C "Injecting buffered CCS message" \
+            -C "Remember CCS message" \
+            -s "Injecting buffered CCS message" \
+            -s "Remember CCS message"
+
+run_test    "DTLS reordering: Buffer encrypted Finished message" \
+            -p "$P_PXY delay_ccs=1" \
+            "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
+            hs_timeout=2500-60000" \
+            0 \
+            -s "Buffer record from epoch 1" \
+            -s "Found buffered record from current epoch - load" \
+            -c "Buffer record from epoch 1" \
+            -c "Found buffered record from current epoch - load"
+
+# In this test, both the fragmented NewSessionTicket and the ChangeCipherSpec
+# from the server are delayed, so that the encrypted Finished message
+# is received and buffered. When the fragmented NewSessionTicket comes
+# in afterwards, the encrypted Finished message must be freed in order
+# to make space for the NewSessionTicket to be reassembled.
+# This works only in very particular circumstances:
+# - MBEDTLS_SSL_DTLS_MAX_BUFFERING must be large enough to allow buffering
+#   of the NewSessionTicket, but small enough to also allow buffering of
+#   the encrypted Finished message.
+# - The MTU setting on the server must be so small that the NewSessionTicket
+#   needs to be fragmented.
+# - All messages sent by the server must be small enough to be either sent
+#   without fragmentation or be reassembled within the bounds of
+#   MBEDTLS_SSL_DTLS_MAX_BUFFERING. Achieve this by testing with a PSK-based
+#   handshake, omitting CRTs.
+requires_config_value_at_least "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 240
+requires_config_value_at_most "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 280
+run_test    "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket" \
+            -p "$P_PXY delay_srv=NewSessionTicket delay_srv=NewSessionTicket delay_ccs=1" \
+            "$P_SRV mtu=190 dgram_packing=0 psk=abc123 psk_identity=foo cookies=0 dtls=1 debug_level=2" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 psk=abc123 psk_identity=foo" \
+            0 \
+            -s "Buffer record from epoch 1" \
+            -s "Found buffered record from current epoch - load" \
+            -c "Buffer record from epoch 1" \
+            -C "Found buffered record from current epoch - load" \
+            -c "Enough space available after freeing future epoch record"
+
 # Tests for "randomly unreliable connection": try a variety of flows and peers
 
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
             -s "Extra-header:" \
@@ -5013,8 +7117,8 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, \"short\" RSA handshake" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
             0 \
             -s "Extra-header:" \
@@ -5023,8 +7127,8 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, \"short\" (no ticket, no cli_auth) FS handshake" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0" \
             0 \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
@@ -5032,8 +7136,8 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, FS, client auth" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=required" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=required" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0" \
             0 \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
@@ -5041,8 +7145,8 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, FS, ticket" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=none" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1 auth_mode=none" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1" \
             0 \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
@@ -5050,8 +7154,8 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=required" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1 auth_mode=required" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1" \
             0 \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
@@ -5059,9 +7163,9 @@
 client_needs_more_time 2
 run_test    "DTLS proxy: 3d, max handshake, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 nbio=2 tickets=1 \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 nbio=2 tickets=1 \
              auth_mode=required" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 nbio=2 tickets=1" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 nbio=2 tickets=1" \
             0 \
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
@@ -5069,9 +7173,9 @@
 client_needs_more_time 4
 run_test    "DTLS proxy: 3d, min handshake, resumption" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 debug_level=3" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -5083,9 +7187,9 @@
 client_needs_more_time 4
 run_test    "DTLS proxy: 3d, min handshake, resumption, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 debug_level=3 nbio=2" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 nbio=2" \
             0 \
@@ -5098,9 +7202,9 @@
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 run_test    "DTLS proxy: 3d, min handshake, client-initiated renego" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 renegotiation=1 debug_level=2" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              renegotiate=1 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -5113,9 +7217,9 @@
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 run_test    "DTLS proxy: 3d, min handshake, client-initiated renego, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 renegotiation=1 debug_level=2" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              renegotiate=1 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -5128,10 +7232,10 @@
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 run_test    "DTLS proxy: 3d, min handshake, server-initiated renego" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \
              debug_level=2" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              renegotiation=1 exchanges=4 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -5144,10 +7248,10 @@
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 run_test    "DTLS proxy: 3d, min handshake, server-initiated renego, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
-            "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \
+            "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
              psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \
              debug_level=2 nbio=2" \
-            "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
              renegotiation=1 exchanges=4 debug_level=2 nbio=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -5156,30 +7260,38 @@
             -s "Extra-header:" \
             -c "HTTP/1.0 200 OK"
 
+## Interop tests with OpenSSL might trigger a bug in recent versions (including
+## all versions installed on the CI machines), reported here:
+## Bug report: https://github.com/openssl/openssl/issues/6902
+## They should be re-enabled once a fixed version of OpenSSL is available
+## (this should happen in some 1.1.1_ release according to the ticket).
+skip_next_test
 client_needs_more_time 6
 not_with_valgrind # risk of non-mbedtls peer timing out
 run_test    "DTLS proxy: 3d, openssl server" \
             -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \
             "$O_SRV -dtls1 -mtu 2048" \
-            "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000 tickets=0" \
             0 \
             -c "HTTP/1.0 200 OK"
 
+skip_next_test # see above
 client_needs_more_time 8
 not_with_valgrind # risk of non-mbedtls peer timing out
 run_test    "DTLS proxy: 3d, openssl server, fragmentation" \
             -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \
             "$O_SRV -dtls1 -mtu 768" \
-            "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000 tickets=0" \
             0 \
             -c "HTTP/1.0 200 OK"
 
+skip_next_test # see above
 client_needs_more_time 8
 not_with_valgrind # risk of non-mbedtls peer timing out
 run_test    "DTLS proxy: 3d, openssl server, fragmentation, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \
             "$O_SRV -dtls1 -mtu 768" \
-            "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2 tickets=0" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000 nbio=2 tickets=0" \
             0 \
             -c "HTTP/1.0 200 OK"
 
@@ -5189,7 +7301,7 @@
 run_test    "DTLS proxy: 3d, gnutls server" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$G_SRV -u --mtu 2048 -a" \
-            "$P_CLI dtls=1 hs_timeout=250-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000" \
             0 \
             -s "Extra-header:" \
             -c "Extra-header:"
@@ -5200,7 +7312,7 @@
 run_test    "DTLS proxy: 3d, gnutls server, fragmentation" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$G_SRV -u --mtu 512" \
-            "$P_CLI dtls=1 hs_timeout=250-60000" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000" \
             0 \
             -s "Extra-header:" \
             -c "Extra-header:"
@@ -5211,7 +7323,7 @@
 run_test    "DTLS proxy: 3d, gnutls server, fragmentation, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$G_SRV -u --mtu 512" \
-            "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2" \
+            "$P_CLI dgram_packing=0 dtls=1 hs_timeout=500-60000 nbio=2" \
             0 \
             -s "Extra-header:" \
             -c "Extra-header:"
diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data
index f7119de..0165a7e 100644
--- a/tests/suites/test_suite_ecdh.data
+++ b/tests/suites/test_suite_ecdh.data
@@ -37,3 +37,35 @@
 ECDH exchange #2
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1
+
+ECDH restartable rfc 5903 p256 restart enabled max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:0:0:0
+
+ECDH restartable rfc 5903 p256 restart enabled max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:1:1:10000
+
+ECDH restartable rfc 5903 p256 restart enabled max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:10000:0:0
+
+ECDH restartable rfc 5903 p256 restart enabled max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:250:2:32
+
+ECDH restartable rfc 5903 p256 restart disabled max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0:0
+
+ECDH restartable rfc 5903 p256 restart disabled max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:1:0:0
+
+ECDH restartable rfc 5903 p256 restart disabled max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:10000:0:0
+
+ECDH restartable rfc 5903 p256 restart disabled max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:250:0:0
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index a2c7ced..9652308 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -156,3 +156,120 @@
     mbedtls_ecdh_free( &cli );
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str,
+                   int enable, int max_ops, int min_restart, int max_restart )
+{
+    int ret;
+    mbedtls_ecdh_context srv, cli;
+    unsigned char buf[1000];
+    const unsigned char *vbuf;
+    size_t len;
+    unsigned char z[MBEDTLS_ECP_MAX_BYTES];
+    size_t z_len;
+    unsigned char rnd_buf_A[MBEDTLS_ECP_MAX_BYTES];
+    unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES];
+    rnd_buf_info rnd_info_A, rnd_info_B;
+    int cnt_restart;
+
+    mbedtls_ecdh_init( &srv );
+    mbedtls_ecdh_init( &cli );
+
+    z_len = unhexify( z, z_str );
+
+    rnd_info_A.buf = rnd_buf_A;
+    rnd_info_A.length = unhexify( rnd_buf_A, dA_str );
+
+    rnd_info_B.buf = rnd_buf_B;
+    rnd_info_B.length = unhexify( rnd_buf_B, dB_str );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 );
+
+    /* otherwise we would have to fix the random buffer,
+     * as in ecdh_primitive_test_vec */
+    TEST_ASSERT( srv.grp.nbits % 8 == 0 );
+
+    /* set up restart parameters */
+    mbedtls_ecp_set_max_ops( max_ops );
+
+    if( enable)
+    {
+        mbedtls_ecdh_enable_restart( &srv );
+        mbedtls_ecdh_enable_restart( &cli );
+    }
+
+    /* server writes its paramaters */
+    memset( buf, 0x00, sizeof( buf ) );
+    len = 0;
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdh_make_params( &srv, &len, buf, sizeof( buf ),
+                                        rnd_buffer_rand, &rnd_info_A );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    /* client read server params */
+    vbuf = buf;
+    TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
+
+    /* client writes its key share */
+    memset( buf, 0x00, sizeof( buf ) );
+    len = 0;
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdh_make_public( &cli, &len, buf, sizeof( buf ),
+                                        rnd_buffer_rand, &rnd_info_B );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    /* server reads client key share */
+    TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
+
+    /* server computes shared secret */
+    memset( buf, 0, sizeof( buf ) );
+    len = 0;
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdh_calc_secret( &srv, &len, buf, sizeof( buf ),
+                                              NULL, NULL );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    TEST_ASSERT( len == z_len );
+    TEST_ASSERT( memcmp( buf, z, len ) == 0 );
+
+    /* client computes shared secret */
+    memset( buf, 0, sizeof( buf ) );
+    len = 0;
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdh_calc_secret( &cli, &len, buf, sizeof( buf ),
+                                              NULL, NULL );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    TEST_ASSERT( len == z_len );
+    TEST_ASSERT( memcmp( buf, z, len ) == 0 );
+
+exit:
+    mbedtls_ecdh_free( &srv );
+    mbedtls_ecdh_free( &cli );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data
index 19c51d3..7e6ec6c 100644
--- a/tests/suites/test_suite_ecdsa.data
+++ b/tests/suites/test_suite_ecdsa.data
@@ -50,7 +50,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 ecdsa_write_read_random:MBEDTLS_ECP_DP_SECP521R1
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p192 sha1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA1:"sample":"98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF":"57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64"
 
@@ -58,7 +58,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA224:"sample":"A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5":"E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A"
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p192 sha256
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA256:"sample":"4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55":"CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85"
 
@@ -66,11 +66,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA384:"sample":"DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5":"C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E"
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p192 sha512
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA512:"sample":"4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8":"3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67"
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p192 sha1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA1:"test":"0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D":"EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7"
 
@@ -78,7 +78,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA224:"test":"6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34":"B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293"
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p192 sha256
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA256:"test":"3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE":"5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F"
 
@@ -86,11 +86,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA384:"test":"B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367":"7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A"
 
-ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p192 sha512
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA512:"test":"FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739":"74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p224 sha1
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA1:"sample":"22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC":"66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69"
 
@@ -98,7 +98,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA224:"sample":"1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E":"A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p224 sha256
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA256:"sample":"61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA":"BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101"
 
@@ -106,11 +106,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA384:"sample":"0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953":"830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p224 sha512
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA512:"sample":"074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397":"A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p224 sha1
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA1:"test":"DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C":"95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2"
 
@@ -118,7 +118,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA224:"test":"C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019":"902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p224 sha256
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA256:"test":"AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6":"178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD"
 
@@ -126,11 +126,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA384:"test":"389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4":"414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB"
 
-ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p224 sha512
 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA512:"test":"049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C":"077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p256 sha1
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA1:"sample":"61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32":"6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB"
 
@@ -138,7 +138,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA224:"sample":"53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F":"B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p256 sha256
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"sample":"EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716":"F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
 
@@ -146,11 +146,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA384:"sample":"0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719":"4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p256 sha512
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA512:"sample":"8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00":"2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p256 sha1
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA1:"test":"0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89":"01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1"
 
@@ -158,7 +158,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA224:"test":"C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692":"C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p256 sha256
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367":"019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"
 
@@ -166,11 +166,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA384:"test":"83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6":"8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C"
 
-ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p256 sha512
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA512:"test":"461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04":"39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p384 sha1
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA1:"sample":"EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2":"A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443"
 
@@ -178,7 +178,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA224:"sample":"42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122":"9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p384 sha256
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA256:"sample":"21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD":"F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0"
 
@@ -186,11 +186,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA384:"sample":"94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46":"99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p384 sha512
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA512:"sample":"ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709":"512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p384 sha1
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA1:"test":"4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7":"D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282"
 
@@ -198,7 +198,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA224:"test":"E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72":"07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p384 sha256
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA256:"test":"6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B":"2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265"
 
@@ -206,11 +206,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA384:"test":"8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB":"DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5"
 
-ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p384 sha512
 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA512:"test":"A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277":"976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p521 sha1
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA1:"sample":"0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D":"0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16"
 
@@ -218,7 +218,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA224:"sample":"1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E":"050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p521 sha256
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA256:"sample":"1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7":"04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC"
 
@@ -226,11 +226,11 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA384:"sample":"1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451":"1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p521 sha512
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"sample":"0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA":"0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha1
+ECDSA deterministic test vector rfc 6979 p521 sha1
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA1_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA1:"test":"13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367":"1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF"
 
@@ -238,7 +238,7 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA224:"test":"1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB":"177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha256
+ECDSA deterministic test vector rfc 6979 p521 sha256
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA256:"test":"00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8":"0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86"
 
@@ -246,10 +246,42 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA384:"test":"14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C":"133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979"
 
-ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha512
+ECDSA deterministic test vector rfc 6979 p521 sha512
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C
 ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"test":"13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D":"1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3"
 
+ECDSA restartable read-verify: max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":0:0:0
+
+ECDSA restartable read-verify: max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":1:42:10000
+
+ECDSA restartable read-verify: max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":10000:0:0
+
+ECDSA restartable read-verify: max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":250:4:64
+
+ECDSA restartable sign-write: secp256r1 max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0
+
+ECDSA restartable sign-write: secp256r1 restart max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000
+
+ECDSA restartable sign-write: secp256r1 restart max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0
+
+ECDSA restartable sign-write: secp256r1 restart max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:32
+
 ECDSA zero private parameter p192
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdsa_prim_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"0":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945":"9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B15":"BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9C":"98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF":"57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64":MBEDTLS_ERR_ECP_INVALID_KEY
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index 48ce586..79421c4 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -84,6 +84,16 @@
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
 
         TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash->x, hash->len, &Q, &r_check, &s_check ) == 0 );
+
+        TEST_ASSERT( mbedtls_mpi_sub_int( &r, &r, 1 ) == 0 );
+        TEST_ASSERT( mbedtls_mpi_add_int( &s, &s, 1 ) == 0 );
+
+        TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash->x, hash->len,
+                     &Q, &r, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+        TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash->x, hash->len,
+                     &Q, &r_check, &s ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+        TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash->x, hash->len,
+                     &grp.G, &r_check, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
     }
 
 exit:
@@ -177,13 +187,13 @@
     /* try modifying r */
     sig[10]++;
     TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
-                 sig, sig_len ) != 0 );
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
     sig[10]--;
 
     /* try modifying s */
     sig[sig_len - 1]++;
     TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
-                 sig, sig_len ) != 0 );
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
     sig[sig_len - 1]--;
 
 exit:
@@ -191,3 +201,130 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void ecdsa_read_restart( int id, char *k_str, char *h_str, char *s_str,
+                         int max_ops, int min_restart, int max_restart )
+{
+    mbedtls_ecdsa_context ctx;
+    mbedtls_ecdsa_restart_ctx rs_ctx;
+    unsigned char hash[64];
+    unsigned char sig[200];
+    unsigned char pk[65];
+    size_t sig_len, hash_len, pk_len;
+    int ret, cnt_restart;
+
+    mbedtls_ecdsa_init( &ctx );
+    mbedtls_ecdsa_restart_init( &rs_ctx );
+
+    hash_len = unhexify(hash, h_str);
+    sig_len = unhexify(sig, s_str);
+    pk_len = unhexify(pk, k_str);
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &ctx.grp, id ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_point_read_binary( &ctx.grp, &ctx.Q, pk, pk_len ) == 0 );
+
+    mbedtls_ecp_set_max_ops( max_ops );
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdsa_read_signature_restartable( &ctx,
+                            hash, hash_len, sig, sig_len, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    /* try modifying r */
+    sig[10]++;
+    do {
+        ret = mbedtls_ecdsa_read_signature_restartable( &ctx,
+                            hash, hash_len, sig, sig_len, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    TEST_ASSERT( ret == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[10]--;
+
+    /* try modifying s */
+    sig[sig_len - 1]++;
+    do {
+        ret = mbedtls_ecdsa_read_signature_restartable( &ctx,
+                            hash, hash_len, sig, sig_len, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    TEST_ASSERT( ret == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[sig_len - 1]--;
+
+    /* Do we leak memory when aborting an operation?
+     * This test only makes sense when we actually restart */
+    if( min_restart > 0 )
+    {
+        ret = mbedtls_ecdsa_read_signature_restartable( &ctx,
+                            hash, hash_len, sig, sig_len, &rs_ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    }
+
+exit:
+    mbedtls_ecdsa_free( &ctx );
+    mbedtls_ecdsa_restart_free( &rs_ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_DETERMINISTIC */
+void ecdsa_write_restart( int id, char *d_str, int md_alg,
+                          char *msg, char *sig_str,
+                          int max_ops, int min_restart, int max_restart )
+{
+    int ret, cnt_restart;
+    mbedtls_ecdsa_restart_ctx rs_ctx;
+    mbedtls_ecdsa_context ctx;
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
+    unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN];
+    size_t hlen, slen, slen_check;
+    const mbedtls_md_info_t *md_info;
+
+    mbedtls_ecdsa_restart_init( &rs_ctx );
+    mbedtls_ecdsa_init( &ctx );
+    memset( hash, 0, sizeof( hash ) );
+    memset( sig, 0, sizeof( sig ) );
+    memset( sig_check, 0, sizeof( sig_check ) );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &ctx.grp, id ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &ctx.d, 16, d_str ) == 0 );
+    slen_check = unhexify( sig_check, sig_str );
+
+    md_info = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md_info != NULL );
+
+    hlen = mbedtls_md_get_size( md_info );
+    mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
+
+    mbedtls_ecp_set_max_ops( max_ops );
+
+    slen = sizeof( sig );
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_ecdsa_write_signature_restartable( &ctx,
+                md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( slen == slen_check );
+    TEST_ASSERT( memcmp( sig, sig_check, slen ) == 0 );
+
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    /* Do we leak memory when aborting an operation?
+     * This test only makes sense when we actually restart */
+    if( min_restart > 0 )
+    {
+        ret = mbedtls_ecdsa_write_signature_restartable( &ctx,
+                md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    }
+
+exit:
+    mbedtls_ecdsa_restart_free( &rs_ctx );
+    mbedtls_ecdsa_free( &ctx );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index e168090..321a1b4 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -348,3 +348,35 @@
 
 ECP selftest
 ecp_selftest:
+
+ECP restartable mul secp256r1 max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":0:0:0
+
+ECP restartable mul secp256r1 max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":1:1:5000
+
+ECP restartable mul secp256r1 max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":10000:0:0
+
+ECP restartable mul secp256r1 max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":250:2:32
+
+ECP restartable muladd secp256r1 max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":0:0:0
+
+ECP restartable muladd secp256r1 max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":1:1:10000
+
+ECP restartable muladd secp256r1 max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":10000:0:0
+
+ECP restartable muladd secp256r1 max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":250:4:64
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index d79a6b3..65c487e 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -2,6 +2,10 @@
 #include "mbedtls/ecp.h"
 
 #define ECP_PF_UNKNOWN     -1
+
+#define ECP_PT_RESET( x )           \
+    mbedtls_ecp_point_free( x );    \
+    mbedtls_ecp_point_init( x );
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -52,6 +56,173 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void ecp_test_vect_restart( int id,
+                            char *dA_str, char *xA_str, char *yA_str,
+                            char *dB_str,  char *xZ_str, char *yZ_str,
+                            int max_ops, int min_restarts, int max_restarts )
+{
+    /*
+     * Test for early restart. Based on test vectors like ecp_test_vect(),
+     * but for the sake of simplicity only does half of each side. It's
+     * important to test both base point and random point, though, as memory
+     * management is different in each case.
+     *
+     * Don't try using too precise bounds for restarts as the exact number
+     * will depend on settings such as MBEDTLS_ECP_FIXED_POINT_OPTIM and
+     * MBEDTLS_ECP_WINDOW_SIZE, as well as implementation details that may
+     * change in the future. A factor 2 is a minimum safety margin.
+     *
+     * For reference, with mbed TLS 2.4 and default settings, for P-256:
+     * - Random point mult:     ~3250M
+     * - Cold base point mult:  ~3300M
+     * - Hot base point mult:   ~1100M
+     * With MBEDTLS_ECP_WINDOW_SIZE set to 2 (minimum):
+     * - Random point mult:     ~3850M
+     */
+    mbedtls_ecp_restart_ctx ctx;
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point R, P;
+    mbedtls_mpi dA, xA, yA, dB, xZ, yZ;
+    int cnt_restarts;
+    int ret;
+
+    mbedtls_ecp_restart_init( &ctx );
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &R ); mbedtls_ecp_point_init( &P );
+    mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &xA ); mbedtls_mpi_init( &yA );
+    mbedtls_mpi_init( &dB ); mbedtls_mpi_init( &xZ ); mbedtls_mpi_init( &yZ );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &dA, 16, dA_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &xA, 16, xA_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &yA, 16, yA_str ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &dB, 16, dB_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &xZ, 16, xZ_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &yZ, 16, yZ_str ) == 0 );
+
+    mbedtls_ecp_set_max_ops( (unsigned) max_ops );
+
+    /* Base point case */
+    cnt_restarts = 0;
+    do {
+        ECP_PT_RESET( &R );
+        ret = mbedtls_ecp_mul_restartable( &grp, &R, &dA, &grp.G, NULL, NULL, &ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xA ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yA ) == 0 );
+
+    TEST_ASSERT( cnt_restarts >= min_restarts );
+    TEST_ASSERT( cnt_restarts <= max_restarts );
+
+    /* Non-base point case */
+    mbedtls_ecp_copy( &P, &R );
+    cnt_restarts = 0;
+    do {
+        ECP_PT_RESET( &R );
+        ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &P, NULL, NULL, &ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xZ ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yZ ) == 0 );
+
+    TEST_ASSERT( cnt_restarts >= min_restarts );
+    TEST_ASSERT( cnt_restarts <= max_restarts );
+
+    /* Do we leak memory when aborting an operation?
+     * This test only makes sense when we actually restart */
+    if( min_restarts > 0 )
+    {
+        ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &P, NULL, NULL, &ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    }
+
+exit:
+    mbedtls_ecp_restart_free( &ctx );
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &R ); mbedtls_ecp_point_free( &P );
+    mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &xA ); mbedtls_mpi_free( &yA );
+    mbedtls_mpi_free( &dB ); mbedtls_mpi_free( &xZ ); mbedtls_mpi_free( &yZ );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
+void ecp_muladd_restart( int id, char *xR_str, char *yR_str,
+                         char *u1_str, char *u2_str,
+                         char *xQ_str, char *yQ_str,
+                         int max_ops, int min_restarts, int max_restarts )
+{
+    /*
+     * Compute R = u1 * G + u2 * Q
+     * (test vectors mostly taken from ECDSA intermediate results)
+     *
+     * See comments at the top of ecp_test_vect_restart()
+     */
+    mbedtls_ecp_restart_ctx ctx;
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point R, Q;
+    mbedtls_mpi u1, u2, xR, yR;
+    int cnt_restarts;
+    int ret;
+
+    mbedtls_ecp_restart_init( &ctx );
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &R );
+    mbedtls_ecp_point_init( &Q );
+    mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
+    mbedtls_mpi_init( &xR ); mbedtls_mpi_init( &yR );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &u1, 16, u1_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &u2, 16, u2_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &xR, 16, xR_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &yR, 16, yR_str ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &Q.X, 16, xQ_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &Q.Y, 16, yQ_str ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_lset( &Q.Z, 1 ) == 0 );
+
+    mbedtls_ecp_set_max_ops( (unsigned) max_ops );
+
+    cnt_restarts = 0;
+    do {
+        ECP_PT_RESET( &R );
+        ret = mbedtls_ecp_muladd_restartable( &grp, &R,
+                                              &u1, &grp.G, &u2, &Q, &ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xR ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yR ) == 0 );
+
+    TEST_ASSERT( cnt_restarts >= min_restarts );
+    TEST_ASSERT( cnt_restarts <= max_restarts );
+
+    /* Do we leak memory when aborting an operation?
+     * This test only makes sense when we actually restart */
+    if( min_restarts > 0 )
+    {
+        ret = mbedtls_ecp_muladd_restartable( &grp, &R,
+                                              &u1, &grp.G, &u2, &Q, &ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    }
+
+exit:
+    mbedtls_ecp_restart_free( &ctx );
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &R );
+    mbedtls_ecp_point_free( &Q );
+    mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+    mbedtls_mpi_free( &xR ); mbedtls_mpi_free( &yR );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void ecp_test_vect( int id, char * dA_str, char * xA_str, char * yA_str,
                     char * dB_str, char * xB_str, char * yB_str,
diff --git a/tests/suites/test_suite_nist_kw.data b/tests/suites/test_suite_nist_kw.data
index eee4574..4462558 100644
--- a/tests/suites/test_suite_nist_kw.data
+++ b/tests/suites/test_suite_nist_kw.data
@@ -69,6 +69,27 @@
 NIST KW lengths #16 KWP unwrapping output buffer too short
 nist_kw_ciphertext_lengths:24:12:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
 
+NIST KW lengths #17 KW plaintext NULL (2 to 2^54 - 1 semiblocks)
+nist_kw_plaintext_lengths:0:8:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #18 KW wrapping output NULL
+nist_kw_plaintext_lengths:8:0:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #19 KWP wrapping output NULL
+nist_kw_plaintext_lengths:8:0:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #20 KW ciphertext NULL
+nist_kw_ciphertext_lengths:0:8:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #21 KWP ciphertext NULL
+nist_kw_ciphertext_lengths:0:8:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #15 KW unwrapping output NULL
+nist_kw_ciphertext_lengths:32:0:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #16 KWP unwrapping output NULL
+nist_kw_ciphertext_lengths:24:0:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
 NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 128 count 7
 depends_on:MBEDTLS_AES_C
 mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"095e293f31e317ba6861114b95c90792":"64349d506ae85ecd84459c7a5c423f55":"97de4425572274bd7fb2d6688d5afd4454d992348d42a643"
diff --git a/tests/suites/test_suite_nist_kw.function b/tests/suites/test_suite_nist_kw.function
index eb67c03..ae3ef80 100644
--- a/tests/suites/test_suite_nist_kw.function
+++ b/tests/suites/test_suite_nist_kw.function
@@ -158,19 +158,17 @@
 
     memset( key, 0, sizeof( key ) );
 
-    if (in_len == 0)
-    {
-        /* mbedtls_calloc can return NULL for zero-length buffers. Make sure we
-         * always have a plaintext buffer, even if the length is 0. */
-        plaintext = mbedtls_calloc( 1, 1 );
-    }
-    else
+    if( in_len != 0 )
     {
         plaintext = mbedtls_calloc( 1, in_len );
+        TEST_ASSERT( plaintext != NULL );
     }
-    TEST_ASSERT( plaintext != NULL );
-    ciphertext = mbedtls_calloc( 1, output_len );
-    TEST_ASSERT( ciphertext != NULL );
+
+    if( out_len != 0 )
+    {
+        ciphertext = mbedtls_calloc( 1, output_len );
+        TEST_ASSERT( ciphertext != NULL );
+    }
 
     memset( plaintext, 0, in_len );
     memset( ciphertext, 0, output_len );
@@ -216,10 +214,16 @@
 
     memset( key, 0, sizeof( key ) );
 
-    plaintext = mbedtls_calloc( 1, output_len );
-    TEST_ASSERT( plaintext != NULL );
-    ciphertext = mbedtls_calloc( 1, in_len );
-    TEST_ASSERT( ciphertext != NULL );
+    if( out_len != 0 )
+    {
+        plaintext = mbedtls_calloc( 1, output_len );
+        TEST_ASSERT( plaintext != NULL );
+    }
+    if( in_len != 0 )
+    {
+        ciphertext = mbedtls_calloc( 1, in_len );
+        TEST_ASSERT( ciphertext != NULL );
+    }
 
     memset( plaintext, 0, output_len );
     memset( ciphertext, 0, in_len );
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index a066bd9..478cde7 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -153,3 +153,35 @@
 RSA hash_len overflow (size_t vs unsigned int)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_HAVE_INT64
 pk_rsa_overflow:
+
+ECDSA restartable sign/verify: ECDSA, max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0
+
+ECDSA restartable sign/verify: ECKEY, max_ops=0 (disabled)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0
+
+ECDSA restartable sign/verify: ECDSA, max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000
+
+ECDSA restartable sign/verify: ECKEY, max_ops=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000
+
+ECDSA restartable sign/verify: ECDSA, max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0
+
+ECDSA restartable sign/verify: ECKEY, max_ops=10000
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0
+
+ECDSA restartable sign/verify: ECDSA, max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64
+
+ECDSA restartable sign/verify: ECKEY, max_ops=250
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C
+pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 9005ddb..4813f71 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -129,6 +129,15 @@
     unsigned char hash_result[1000];
     mbedtls_rsa_context *rsa;
     mbedtls_pk_context pk;
+    mbedtls_pk_restart_ctx *rs_ctx = NULL;
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_pk_restart_ctx ctx;
+
+    rs_ctx = &ctx;
+    mbedtls_pk_restart_init( rs_ctx );
+    // this setting would ensure restart would happen if ECC was used
+    mbedtls_ecp_set_max_ops( 1 );
+#endif
 
     mbedtls_pk_init( &pk );
 
@@ -148,7 +157,13 @@
     TEST_ASSERT( mbedtls_pk_verify( &pk, digest, hash_result, 0,
                             result_str->x, mbedtls_pk_get_len( &pk ) ) == result );
 
+    TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, digest, hash_result, 0,
+                    result_str->x, mbedtls_pk_get_len( &pk ), rs_ctx ) == result );
+
 exit:
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_pk_restart_free( rs_ctx );
+#endif
     mbedtls_pk_free( &pk );
 }
 /* END_CASE */
@@ -239,12 +254,125 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC */
+void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str,
+                              char *QX_str, char *QY_str,
+                              int md_alg, char *msg, char *sig_str,
+                              int max_ops, int min_restart, int max_restart )
+{
+    int ret, cnt_restart;
+    mbedtls_pk_restart_ctx rs_ctx;
+    mbedtls_pk_context prv, pub;
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
+    unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN];
+    size_t hlen, slen, slen_check;
+    const mbedtls_md_info_t *md_info;
+
+    mbedtls_pk_restart_init( &rs_ctx );
+    mbedtls_pk_init( &prv );
+    mbedtls_pk_init( &pub );
+    memset( hash, 0, sizeof( hash ) );
+    memset( sig, 0, sizeof( sig ) );
+    memset( sig_check, 0, sizeof( sig_check ) );
+
+    TEST_ASSERT( mbedtls_pk_setup( &prv, mbedtls_pk_info_from_type( pk_type ) ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( prv )->grp, grp_id ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_string( &mbedtls_pk_ec( prv )->d, 16, d_str ) == 0 );
+
+    TEST_ASSERT( mbedtls_pk_setup( &pub, mbedtls_pk_info_from_type( pk_type ) ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( pub )->grp, grp_id ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_point_read_string( &mbedtls_pk_ec( pub )->Q, 16, QX_str, QY_str ) == 0 );
+
+    slen_check = unhexify( sig_check, sig_str );
+
+    md_info = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md_info != NULL );
+
+    hlen = mbedtls_md_get_size( md_info );
+    mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
+
+    mbedtls_ecp_set_max_ops( max_ops );
+
+    slen = sizeof( sig );
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen,
+                                            sig, &slen, NULL, NULL, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( slen == slen_check );
+    TEST_ASSERT( memcmp( sig, sig_check, slen ) == 0 );
+
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_pk_verify_restartable( &pub, md_alg,
+                                 hash, hlen, sig, slen, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    hash[0]++;
+    do {
+        ret = mbedtls_pk_verify_restartable( &pub, md_alg,
+                                 hash, hlen, sig, slen, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    TEST_ASSERT( ret != 0 );
+    hash[0]--;
+
+    sig[0]++;
+    do {
+        ret = mbedtls_pk_verify_restartable( &pub, md_alg,
+                                 hash, hlen, sig, slen, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    TEST_ASSERT( ret != 0 );
+    sig[0]--;
+
+    /* Do we leak memory when aborting? try verify then sign
+     * This test only makes sense when we actually restart */
+    if( min_restart > 0 )
+    {
+        ret = mbedtls_pk_verify_restartable( &pub, md_alg,
+                                 hash, hlen, sig, slen, &rs_ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+        mbedtls_pk_restart_free( &rs_ctx );
+
+        slen = sizeof( sig );
+        ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen,
+                                            sig, &slen, NULL, NULL, &rs_ctx );
+        TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+    }
+
+exit:
+    mbedtls_pk_restart_free( &rs_ctx );
+    mbedtls_pk_free( &prv );
+    mbedtls_pk_free( &pub );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
 void pk_sign_verify( int type, int sign_ret, int verify_ret )
 {
     mbedtls_pk_context pk;
     unsigned char hash[50], sig[5000];
     size_t sig_len;
+    void *rs_ctx = NULL;
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_pk_restart_ctx ctx;
+
+    rs_ctx = &ctx;
+    mbedtls_pk_restart_init( rs_ctx );
+    /* This value is large enough that the operation will complete in one run.
+     * See comments at the top of ecp_test_vect_restart in
+     * test_suite_ecp.function for estimates of operation counts. */
+    mbedtls_ecp_set_max_ops( 42000 );
+#endif
 
     mbedtls_pk_init( &pk );
 
@@ -254,13 +382,49 @@
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 );
     TEST_ASSERT( pk_genkey( &pk ) == 0 );
 
-    TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash,
-                          sig, &sig_len, rnd_std_rand, NULL ) == sign_ret );
+    TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256,
+                 hash, sizeof hash, sig, &sig_len,
+                 rnd_std_rand, NULL, rs_ctx ) == sign_ret );
 
     TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
                             hash, sizeof hash, sig, sig_len ) == verify_ret );
 
+    if( verify_ret == 0 )
+    {
+        hash[0]++;
+        TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
+                                hash, sizeof hash, sig, sig_len ) != 0 );
+        hash[0]--;
+
+        sig[0]++;
+        TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
+                                hash, sizeof hash, sig, sig_len ) != 0 );
+        sig[0]--;
+    }
+
+    TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash,
+                          sig, &sig_len, rnd_std_rand, NULL ) == sign_ret );
+
+    TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
+                 hash, sizeof hash, sig, sig_len, rs_ctx ) == verify_ret );
+
+    if( verify_ret == 0 )
+    {
+        hash[0]++;
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
+                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        hash[0]--;
+
+        sig[0]++;
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
+                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        sig[0]--;
+    }
+
 exit:
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    mbedtls_pk_restart_free( rs_ctx );
+#endif
     mbedtls_pk_free( &pk );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 402c8b8..c3542e5 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.12.0"
+check_compiletime_version:"2.13.1"
 
 Check runtime library version
-check_runtime_version:"2.12.0"
+check_runtime_version:"2.13.1"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 406cf59..80e49d2 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1877,3 +1877,91 @@
 X509 Get time (Generalized Time invalid leap year not multiple of 4, 100 or 400)
 depends_on:MBEDTLS_X509_USE_C
 x509_get_time:MBEDTLS_ASN1_GENERALIZED_TIME:"19910229000000Z":MBEDTLS_ERR_X509_INVALID_DATE:0:0:0:0:0:0
+
+X509 cert verify restart: trusted EE, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:0:0:0
+
+X509 cert verify restart: trusted EE, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:1:0:0
+
+X509 cert verify restart: no intermediate, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:0:0:0
+
+X509 cert verify restart: no intermediate, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:1:100:10000
+
+X509 cert verify restart: no intermediate, max_ops=40000
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:40000:0:0
+
+X509 cert verify restart: no intermediate, max_ops=500
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:500:20:80
+
+X509 cert verify restart: no intermediate, badsign, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0
+
+X509 cert verify restart: no intermediate, badsign, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000
+
+X509 cert verify restart: no intermediate, badsign, max_ops=40000
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:40000:0:0
+
+X509 cert verify restart: no intermediate, badsign, max_ops=500
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:20:80
+
+X509 cert verify restart: one int, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:0:0:0
+
+X509 cert verify restart: one int, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:1:100:10000
+
+X509 cert verify restart: one int, max_ops=30000
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:30000:0:0
+
+X509 cert verify restart: one int, max_ops=500
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:500:25:100
+
+X509 cert verify restart: one int, EE badsign, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0
+
+X509 cert verify restart: one int, EE badsign, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000
+
+X509 cert verify restart: one int, EE badsign, max_ops=30000
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:30000:0:0
+
+X509 cert verify restart: one int, EE badsign, max_ops=500
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:25:100
+
+X509 cert verify restart: one int, int badsign, max_ops=0 (disabled)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0
+
+X509 cert verify restart: one int, int badsign, max_ops=1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000
+
+X509 cert verify restart: one int, int badsign, max_ops=30000
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:30000:0:0
+
+X509 cert verify restart: one int, int badsign, max_ops=500
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C
+x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:25:100
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index df95f63..552c494 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -263,6 +263,62 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_C */
+void x509_verify_restart( char *crt_file, char *ca_file,
+                          int result, int flags_result,
+                          int max_ops, int min_restart, int max_restart )
+{
+    int ret, cnt_restart;
+    mbedtls_x509_crt_restart_ctx rs_ctx;
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt ca;
+    uint32_t flags = 0;
+
+    /*
+     * See comments on ecp_test_vect_restart() for op count precision.
+     *
+     * For reference, with mbed TLS 2.6 and default settings:
+     * - ecdsa_verify() for P-256:  ~  6700
+     * - ecdsa_verify() for P-384:  ~ 18800
+     * - x509_verify() for server5 -> test-ca2:             ~ 18800
+     * - x509_verify() for server10 -> int-ca3 -> int-ca2:  ~ 25500
+     */
+
+    mbedtls_x509_crt_restart_init( &rs_ctx );
+    mbedtls_x509_crt_init( &crt );
+    mbedtls_x509_crt_init( &ca );
+
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
+
+    mbedtls_ecp_set_max_ops( max_ops );
+
+    cnt_restart = 0;
+    do {
+        ret = mbedtls_x509_crt_verify_restartable( &crt, &ca, NULL,
+                &mbedtls_x509_crt_profile_default, NULL, &flags,
+                NULL, NULL, &rs_ctx );
+    } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
+
+    TEST_ASSERT( ret == result );
+    TEST_ASSERT( flags == (uint32_t) flags_result );
+
+    TEST_ASSERT( cnt_restart >= min_restart );
+    TEST_ASSERT( cnt_restart <= max_restart );
+
+    /* Do we leak memory when aborting? */
+    ret = mbedtls_x509_crt_verify_restartable( &crt, &ca, NULL,
+            &mbedtls_x509_crt_profile_default, NULL, &flags,
+            NULL, NULL, &rs_ctx );
+    TEST_ASSERT( ret == result || ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
+
+exit:
+    mbedtls_x509_crt_restart_free( &rs_ctx );
+    mbedtls_x509_crt_free( &crt );
+    mbedtls_x509_crt_free( &ca );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C */
 void x509_verify( char *crt_file, char *ca_file, char *crl_file,
                   char *cn_name_str, int result, int flags_result,
diff --git a/yotta/.gitignore b/yotta/.gitignore
deleted file mode 100644
index 0cca093..0000000
--- a/yotta/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-module
diff --git a/yotta/create-module.sh b/yotta/create-module.sh
deleted file mode 100755
index 4c79ebe..0000000
--- a/yotta/create-module.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-
-set -eu
-
-# relative to the script's directory
-TREE=..
-DEST=module
-
-# make sure we're running in our own directory
-if [ -f create-module.sh ]; then :; else
-    cd $( dirname $0 )
-    if [ -f create-module.sh ]; then :; else
-        echo "Please run the script from is directory." >&2
-        exit 1
-    fi
-fi
-
-# use a temporary directory to build the module, then rsync to DEST
-# this allows touching only new files, for more efficient re-builds
-TMP=$DEST-tmp
-rm -rf $TMP
-
-mkdir -p $TMP/mbedtls $TMP/source
-cp $TREE/include/mbedtls/*.h $TMP/mbedtls
-cp $TREE/library/*.c $TMP/source
-
-# temporary, should depend on external module later
-cp data/entropy_hardware_poll.c $TMP/source
-cp data/target_config.h $TMP/mbedtls
-
-data/adjust-config.sh $TREE/scripts/config.pl $TMP/mbedtls/config.h
-
-mkdir -p $TMP/test
-cp -r data/example-* $TMP/test
-# later we should have the generated test suites here too
-
-cp data/module.json $TMP
-cp data/README.md $TMP
-
-cp ../LICENSE $TMP
-if [ -f ../apache-2.0.txt ]; then cp ../apache-2.0.txt $TMP; fi
-
-mkdir -p $DEST
-rsync -cr --delete --exclude build --exclude yotta_\* $TMP/ $DEST/
-rm -rf $TMP
-
-echo "mbed TLS yotta module created in '$PWD/$DEST'."
diff --git a/yotta/data/README.md b/yotta/data/README.md
deleted file mode 100644
index b748aac..0000000
--- a/yotta/data/README.md
+++ /dev/null
@@ -1,103 +0,0 @@
-# mbed TLS
-
-mbed TLS makes it trivially easy for developers to include cryptographic and SSL/TLS capabilities in their embedded products, with a minimal code footprint. It offers an SSL library with an intuitive API and readable source code.
-
-**Note:** The current release is beta, and implements no secure source of random numbers, weakening its security.
-
-Currently the only supported yotta targets are:
-- `frdm-k64f-gcc`
-- `frdm-k64f-armcc`
-- `x86-linux-native`
-- `x86-osx-native`
-
-## Sample programs
-
-This release includes the following examples:
-
-1. [**Self test:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-selftest) Tests different basic functions in the mbed TLS library.
-
-2. [**Benchmark:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-benchmark) Measures the time taken to perform basic cryptographic functions used in the library.
-
-3. [**Hashing:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-hashing) Demonstrates the various APIs for computing hashes of data (also known as message digests) with SHA-256.
-
-4. [**Authenticated encryption:**](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/example-authcrypt) Demonstrates usage of the Cipher API for encrypting and authenticating data with AES-CCM.
-
-These examples are integrated as yotta tests, so that they are built automatically when you build mbed TLS. Each of them comes with complete usage instructions as a Readme file in the repository.
-
-## Performing TLS and DTLS connections
-
-A high-level API for performing TLS and DTLS connections with mbed TLS in mbed OS is provided in a separate yotta module: [mbed-tls-sockets](https://github.com/ARMmbed/mbed-tls-sockets). We recommend this API for TLS and DTLS connections. It is very similar to the API provided by the [sockets](https://github.com/ARMmbed/sockets) module for unencrypted TCP and UDP connections.
-
-The `mbed-tls-sockets` module includes a complete [example TLS client](https://github.com/ARMmbed/mbed-tls-sockets/blob/master/test/tls-client/main.cpp) with [usage instructions](https://github.com/ARMmbed/mbed-tls-sockets/blob/master/test/tls-client/README.md).
-
-## Configuring mbed TLS features
-
-mbed TLS makes it easy to disable any feature during compilation, if that feature isn't required for a particular project. The default configuration enables all modern and widely-used features, which should meet the needs of new projects, and disables all features that are older or less common, to minimize the code footprint.
-
-The list of available compilation flags is available in the fully documented [config.h file](https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/config.h).
-
-If you need to adjust those flags, you can provide your own configuration-adjustment file with suitable `#define` and `#undef` statements. These will be included between the default definitions and the sanity checks. Your configuration file should be in your application's include directory, and can be named freely; you just need to let mbed TLS know the file's name. To do that, use yotta's [configuration system](http://docs.yottabuild.org/reference/config.html). The file's name should be in your `config.json` file, under mbedtls, as the key `user-config-file`.
-
-For example, in an application called `myapp`, if you want to enable the EC J-PAKE key exchange and disable the CBC cipher mode, you can create a file named  `mbedtls-config-changes.h` in the `myapp` directory containing the following lines:
-
-    #define MBEDTLS_ECJPAKE_C
-    #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
-
-    #undef MBEDTLS_CIPHER_MODE_CBC
-
-And then create a file named `config.json` at the root of your application with the following contents:
-
-    {
-       "mbedtls": {
-          "user-config-file": "\"myapp/mbedtls-config-changes.h\""
-       }
-    }
-
-Please note: you need to provide the exact name that will be used in the `#include` directive, including the `<>` or quotes around the name.
-
-## Getting mbed TLS from GitHub
-
-Like most components of mbed OS, mbed TLS is developed in the open and its source can be found on GitHub: [ARMmbed/mbedtls](https://github.com/ARMmbed/mbedtls). Unlike most other mbed OS components, however, you cannot just clone the repository and run `yotta build` from its root. This is because mbed TLS also exists as an independent component, so its repository includes things that are not relevant for mbed OS, as well as other build systems.
-
-The way to use mbed TLS from a clone of the GitHub repository is to run the following commands from the root of a checkout:
-
-    yotta/create-module.sh
-    cd yotta/module
-
-You can then run any yotta command you would normally run, such as `yotta build` or `yotta link`.
-
-## Differences between the standalone and mbed OS editions
-
-While the two editions share the same code base, there are still a number of differences, mainly in configuration and integration. You should keep in mind those differences when reading some articles in our [knowledge base](https://tls.mbed.org/kb), as currently all the articles are about the standalone edition.
-
-* The mbed OS edition has a smaller set of features enabled by default in `config.h`, in order to reduce footprint. While the default configuration of the standalone edition puts more emphasize on maintaining interoperability with old peers, the mbed OS edition only enables the most modern ciphers and the latest version of (D)TLS.
-
-* The following components of mbed TLS are disabled in the mbed OS edition: `net_sockets.c` and `timing.c`. This is because mbed OS include their equivalents.
-
-* The mbed OS edition comes with a fully integrated API for (D)TLS connections in a companion module: [mbed-tls-sockets](https://github.com/ARMmbed/mbed-tls-sockets). See "Performing TLS and DTLS connections" above.
-
-## Other resources
-
-The [mbed TLS website](https://tls.mbed.org) contains many other useful
-resources for the developer, such as [developer
-documentation](https://tls.mbed.org/dev-corner), [knowledgebase
-articles](https://tls.mbed.org/kb), and a [support forum](https://tls.mbed.org/discussions).
-
-## Contributing
-
-We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
-
-* Simple bug fixes to existing code do not contain copyright themselves and we can integrate without issue. The same is true of trivial contributions.
-
-* For larger contributions, such as a new feature, the code can possibly fall under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for this, which we will send to you in case you submit a contribution or pull request that we deem this necessary for.
-
-To contribute, please:
-
-* [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug.
-
-* Fork the [mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the "development" branch as a basis.
-
-* Write a test that shows that the bug was fixed or that the feature works as expected.
-
-* Send a pull request and bug us until it gets merged and published. We will include your name in the ChangeLog.
-
diff --git a/yotta/data/adjust-config.sh b/yotta/data/adjust-config.sh
deleted file mode 100755
index 3fa8490..0000000
--- a/yotta/data/adjust-config.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-
-set -eu
-
-if [ $# -ne 2 ]; then
-    echo "Usage: $0 path/to/config.pl path/to/config.h" >&2
-    exit 1
-fi
-
-SCRIPT=$1
-FILE=$2
-
-conf() {
-    $SCRIPT -f $FILE $@
-}
-
-
-# Set the target specific header
-conf set YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE \"mbedtls/target_config.h\"
-
-# not supported on mbed OS, nor used by mbed Client
-conf unset MBEDTLS_NET_C
-conf unset MBEDTLS_TIMING_C
-
-# not supported on all targets with mbed OS, nor used by mbed Client
-conf unset MBEDTLS_FS_IO
-
-conf unset MBEDTLS_CIPHER_MODE_CFB
-conf unset MBEDTLS_CIPHER_MODE_CTR
-conf unset MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
-conf unset MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
-conf unset MBEDTLS_CIPHER_PADDING_ZEROS
-conf unset MBEDTLS_ECP_DP_SECP192R1_ENABLED
-conf unset MBEDTLS_ECP_DP_SECP224R1_ENABLED
-conf unset MBEDTLS_ECP_DP_SECP521R1_ENABLED
-conf unset MBEDTLS_ECP_DP_SECP192K1_ENABLED
-conf unset MBEDTLS_ECP_DP_SECP224K1_ENABLED
-conf unset MBEDTLS_ECP_DP_SECP256K1_ENABLED
-conf unset MBEDTLS_ECP_DP_BP256R1_ENABLED
-conf unset MBEDTLS_ECP_DP_BP384R1_ENABLED
-conf unset MBEDTLS_ECP_DP_BP512R1_ENABLED
-conf unset MBEDTLS_PK_PARSE_EC_EXTENDED
-
-conf unset MBEDTLS_AESNI_C
-conf unset MBEDTLS_ARC4_C
-conf unset MBEDTLS_BLOWFISH_C
-conf unset MBEDTLS_CAMELLIA_C
-conf unset MBEDTLS_DES_C
-conf unset MBEDTLS_DHM_C
-conf unset MBEDTLS_GENPRIME
-conf unset MBEDTLS_MD5_C
-conf unset MBEDTLS_PADLOCK_C
-conf unset MBEDTLS_PEM_WRITE_C
-conf unset MBEDTLS_PKCS5_C
-conf unset MBEDTLS_PKCS12_C
-conf unset MBEDTLS_RIPEMD160_C
-conf unset MBEDTLS_SHA1_C
-conf unset MBEDTLS_XTEA_C
-
-conf unset MBEDTLS_X509_RSASSA_PSS_SUPPORT
-
-conf unset MBEDTLS_X509_CSR_PARSE_C
-conf unset MBEDTLS_X509_CREATE_C
-conf unset MBEDTLS_X509_CRT_WRITE_C
-conf unset MBEDTLS_X509_CSR_WRITE_C
-
-conf unset MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
-conf unset MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
-conf unset MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-conf unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
-conf unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
-conf unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
-conf unset MBEDTLS_SSL_FALLBACK_SCSV
-conf unset MBEDTLS_SSL_CBC_RECORD_SPLITTING
-conf unset MBEDTLS_SSL_PROTO_TLS1
-conf unset MBEDTLS_SSL_PROTO_TLS1_1
-conf unset MBEDTLS_SSL_TRUNCATED_HMAC
diff --git a/yotta/data/entropy_hardware_poll.c b/yotta/data/entropy_hardware_poll.c
deleted file mode 100644
index 3a61e22..0000000
--- a/yotta/data/entropy_hardware_poll.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  Hardware entropy collector for the K64F, using Freescale's RNGA
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-/*
- * WARNING: this is temporary!
- * This should be in a separate yotta module which would be a target
- * dependency of mbedtls (see IOTSSL-313)
- */
-
-#if defined(TARGET_LIKE_K64F)
-
-/*
- * Reference: "K64 Sub-Family Reference Manual, Rev. 2", chapter 34
- */
-
-#include "fsl_clock_manager.h"
-
-/*
- * Get one byte of entropy from the RNG, assuming it is up and running.
- * As recommended (34.1.1), get only one bit of each output.
- */
-static void rng_get_byte( unsigned char *byte )
-{
-    size_t bit;
-
-    /* 34.5 Steps 3-4-5: poll SR and read from OR when ready */
-    for( bit = 0; bit < 8; bit++ )
-    {
-        while( ( RNG->SR & RNG_SR_OREG_LVL_MASK ) == 0 );
-        *byte |= ( RNG->OR & 1 ) << bit;
-    }
-}
-
-/*
- * Get len bytes of entropy from the hardware RNG.
- */
-int mbedtls_hardware_poll( void *data,
-                    unsigned char *output, size_t len, size_t *olen )
-{
-    size_t i;
-    int ret;
-    ((void) data);
-
-    CLOCK_SYS_EnableRngaClock( 0 );
-
-    /* Set "Interrupt Mask", "High Assurance" and "Go",
-     * unset "Clear interrupt" and "Sleep" */
-    RNG->CR = RNG_CR_INTM_MASK | RNG_CR_HA_MASK | RNG_CR_GO_MASK;
-
-    for( i = 0; i < len; i++ )
-        rng_get_byte( output + i );
-
-    /* Just be extra sure that we didn't do it wrong */
-    if( ( RNG->SR & RNG_SR_SECV_MASK ) != 0 )
-    {
-        ret = -1;
-        goto cleanup;
-    }
-
-    *olen = len;
-    ret = 0;
-
-cleanup:
-    /* Disable clock to save power - assume we're the only users of RNG */
-    CLOCK_SYS_DisableRngaClock( 0 );
-
-    return( ret );
-}
-
-#endif
diff --git a/yotta/data/example-authcrypt/README.md b/yotta/data/example-authcrypt/README.md
deleted file mode 100644
index 4498b9d..0000000
--- a/yotta/data/example-authcrypt/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# Authenticated Encryption Example
-
-This application performs authenticated encryption and authenticated decryption of a buffer. It serves as a tutorial for the basic authenticated encryption functions of mbed TLS.
-
-## Pre-requisites
-
-To build and run this example you must have:
-
-* A computer with the following software installed:
-  * [CMake](http://www.cmake.org/download/).
-  * [yotta](https://github.com/ARMmbed/yotta). Please note that **yotta has its own set of dependencies**, listed in the [installation instructions](http://armmbed.github.io/yotta/#installing-on-windows).
-  * [Python](https://www.python.org/downloads/).
-  * [The ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded).
-  * A serial terminal emulator (Like screen, pySerial and cu).
-* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in which case you'll have to substitute frdm-k64f-gcc with the appropriate target in the instructions below).
-* A micro-USB cable.
-* If your OS is Windows, please follow the installation instructions [for the serial port driver](https://developer.mbed.org/handbook/Windows-serial-configuration).
-
-## Getting started
-
-1. Connect the FRDM-K64F to the computer with the micro-USB cable, being careful to use the "OpenSDA" connector on the target board.
-
-2. Navigate to the mbedtls directory supplied with your release and open a terminal.
-
-3. Set the yotta target:
-
-    ```
-    yotta target frdm-k64f-gcc
-    ```
-
-4. Build mbedtls and the examples. This may take a long time if this is your first compilation:
-
-    ```
-    $ yotta build
-    ```
-
-5. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-authcrypt.bin` to your mbed board and wait until the LED next to the USB port stops blinking.
-
-6. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F. 
-
-   Use the following settings:
-
-    * 115200 baud (not 9600).
-    * 8N1.
-    * No flow control.
-
-7. Press the Reset button on the board.
-
-8. The output in the terminal window should look like:
-
-    ```
-    {{timeout;10}}
-    {{host_test_name;default}}
-    {{description;mbed TLS example authcrypt}}
-    {{test_id;MBEDTLS_EX_AUTHCRYPT}}
-    {{start}}
-
-
-    plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400
-    ciphertext: c57f7afb94f14c7977d785d08682a2596bd62ee9dcf216b8cccd997afee9b402f5de1739e8e6467aa363749ef39392e5c66622b01c7203ec0a3d14
-    decrypted: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400
-
-    DONE
-    {{success}}
-    {{end}}
-    ```
-
-The actual output for the ciphertext line will vary on each run because of the use of a random nonce in the encryption process.
diff --git a/yotta/data/example-authcrypt/main.cpp b/yotta/data/example-authcrypt/main.cpp
deleted file mode 100644
index 23fad27..0000000
--- a/yotta/data/example-authcrypt/main.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- *  Hello world example of using the authenticated encryption with mbed TLS
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#include "mbedtls/cipher.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/ctr_drbg.h"
-
-#include <stdio.h>
-#include <string.h>
-
-static void print_hex(const char *title, const unsigned char buf[], size_t len)
-{
-    printf("%s: ", title);
-
-    for (size_t i = 0; i < len; i++)
-        printf("%02x", buf[i]);
-
-    printf("\r\n");
-}
-
-/*
- * The pre-shared key. Should be generated randomly and be unique to the
- * device/channel/etc. Just used a fixed on here for simplicity.
- */
-static const unsigned char secret_key[16] = {
-    0xf4, 0x82, 0xc6, 0x70, 0x3c, 0xc7, 0x61, 0x0a,
-    0xb9, 0xa0, 0xb8, 0xe9, 0x87, 0xb8, 0xc1, 0x72,
-};
-
-static int example(void)
-{
-    /* message that should be protected */
-    const char message[] = "Some things are better left unread";
-    /* metadata transmitted in the clear but authenticated */
-    const char metadata[] = "eg sequence number, routing info";
-    /* ciphertext buffer large enough to hold message + nonce + tag */
-    unsigned char ciphertext[128] = { 0 };
-    int ret;
-
-    printf("\r\n\r\n");
-    print_hex("plaintext message", (unsigned char *) message, sizeof message);
-
-    /*
-     * Setup random number generator
-     * (Note: later this might be done automatically.)
-     */
-    mbedtls_entropy_context entropy;    /* entropy pool for seeding PRNG */
-    mbedtls_ctr_drbg_context drbg;      /* pseudo-random generator */
-
-    mbedtls_entropy_init(&entropy);
-    mbedtls_ctr_drbg_init(&drbg);
-
-    /* Seed the PRNG using the entropy pool, and throw in our secret key as an
-     * additional source of randomness. */
-    ret = mbedtls_ctr_drbg_seed(&drbg, mbedtls_entropy_func, &entropy,
-                                       secret_key, sizeof (secret_key));
-    if (ret != 0) {
-        printf("mbedtls_ctr_drbg_init() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-
-    /*
-     * Setup AES-CCM contex
-     */
-    mbedtls_cipher_context_t ctx;
-
-    mbedtls_cipher_init(&ctx);
-
-    ret = mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CCM));
-    if (ret != 0) {
-        printf("mbedtls_cipher_setup() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-
-    ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_ENCRYPT);
-    if (ret != 0) {
-        printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-
-    /*
-     * Encrypt-authenticate the message and authenticate additional data
-     *
-     * First generate a random 8-byte nonce.
-     * Put it directly in the output buffer as the recipient will need it.
-     *
-     * Warning: you must never re-use the same (key, nonce) pair. One of the
-     * best ways to ensure this to use a counter for the nonce. However this
-     * means you should save the counter accross rebots, if the key is a
-     * long-term one. The alternative we choose here is to generate the nonce
-     * randomly. However it only works if you have a good source of
-     * randomness.
-     */
-    const size_t nonce_len = 8;
-    mbedtls_ctr_drbg_random(&drbg, ciphertext, nonce_len);
-
-    size_t ciphertext_len = 0;
-    /* Go for a conservative 16-byte (128-bit) tag
-     * and append it to the ciphertext */
-    const size_t tag_len = 16;
-    ret = mbedtls_cipher_auth_encrypt(&ctx, ciphertext, nonce_len,
-                              (const unsigned char *) metadata, sizeof metadata,
-                              (const unsigned char *) message, sizeof message,
-                              ciphertext + nonce_len, &ciphertext_len,
-                              ciphertext + nonce_len + sizeof message, tag_len );
-    if (ret != 0) {
-        printf("mbedtls_cipher_auth_encrypt() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-    ciphertext_len += nonce_len + tag_len;
-
-    /*
-     * The following information should now be transmitted:
-     * - first ciphertext_len bytes of ciphertext buffer
-     * - metadata if not already transmitted elsewhere
-     */
-    print_hex("ciphertext", ciphertext, ciphertext_len);
-
-    /*
-     * Decrypt-authenticate
-     */
-    unsigned char decrypted[128] = { 0 };
-    size_t decrypted_len = 0;
-
-    ret = mbedtls_cipher_setkey(&ctx, secret_key, 8 * sizeof secret_key, MBEDTLS_DECRYPT);
-    if (ret != 0) {
-        printf("mbedtls_cipher_setkey() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-
-    ret = mbedtls_cipher_auth_decrypt(&ctx,
-                              ciphertext, nonce_len,
-                              (const unsigned char *) metadata, sizeof metadata,
-                              ciphertext + nonce_len, ciphertext_len - nonce_len - tag_len,
-                              decrypted, &decrypted_len,
-                              ciphertext + ciphertext_len - tag_len, tag_len );
-    /* Checking the return code is CRITICAL for security here */
-    if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
-        printf("Something bad is happening! Data is not authentic!\r\n");
-        return 1;
-    }
-    if (ret != 0) {
-        printf("mbedtls_cipher_authdecrypt() returned -0x%04X\r\n", -ret);
-        return 1;
-    }
-
-    print_hex("decrypted", decrypted, decrypted_len);
-
-    printf("\r\nDONE\r\n");
-
-    return 0;
-}
-
-#if defined(TARGET_LIKE_MBED)
-
-#include "mbed-drivers/test_env.h"
-#include "minar/minar.h"
-
-static void run() {
-    MBED_HOSTTEST_TIMEOUT(10);
-    MBED_HOSTTEST_SELECT(default);
-    MBED_HOSTTEST_DESCRIPTION(mbed TLS example authcrypt);
-    MBED_HOSTTEST_START("MBEDTLS_EX_AUTHCRYPT");
-    MBED_HOSTTEST_RESULT(example() == 0);
-}
-
-void app_start(int, char*[]) {
-    /* Use 115200 bps for consistency with other examples */
-    get_stdio_serial().baud(115200);
-    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
-}
-
-#else
-
-int main() {
-    return example();
-}
-
-#endif
diff --git a/yotta/data/example-benchmark/README.md b/yotta/data/example-benchmark/README.md
deleted file mode 100644
index 715abee..0000000
--- a/yotta/data/example-benchmark/README.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# mbed TLS Benchmark Example
-
-This application benchmarks the various cryptographic primitives offered by mbed TLS.
-
-## Pre-requisites
-
-To build and run this example you must have:
-
-* A computer with the following software installed:
-  * [CMake](http://www.cmake.org/download/).
-  * [yotta](https://github.com/ARMmbed/yotta). Please note that **yotta has its own set of dependencies**, listed in the [installation instructions](http://armmbed.github.io/yotta/#installing-on-windows).
-  * [Python](https://www.python.org/downloads/).
-  * [The ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded).
-  * A serial terminal emulator (Like screen, pySerial and cu).
-* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in which case you'll have to substitute frdm-k64f-gcc with the appropriate target in the instructions below).
-* A micro-USB cable.
-* If your OS is Windows, please follow the installation instructions [for the serial port driver](https://developer.mbed.org/handbook/Windows-serial-configuration).
-
-## Getting started
-
-1. Connect the FRDM-K64F to the computer with the micro-USB cable, being careful to use the "OpenSDA" connector on the target board.
-
-2. Navigate to the mbedtls directory supplied with your release and open a terminal.
-
-3. Set the yotta target:
-
-    ```
-    yotta target frdm-k64f-gcc
-    ```
-
-4. Build mbedtls and the examples. This may take a long time if this is your first compilation:
-
-    ```
-    $ yotta build
-    ```
-
-5. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-benchmark.bin` to your mbed board and wait until the LED next to the USB port stops blinking.
-
-6. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F. 
-
-   Use the following settings:
-
-    * 115200 baud (not 9600).
-    * 8N1.
-    * No flow control.
-
-7. Press the Reset button on the board.
-
-8. The output in the terminal window should look like:
-
-    ```
-    {{timeout;150}}
-    {{host_test_name;default}}
-    {{description;mbed TLS benchmark program}}
-    {{test_id;MBEDTLS_BENCHMARK}}
-    {{start}}
-
-
-      SHA-1                    :       3644 KiB/s,         32 cycles/byte
-      SHA-256                  :       1957 KiB/s,         59 cycles/byte
-      SHA-512                  :        587 KiB/s,        200 cycles/byte
-      AES-CBC-128              :       1359 KiB/s,         86 cycles/byte
-      AES-CBC-192              :       1183 KiB/s,         99 cycles/byte
-      AES-CBC-256              :       1048 KiB/s,        111 cycles/byte
-      AES-GCM-128              :        421 KiB/s,        279 cycles/byte
-      AES-GCM-192              :        403 KiB/s,        292 cycles/byte
-      AES-GCM-256              :        385 KiB/s,        305 cycles/byte
-      AES-CCM-128              :        542 KiB/s,        216 cycles/byte
-      AES-CCM-192              :        484 KiB/s,        242 cycles/byte
-      AES-CCM-256              :        437 KiB/s,        268 cycles/byte
-      CTR_DRBG (NOPR)          :       1002 KiB/s,        117 cycles/byte
-      CTR_DRBG (PR)            :        705 KiB/s,        166 cycles/byte
-      HMAC_DRBG SHA-1 (NOPR)   :        228 KiB/s,        517 cycles/byte
-      HMAC_DRBG SHA-1 (PR)     :        210 KiB/s,        561 cycles/byte
-      HMAC_DRBG SHA-256 (NOPR) :        212 KiB/s,        557 cycles/byte
-      HMAC_DRBG SHA-256 (PR)   :        185 KiB/s,        637 cycles/byte
-      RSA-2048                 :      41 ms/ public
-      RSA-2048                 :    1349 ms/private
-      RSA-4096                 :     134 ms/ public
-      RSA-4096                 :    7149 ms/private
-      ECDSA-secp384r1          :     640 ms/sign
-      ECDSA-secp256r1          :     387 ms/sign
-      ECDSA-secp384r1          :    1233 ms/verify
-      ECDSA-secp256r1          :     751 ms/verify
-      ECDHE-secp384r1          :    1191 ms/handshake
-      ECDHE-secp256r1          :     730 ms/handshake
-      ECDHE-Curve25519         :     611 ms/handshake
-      ECDH-secp384r1           :     584 ms/handshake
-      ECDH-secp256r1           :     365 ms/handshake
-      ECDH-Curve25519          :     303 ms/handshake
-
-    {{success}}
-    {{end}}
-    ```
-
-Any performance data generated by this example application are indicative only of the performance of the mbed TLS module on the platform it's executed on.
-
-Differences in the integration of mbed TLS into the platform, such as whether all available hardware accelerators have been used or not, can lead to significant differences in performance, and so results from the program are not intended to be used to meaningfully compare platforms.
-
-The figures may also slightly change from execution to execution due to variations in the timing functions.
diff --git a/yotta/data/example-benchmark/main.cpp b/yotta/data/example-benchmark/main.cpp
deleted file mode 100644
index d13cde5..0000000
--- a/yotta/data/example-benchmark/main.cpp
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- *  Benchmark demonstration program
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if !defined(TARGET_LIKE_MBED)
-
-#include <stdio.h>
-
-int main() {
-    printf("this version of this program only works on mbed OS\n");
-    return 0;
-}
-
-#else
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_exit       exit
-#define mbedtls_printf     printf
-#define mbedtls_snprintf   snprintf
-#define mbedtls_free       free
-#endif
-
-#include <string.h>
-
-#include "mbedtls/md4.h"
-#include "mbedtls/md5.h"
-#include "mbedtls/ripemd160.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-#include "mbedtls/sha512.h"
-#include "mbedtls/arc4.h"
-#include "mbedtls/des.h"
-#include "mbedtls/aes.h"
-#include "mbedtls/blowfish.h"
-#include "mbedtls/camellia.h"
-#include "mbedtls/gcm.h"
-#include "mbedtls/ccm.h"
-#include "mbedtls/havege.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/hmac_drbg.h"
-#include "mbedtls/rsa.h"
-#include "mbedtls/pk.h"
-#include "mbedtls/dhm.h"
-#include "mbedtls/ecdsa.h"
-#include "mbedtls/ecdh.h"
-#include "mbedtls/error.h"
-
-#include "mbed-drivers/mbed.h"
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#include "mbedtls/memory_buffer_alloc.h"
-#endif
-
-#define RSA_PRIVATE_KEY_2048                                            \
-"-----BEGIN RSA PRIVATE KEY-----\r\n"                                   \
-"MIIEogIBAAKCAQEA2dwVr+IMGEtA2/MCP6fA5eb/6B18Bq6e7gw8brNPkm3E6LyR\r\n"  \
-"4DnMJVxZmw3bPDKBDoKzfntkMESi/Yw5UopLtVfjGfWeQWPClqffLZBsZ60BRAsg\r\n"  \
-"/g+ID5tgzxSuxzftypK59uexOVCAm7hCKZHGO3DbI7bLY27j7VAgEP7d/yuaz5Fx\r\n"  \
-"Kl/vu7shqrBoz6ABJVJD3KC8nUiMRUCXRINmxbyUUjA4DnicZv6+xrGKr36r6M8h\r\n"  \
-"VYLa5msKc8WzbnBWzpUsrpb4/r7ML+qp92gdSfVJ8/bLiU7h2C7faDA59uaqrFK9\r\n"  \
-"xmDdx7FaWhGQs3LWW6w1UNgkPS0FDYUslpsnsQIDAQABAoIBAC7IJNwM5V3+IuJY\r\n"  \
-"T35Nzo1PyloUosJokvY5KGz5Ejg2XBdCDu0gXCcVqqQyGIbXrYDpLhQV+RCoXHun\r\n"  \
-"tdN0oQdC5SB47s/J1Uo2qCUHo0+sBd6PqTkFKsl3KxWssk9TQjvCwC412IefMs69\r\n"  \
-"hW+ZvwCanmQP56LleApIr2oW4KLfW8Ry/QfZlua+dizctdN7+H1mWwgZQTY9T27J\r\n"  \
-"6RtGRA5NVkKVPzIHVJfdpKoO7xGg1g06aEbPB/VmGvZaaFWWnaf7uRvFjLZecBLu\r\n"  \
-"QSx2DA/GDjirlDYj99PJb7DtB4xRtKzsyw0o+xapC8w6OtIl/3xFt9moCu2jGrsx\r\n"  \
-"vpjHdfECgYEA7fSACRseIs9gAIVX8wq6gayTpA47DHYWAD6IQfIj35SJ+AgsvbFF\r\n"  \
-"4AmrwDhcJVPmDy1N4nLBfyGAMt/2CfiYkdkW6QFX/ULRMMBL/G7kWV8hYQDICB2g\r\n"  \
-"xaMRN1lPCmFq6BkSWjwIYTnYDFBDWVm1GVT8TMtJoM8Erej9qC0PeFUCgYEA6mF3\r\n"  \
-"bigO3t8f5sig+XepaftEUbkJMzo72TVRnIR2ycdR2ihelPQ+25g9dwV0ZA5XXhBS\r\n"  \
-"DKOABWjMM739Mwmy9v26Dlmu9R01zHQktMvtEAyfz7lk2NF0aMuj8285OJUBf9bz\r\n"  \
-"Cq3MjtMCD+4CZ6iaEqCdUKOuxfpx5cWVJV+qve0CgYBhD1YaYMFOGaBjFgDl1f51\r\n"  \
-"Xltqk5NqZdBbkSYrIAWZ8RDF5y+4wFJsLAWuhk6vuyUgE66tK3nZzWRpXAkT0B8L\r\n"  \
-"fq1lpXKqj1KcvBNCiEkEW1VWJ+dvyAYIF5eyJ++hoFLnETL3M32HivyhKSwPihPg\r\n"  \
-"nVW8TT9fJJIYDe1JZ/fjcQKBgHJfv7UsrR0LSvkG3K8AOtbx+8PZhOjPuRbk0v+L\r\n"  \
-"EKCkuIe5/XW4vtfQMeZb7hFJgk7vrepm+vkoy8VQKDf4urGW3W1VTHBmobM01hi4\r\n"  \
-"DuYvEul+Mf0wMRtWjJolo4m+BO5KiW2jpFfqFm6JmfjVqOIAKOSKC6am8V/MDF0h\r\n"  \
-"kyN9AoGAT9oOiEXMolbkDZw/QCaBiRoAGlGlNYUkJ+58U6OjIZLISw6aFv+Y2uE0\r\n"  \
-"mEImItjuYZtSYKblWikp6ldPoKlt9bwEFe3c6IZ8kJ3+xyEyAGrvjXjEY7PzP6dp\r\n"  \
-"Ajbjp9X9uocEBv9W/KsBLdQ7yizcL/toHwdBO4vQqmqTvAc5IIw=\r\n"              \
-"-----END RSA PRIVATE KEY-----\r\n"
-
-#define RSA_PRIVATE_KEY_4096                                            \
-"-----BEGIN RSA PRIVATE KEY-----\r\n"                                   \
-"MIIJKgIBAAKCAgEAmkdGjoIshJuOt2NO47qB3Z3yyvmLg2j351isItSNuFQU3qr+\r\n"  \
-"jXHIeANf03yw/K0Zvos8RPd+CqLjoxAQL3QDH4bZAl88bIo29i+SANbNSrKQmc0k\r\n"  \
-"pH+yzw3alDzO0GZaOPZjsbo6AwBrno5msi0vRuC2aY8vGLPsZWSyLai7tneS1j/o\r\n"  \
-"vYW6XIo8Cj61j2Ypy9HhVUW/4Wc+zAT25D/x7jTpkqJLWWT+YzibNbOY48M5eJcB\r\n"  \
-"6/sMyUIeI3/u/wXyMrooNyLiCpedkuHRA0m7u5cWPTUISTunSRlVFij/NHJjuU8e\r\n"  \
-"wA3B29yfZFsUqDEnyc+OxniIueAixTomVszxAaVn8zFEbYhFMPqziiFp99u3jfeG\r\n"  \
-"k1q9mmUi/uCfUC4e2IC5rqq1ZbKSduH7Ug/Vn2bGQahww0sZFRHDXFrnBcotcW+M\r\n"  \
-"bnC290VBDnYgzmdYrIOxuPb2aUwJo4ZlbKh5uBB1PigMuyhLKibQ1a+V5ZJGdpP6\r\n"  \
-"SE9PGIdgYWSmh2QEMuLE6v+wTO2LQ5JgqsvFfi3GIZvkn0s8jTS72Jq2uMkFkMer\r\n"  \
-"UBjPDYaSPy5kpo103KerWs+cMPOJ/3FtZzI++7MoSUTkWVr1ySQFt5i1EIZ/0Thi\r\n"  \
-"jut2jNe8a4AoA3TtC8Rkk/3AIIbg8MVNT4EnT+KHROTMu6gET1oJ3YfBRpUCAwEA\r\n"  \
-"AQKCAgEAhuNSmT7PVZH8kfLOAuYKrY1vvm+4v0iDl048Eqfs0QESziyLK3gUYnnw\r\n"  \
-"yqP2yrU+EQ8Dvvj0xq/sf6GHxTWVlXb9PcmutueRbmXhLcKg83J0Y0StiPXtjIL8\r\n"  \
-"XSddW3Bh6fPi7n14Qy+W6KZwu9AtybanRlvePabyRSRpdOpWVQ7u30w5XZsSed6S\r\n"  \
-"6BI0BBC68m2qqje1sInoqdCdXKtcB31TytUDNEHM+UuAyM8iGeGS2hCNqZlycHTS\r\n"  \
-"jQ9KEsdMH3YLu0lQgRpWtxmg+VL6ROWwmAtKF12EwbDYZ+uoVl69OkQnCpv8pxKa\r\n"  \
-"ec/4m6V+uEA1AOpaAMorHG3fH31IKWC/fTZstovgO/eG2XCtlbcCoWCQ7amFq16l\r\n"  \
-"Gh1UKeBHxMXpDj4oDmIUGUvgzSNnEeSN/v76losWvWYQDjXR/LMDa/CNYsD8BmJR\r\n"  \
-"PZidIjIXdVRlYOhA7ljtySQvp6RBujBfw3tsVMyZw2XzXFwM9O89b1xXC6+M5jf9\r\n"  \
-"DXs/U7Fw+J9qq/YpByABcPCwWdttwdQFRbOxwxaSOKarIqS87TW1JuFcNJ59Ut6G\r\n"  \
-"kMvAg6gC34U+0ktkG/AmI1hgjC+P7ErHCXBR2xARoGzcO/CMZF59S+Z2HFchpTSP\r\n"  \
-"5T2o4mGy3VfHSBidQQrcZRukg8ZP8M1NF3bXjpY6QZpeLHc4oHECggEBAMjdgzzk\r\n"  \
-"xp4mIYFxAEiXYt7tzuUXJk+0UpEJj5uboWLirUZqZmNUPyh6WDnzlREBH++Ms0LO\r\n"  \
-"+AWSfaGPDoMb0NE2j3c4FRWAhe7Vn6lj7nLVpF2RdwRo88yGerZ4uwGMY8NUQCtn\r\n"  \
-"zum3J7eCJ5DojiceRb6uMxTJ8xZmUC4W2f3J/lrR7wlYjyVnnHqH5HcemYUipWSw\r\n"  \
-"sM0/cHp3lrz2VWrbAEu8HVpklvDQpdAgl7cjXt/JHYawY+p426IF/PzQSRROnzgy\r\n"  \
-"4WI8FVYNV2tgu0TOFURbkkEvuj/duDKeooUIF0G0XHzha5oAX/j0iWiHbrOF6wHj\r\n"  \
-"0xeajL9msKBnmD8CggEBAMSgLWmv7G31x4tndJCcXnX4AyVL7KpygAx/ZwCcyTR8\r\n"  \
-"rY1rO07f/ta2noEra/xmEW/BW98qJFCHSU2nSLAQ5FpFSWyuQqrnffrMJnfWyvpr\r\n"  \
-"ceQ0yQ/MiA6/JIOvGAjabcspzZijxzGp+Qk3eTT0yOXLSVOCH9B9XVHLodcy4PQM\r\n"  \
-"KSCxy0vVHhVNl2SdPEwTXRmxk99Q/rw6IHVpQxBq1OhQt05nTKT+rZMD/grSK22e\r\n"  \
-"my2F0DodAJwLo063Zv3RXQZhDYodMmjcp9Hqrtvj9P3HD7J3z6ACiV3SCi8cZumL\r\n"  \
-"bSmnKCcd0bb45+aOWm31ieECJuIcJ9rOREEa/KDYTCsCggEBAMG5WkSVhLWsou37\r\n"  \
-"dUGNuA63nq42SH3gtS0q4nU6gUkkw+dA4ST1cMByVrr1oRQ4WHup4I4TnQOKyF3T\r\n"  \
-"4jQy1I+ipnVeAn+tZ/7zyzwMpEHeqNqRXA9FxbTBEoMAJ6QTqXgOvqDeSqIAQm7r\r\n"  \
-"OYu5rrgtqyh/S8bGCwvUe4ooAfCSKx2ekYMbBVwW9MT8YS09tuS/iHJ3Mt2RTMLg\r\n"  \
-"qeHvVmxrcXqZoFm44Ba7tN/pP0mi9HKyviZT4tmV3IYEbn3JyGGsfkUuVU9wEUfg\r\n"  \
-"MCrgrVxrwfketAzooiHMjkVL2ASjzAJTmEvdAPETYXxzJD9LN0ovY3t8JfAC37IN\r\n"  \
-"sVXS8/MCggEBALByOS59Y4Ktq1rLBQx8djwQyuneP0wZohUVAx7Gk7xZIfklQDyg\r\n"  \
-"v/R4PrcVezstcPpDnykdjScCsGJR+uWc0v667I/ttP/e6utz5hVmmBGu965dPAzE\r\n"  \
-"c1ggaSkOqFfRg/Nr2Qbf+fH0YPnHYSqHe/zSt0OMIvaaeXLcdKhEDSCUBRhE1HWB\r\n"  \
-"kxR046WzgBeYzNQwycz9xwqsctJKGpeR9ute+5ANHPd3X9XtID0fqz8ctI5eZaSw\r\n"  \
-"wApIW01ZQcAF8B+4WkkVuFXnpWW33yCOaRyPVOPHpnclr5WU1fS+3Q85QkW9rkej\r\n"  \
-"97zlkl0QY9AHJqrXnoML1ywAK7ns+MVyNK8CggEAf62xcKZhOb1djeF72Ms+i/i/\r\n"  \
-"WIAq4Q4YpsElgvJTHpNH2v9g4ngSTKe3ws3bGc502sWRlhcoTFMOW2rJNe/iqKkb\r\n"  \
-"3cdeTkseDbpqozmJWz9dJWSVtXas2bZjzBEa//gQ7nHGVeQdqZJQ9rxPsoOAkfpi\r\n"  \
-"qCFrmfUVUqC53e3XMt8+W+aSvKl+JZiB9ozkO9A6Q0vfQLKtjUMdQE3XaCFQT8DI\r\n"  \
-"smaLBlBmeRaBpc02ENeC4ADlWosm1SwgxqMhuh2Alba/GrHOoPlVl4hDs9Fb5a6R\r\n"  \
-"rmpXSt07GAxnG6j9jssA95E4rc1zO0CVKG5bvjVTxwi/sT0/VVX7VsJM4uTAQg==\r\n"  \
-"-----END RSA PRIVATE KEY-----\r\n"
-
-#if defined _MSC_VER && !defined snprintf
-#define snprintf _snprintf
-#endif
-
-/*
- * For heap usage estimates, we need an estimate of the overhead per allocated
- * block. ptmalloc2/3 (used in gnu libc for instance) uses 2 size_t per block,
- * so use that as our baseline.
- */
-#define MEM_BLOCK_OVERHEAD  ( 2 * sizeof( size_t ) )
-
-/*
- * Size to use for the malloc buffer if MEMORY_BUFFER_ALLOC_C is defined.
- */
-#define HEAP_SIZE       (1u << 16)  // 64k
-
-#define BUFSIZE         1024
-#define HEADER_FORMAT   "  %-24s :  "
-#define TITLE_LEN       25
-
-#define OPTIONS                                                         \
-    "md4, md5, ripemd160, sha1, sha256, sha512,\r\n"                      \
-    "arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish,\r\n" \
-    "havege, ctr_drbg, hmac_drbg\r\n"                                     \
-    "rsa, dhm, ecdsa, ecdh.\r\n"
-
-#if defined(MBEDTLS_ERROR_C)
-#define PRINT_ERROR                                                     \
-        mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) );         \
-        mbedtls_printf( "FAILED: %s\r\n", tmp );
-#else
-#define PRINT_ERROR                                                     \
-        mbedtls_printf( "FAILED: -0x%04x\r\n", -ret );
-#endif
-
-static unsigned long mbedtls_timing_hardclock( void )
-{
-    static int dwt_started = 0;
-
-    if( dwt_started == 0 )
-    {
-        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
-        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
-    }
-
-    return( DWT->CYCCNT );
-}
-
-static volatile int alarmed;
-static void alarm() { alarmed = 1; }
-
-#define TIME_AND_TSC( TITLE, CODE )                                     \
-do {                                                                    \
-    unsigned long i, j, tsc;                                            \
-    Timeout t; \
-                                                                        \
-    mbedtls_printf( HEADER_FORMAT, TITLE );                            \
-    fflush( stdout );                                                   \
-                                                                        \
-    for( i = 1, alarmed = 0, t.attach( alarm, 1.0 ); !alarmed; i++ )                                        \
-    {                                                                   \
-        CODE;                                                           \
-    }                                                                   \
-                                                                        \
-    tsc = mbedtls_timing_hardclock();                                                  \
-    for( j = 0; j < 1024; j++ )                                         \
-    {                                                                   \
-        CODE;                                                           \
-    }                                                                   \
-                                                                        \
-    mbedtls_printf( "%9lu KiB/s,  %9lu cycles/byte\r\n",                  \
-                     i * BUFSIZE / 1024,                                \
-                     ( mbedtls_timing_hardclock() - tsc ) / ( j * BUFSIZE ) );         \
-} while( 0 )
-
-#if defined(MBEDTLS_ERROR_C)
-#define PRINT_ERROR                                                     \
-        mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) );         \
-        mbedtls_printf( "FAILED: %s\r\n", tmp );
-#else
-#define PRINT_ERROR                                                     \
-        mbedtls_printf( "FAILED: -0x%04x\r\n", -ret );
-#endif
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG)
-
-#define MEMORY_MEASURE_INIT                                             \
-    size_t max_used, max_blocks, max_bytes;                             \
-    size_t prv_used, prv_blocks;                                        \
-    mbedtls_memory_buffer_alloc_cur_get( &prv_used, &prv_blocks );              \
-    mbedtls_memory_buffer_alloc_max_reset( );
-
-#define MEMORY_MEASURE_PRINT( title_len )                               \
-    mbedtls_memory_buffer_alloc_max_get( &max_used, &max_blocks );              \
-    for( i = 12 - title_len; i != 0; i-- ) mbedtls_printf( " " );      \
-    max_used -= prv_used;                                               \
-    max_blocks -= prv_blocks;                                           \
-    max_bytes = max_used + MEM_BLOCK_OVERHEAD * max_blocks;             \
-    mbedtls_printf( "%6u heap bytes", (unsigned) max_bytes );
-
-#else
-#define MEMORY_MEASURE_INIT
-#define MEMORY_MEASURE_PRINT( title_len )
-#endif
-
-#define TIME_PUBLIC( TITLE, TYPE, CODE )                                \
-do {                                                                    \
-    unsigned long ms;                                                    \
-    int ret = 0;                                                            \
-    Timer t; \
-    MEMORY_MEASURE_INIT;                                                \
-                                                                        \
-    mbedtls_printf( HEADER_FORMAT, TITLE );                            \
-    fflush( stdout );                                                   \
-    \
-    t.start(); \
-    CODE; \
-    t.stop(); \
-    ms = t.read_ms(); \
-                                                                        \
-    if( ret != 0 )                                                      \
-    {                                                                   \
-        PRINT_ERROR;                                                    \
-    }                                                                   \
-    else                                                                \
-    {                                                                   \
-        mbedtls_printf( "%6lu ms/" TYPE, ms );                    \
-        MEMORY_MEASURE_PRINT( sizeof( TYPE ) + 1 );                     \
-        mbedtls_printf( "\r\n" );                                        \
-    }                                                                   \
-} while( 0 )
-
-static int myrand( void *rng_state, unsigned char *output, size_t len )
-{
-    size_t use_len;
-    int rnd;
-
-    if( rng_state != NULL )
-        rng_state  = NULL;
-
-    while( len > 0 )
-    {
-        use_len = len;
-        if( use_len > sizeof(int) )
-            use_len = sizeof(int);
-
-        rnd = rand();
-        memcpy( output, &rnd, use_len );
-        output += use_len;
-        len -= use_len;
-    }
-
-    return( 0 );
-}
-
-/*
- * Clear some memory that was used to prepare the context
- */
-#if defined(MBEDTLS_ECP_C)
-void ecp_clear_precomputed( mbedtls_ecp_group *grp )
-{
-    if( grp->T != NULL )
-    {
-        size_t i;
-        for( i = 0; i < grp->T_size; i++ )
-            mbedtls_ecp_point_free( &grp->T[i] );
-        mbedtls_free( grp->T );
-    }
-    grp->T = NULL;
-    grp->T_size = 0;
-}
-#else
-#define ecp_clear_precomputed( g )
-#endif
-
-unsigned char buf[BUFSIZE];
-
-typedef struct {
-    char md4, md5, ripemd160, sha1, sha256, sha512,
-         arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish,
-         havege, ctr_drbg, hmac_drbg,
-         rsa, dhm, ecdsa, ecdh;
-} todo_list;
-
-int benchmark( int argc, char *argv[] )
-{
-    int i;
-    unsigned char tmp[200];
-    char title[TITLE_LEN];
-    todo_list todo;
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    unsigned char malloc_buf[HEAP_SIZE] = { 0 };
-#endif
-
-    if( argc <= 1 )
-    {
-        memset( &todo, 1, sizeof( todo ) );
-    }
-    else
-    {
-        memset( &todo, 0, sizeof( todo ) );
-
-        for( i = 1; i < argc; i++ )
-        {
-            if( strcmp( argv[i], "md4" ) == 0 )
-                todo.md4 = 1;
-            else if( strcmp( argv[i], "md5" ) == 0 )
-                todo.md5 = 1;
-            else if( strcmp( argv[i], "ripemd160" ) == 0 )
-                todo.ripemd160 = 1;
-            else if( strcmp( argv[i], "sha1" ) == 0 )
-                todo.sha1 = 1;
-            else if( strcmp( argv[i], "sha256" ) == 0 )
-                todo.sha256 = 1;
-            else if( strcmp( argv[i], "sha512" ) == 0 )
-                todo.sha512 = 1;
-            else if( strcmp( argv[i], "arc4" ) == 0 )
-                todo.arc4 = 1;
-            else if( strcmp( argv[i], "des3" ) == 0 )
-                todo.des3 = 1;
-            else if( strcmp( argv[i], "des" ) == 0 )
-                todo.des = 1;
-            else if( strcmp( argv[i], "aes_cbc" ) == 0 )
-                todo.aes_cbc = 1;
-            else if( strcmp( argv[i], "aes_gcm" ) == 0 )
-                todo.aes_gcm = 1;
-            else if( strcmp( argv[i], "aes_ccm" ) == 0 )
-                todo.aes_ccm = 1;
-            else if( strcmp( argv[i], "camellia" ) == 0 )
-                todo.camellia = 1;
-            else if( strcmp( argv[i], "blowfish" ) == 0 )
-                todo.blowfish = 1;
-            else if( strcmp( argv[i], "havege" ) == 0 )
-                todo.havege = 1;
-            else if( strcmp( argv[i], "ctr_drbg" ) == 0 )
-                todo.ctr_drbg = 1;
-            else if( strcmp( argv[i], "hmac_drbg" ) == 0 )
-                todo.hmac_drbg = 1;
-            else if( strcmp( argv[i], "rsa" ) == 0 )
-                todo.rsa = 1;
-            else if( strcmp( argv[i], "dhm" ) == 0 )
-                todo.dhm = 1;
-            else if( strcmp( argv[i], "ecdsa" ) == 0 )
-                todo.ecdsa = 1;
-            else if( strcmp( argv[i], "ecdh" ) == 0 )
-                todo.ecdh = 1;
-            else
-            {
-                mbedtls_printf( "Unrecognized option: %s\r\n", argv[i] );
-                mbedtls_printf( "Available options: " OPTIONS );
-            }
-        }
-    }
-
-    mbedtls_printf( "\r\n\r\n" );
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    mbedtls_memory_buffer_alloc_init( malloc_buf, sizeof( malloc_buf ) );
-#endif
-    memset( buf, 0xAA, sizeof( buf ) );
-    memset( tmp, 0xBB, sizeof( tmp ) );
-
-#if defined(MBEDTLS_MD4_C)
-    if( todo.md4 )
-        TIME_AND_TSC( "MD4", mbedtls_md4( buf, BUFSIZE, tmp ) );
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-    if( todo.md5 )
-        TIME_AND_TSC( "MD5", mbedtls_md5( buf, BUFSIZE, tmp ) );
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-    if( todo.ripemd160 )
-        TIME_AND_TSC( "RIPEMD160", mbedtls_ripemd160( buf, BUFSIZE, tmp ) );
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-    if( todo.sha1 )
-        TIME_AND_TSC( "SHA-1", mbedtls_sha1( buf, BUFSIZE, tmp ) );
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-    if( todo.sha256 )
-        TIME_AND_TSC( "SHA-256", mbedtls_sha256( buf, BUFSIZE, tmp, 0 ) );
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-    if( todo.sha512 )
-        TIME_AND_TSC( "SHA-512", mbedtls_sha512( buf, BUFSIZE, tmp, 0 ) );
-#endif
-
-#if defined(MBEDTLS_ARC4_C)
-    if( todo.arc4 )
-    {
-        mbedtls_arc4_context arc4;
-        mbedtls_arc4_init( &arc4 );
-        mbedtls_arc4_setup( &arc4, tmp, 32 );
-        TIME_AND_TSC( "ARC4", mbedtls_arc4_crypt( &arc4, BUFSIZE, buf, buf ) );
-        mbedtls_arc4_free( &arc4 );
-    }
-#endif
-
-#if defined(MBEDTLS_DES_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( todo.des3 )
-    {
-        mbedtls_des3_context des3;
-        mbedtls_des3_init( &des3 );
-        mbedtls_des3_set3key_enc( &des3, tmp );
-        TIME_AND_TSC( "3DES",
-                mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
-        mbedtls_des3_free( &des3 );
-    }
-
-    if( todo.des )
-    {
-        mbedtls_des_context des;
-        mbedtls_des_init( &des );
-        mbedtls_des_setkey_enc( &des, tmp );
-        TIME_AND_TSC( "DES",
-                mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
-        mbedtls_des_free( &des );
-    }
-#endif
-
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( todo.aes_cbc )
-    {
-        int keysize;
-        mbedtls_aes_context aes;
-        mbedtls_aes_init( &aes );
-        for( keysize = 128; keysize <= 256; keysize += 64 )
-        {
-            mbedtls_snprintf( title, sizeof( title ), "AES-CBC-%d", keysize );
-
-            memset( buf, 0, sizeof( buf ) );
-            memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_setkey_enc( &aes, tmp, keysize );
-
-            TIME_AND_TSC( title,
-                mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
-        }
-        mbedtls_aes_free( &aes );
-    }
-#endif
-#if defined(MBEDTLS_GCM_C)
-    if( todo.aes_gcm )
-    {
-        int keysize;
-        mbedtls_gcm_context gcm;
-
-        mbedtls_gcm_init( &gcm );
-        for( keysize = 128; keysize <= 256; keysize += 64 )
-        {
-            mbedtls_snprintf( title, sizeof( title ), "AES-GCM-%d", keysize );
-
-            memset( buf, 0, sizeof( buf ) );
-            memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_gcm_setkey( &gcm, MBEDTLS_CIPHER_ID_AES, tmp, keysize );
-
-            TIME_AND_TSC( title,
-                    mbedtls_gcm_crypt_and_tag( &gcm, MBEDTLS_GCM_ENCRYPT, BUFSIZE, tmp,
-                        12, NULL, 0, buf, buf, 16, tmp ) );
-
-            mbedtls_gcm_free( &gcm );
-        }
-    }
-#endif
-#if defined(MBEDTLS_CCM_C)
-    if( todo.aes_ccm )
-    {
-        int keysize;
-        mbedtls_ccm_context ccm;
-
-        mbedtls_ccm_init( &ccm );
-        for( keysize = 128; keysize <= 256; keysize += 64 )
-        {
-            mbedtls_snprintf( title, sizeof( title ), "AES-CCM-%d", keysize );
-
-            memset( buf, 0, sizeof( buf ) );
-            memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_ccm_setkey( &ccm, MBEDTLS_CIPHER_ID_AES, tmp, keysize );
-
-            TIME_AND_TSC( title,
-                    mbedtls_ccm_encrypt_and_tag( &ccm, BUFSIZE, tmp,
-                        12, NULL, 0, buf, buf, tmp, 16 ) );
-
-            mbedtls_ccm_free( &ccm );
-        }
-    }
-#endif
-#endif
-
-#if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( todo.camellia )
-    {
-        int keysize;
-        mbedtls_camellia_context camellia;
-        mbedtls_camellia_init( &camellia );
-        for( keysize = 128; keysize <= 256; keysize += 64 )
-        {
-            mbedtls_snprintf( title, sizeof( title ), "CAMELLIA-CBC-%d", keysize );
-
-            memset( buf, 0, sizeof( buf ) );
-            memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_camellia_setkey_enc( &camellia, tmp, keysize );
-
-            TIME_AND_TSC( title,
-                    mbedtls_camellia_crypt_cbc( &camellia, MBEDTLS_CAMELLIA_ENCRYPT,
-                        BUFSIZE, tmp, buf, buf ) );
-        }
-        mbedtls_camellia_free( &camellia );
-    }
-#endif
-
-#if defined(MBEDTLS_BLOWFISH_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( todo.blowfish )
-    {
-        int keysize;
-        mbedtls_blowfish_context blowfish;
-        mbedtls_blowfish_init( &blowfish );
-
-        for( keysize = 128; keysize <= 256; keysize += 64 )
-        {
-            mbedtls_snprintf( title, sizeof( title ), "BLOWFISH-CBC-%d", keysize );
-
-            memset( buf, 0, sizeof( buf ) );
-            memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_blowfish_setkey( &blowfish, tmp, keysize );
-
-            TIME_AND_TSC( title,
-                    mbedtls_blowfish_crypt_cbc( &blowfish, MBEDTLS_BLOWFISH_ENCRYPT, BUFSIZE,
-                        tmp, buf, buf ) );
-        }
-
-        mbedtls_blowfish_free( &blowfish );
-    }
-#endif
-
-#if defined(MBEDTLS_HAVEGE_C)
-    if( todo.havege )
-    {
-        mbedtls_havege_state hs;
-        mbedtls_havege_init( &hs );
-        TIME_AND_TSC( "HAVEGE", mbedtls_havege_random( &hs, buf, BUFSIZE ) );
-        mbedtls_havege_free( &hs );
-    }
-#endif
-
-#if defined(MBEDTLS_CTR_DRBG_C)
-    if( todo.ctr_drbg )
-    {
-        mbedtls_ctr_drbg_context ctr_drbg;
-
-        mbedtls_ctr_drbg_init( &ctr_drbg );
-
-        if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        TIME_AND_TSC( "CTR_DRBG (NOPR)",
-                if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-
-        if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
-        TIME_AND_TSC( "CTR_DRBG (PR)",
-                if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-        mbedtls_ctr_drbg_free( &ctr_drbg );
-    }
-#endif
-
-#if defined(MBEDTLS_HMAC_DRBG_C)
-    if( todo.hmac_drbg )
-    {
-        mbedtls_hmac_drbg_context hmac_drbg;
-        const mbedtls_md_info_t *md_info;
-
-        mbedtls_hmac_drbg_init( &hmac_drbg );
-
-#if defined(MBEDTLS_SHA1_C)
-        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
-            mbedtls_exit(1);
-
-        if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
-
-        if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
-                                             MBEDTLS_HMAC_DRBG_PR_ON );
-        TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ) ) == NULL )
-            mbedtls_exit(1);
-
-        if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
-
-        if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
-            mbedtls_exit(1);
-        mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
-                                             MBEDTLS_HMAC_DRBG_PR_ON );
-        TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
-        mbedtls_hmac_drbg_free( &hmac_drbg );
-#endif
-    }
-#endif
-
-#if defined(MBEDTLS_RSA_C) && \
-    defined(MBEDTLS_PEM_PARSE_C) && defined(MBEDTLS_PK_PARSE_C)
-    if( todo.rsa )
-    {
-        mbedtls_pk_context pk;
-        mbedtls_rsa_context *rsa;
-        const char *rsa_keys[] = { RSA_PRIVATE_KEY_2048, RSA_PRIVATE_KEY_4096 };
-        size_t i;
-
-        for( i = 0; i < sizeof( rsa_keys ) / sizeof( rsa_keys[0] ); i++ )
-        {
-            mbedtls_pk_init( &pk );
-            mbedtls_pk_parse_key( &pk, (const unsigned char *) rsa_keys[i],
-                                                       strlen( rsa_keys[i] ) + 1, NULL, 0 );
-            rsa = mbedtls_pk_rsa( pk );
-
-            mbedtls_snprintf( title, sizeof( title ), "RSA-%d", mbedtls_pk_get_bitlen( &pk ) );
-
-            TIME_PUBLIC( title, " public",
-                    buf[0] = 0;
-                    ret = mbedtls_rsa_public( rsa, buf, buf ) );
-
-            TIME_PUBLIC( title, "private",
-                    buf[0] = 0;
-                    ret = mbedtls_rsa_private( rsa, myrand, NULL, buf, buf ) );
-
-            mbedtls_pk_free( &pk );
-        }
-    }
-#endif
-
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_BIGNUM_C)
-    if( todo.dhm )
-    {
-        int dhm_sizes[] = { 2048, 3072 };
-        const char *dhm_P[] = {
-            MBEDTLS_DHM_RFC3526_MODP_2048_P,
-            MBEDTLS_DHM_RFC3526_MODP_3072_P,
-        };
-        const char *dhm_G[] = {
-            MBEDTLS_DHM_RFC3526_MODP_2048_G,
-            MBEDTLS_DHM_RFC3526_MODP_3072_G,
-        };
-
-        mbedtls_dhm_context dhm;
-        size_t olen;
-        for( i = 0; (size_t) i < sizeof( dhm_sizes ) / sizeof( dhm_sizes[0] ); i++ )
-        {
-            mbedtls_dhm_init( &dhm );
-
-            if( mbedtls_mpi_read_string( &dhm.P, 16, dhm_P[i] ) != 0 ||
-                mbedtls_mpi_read_string( &dhm.G, 16, dhm_G[i] ) != 0 )
-            {
-                mbedtls_exit( 1 );
-            }
-
-            dhm.len = mbedtls_mpi_size( &dhm.P );
-            mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len, myrand, NULL );
-            if( mbedtls_mpi_copy( &dhm.GY, &dhm.GX ) != 0 )
-                mbedtls_exit( 1 );
-
-            mbedtls_snprintf( title, sizeof( title ), "DHE-%d", dhm_sizes[i] );
-            TIME_PUBLIC( title, "handshake",
-                    ret |= mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, dhm.len,
-                                            myrand, NULL );
-                    ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) );
-
-            mbedtls_snprintf( title, sizeof( title ), "DH-%d", dhm_sizes[i] );
-            TIME_PUBLIC( title, "handshake",
-                    ret |= mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &olen, myrand, NULL ) );
-
-            mbedtls_dhm_free( &dhm );
-        }
-    }
-#endif
-
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA256_C)
-    if( todo.ecdsa )
-    {
-        mbedtls_ecdsa_context ecdsa;
-        const mbedtls_ecp_curve_info *curve_info;
-        size_t sig_len;
-
-        memset( buf, 0x2A, sizeof( buf ) );
-
-        for( curve_info = mbedtls_ecp_curve_list();
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++ )
-        {
-            mbedtls_ecdsa_init( &ecdsa );
-
-            if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 )
-                mbedtls_exit( 1 );
-            ecp_clear_precomputed( &ecdsa.grp );
-
-            mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s",
-                                              curve_info->name );
-            TIME_PUBLIC( title, "sign",
-                    ret = mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size,
-                                                tmp, &sig_len, myrand, NULL ) );
-
-            mbedtls_ecdsa_free( &ecdsa );
-        }
-
-        for( curve_info = mbedtls_ecp_curve_list();
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++ )
-        {
-            mbedtls_ecdsa_init( &ecdsa );
-
-            if( mbedtls_ecdsa_genkey( &ecdsa, curve_info->grp_id, myrand, NULL ) != 0 ||
-                mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size,
-                                               tmp, &sig_len, myrand, NULL ) != 0 )
-            {
-                mbedtls_exit( 1 );
-            }
-            ecp_clear_precomputed( &ecdsa.grp );
-
-            mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s",
-                                              curve_info->name );
-            TIME_PUBLIC( title, "verify",
-                    ret = mbedtls_ecdsa_read_signature( &ecdsa, buf, curve_info->bit_size,
-                                                tmp, sig_len ) );
-
-            mbedtls_ecdsa_free( &ecdsa );
-        }
-    }
-#endif
-
-#if defined(MBEDTLS_ECDH_C)
-    if( todo.ecdh )
-    {
-        mbedtls_ecdh_context ecdh;
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-        mbedtls_mpi z;
-#endif
-        const mbedtls_ecp_curve_info *curve_info;
-        size_t olen;
-
-        for( curve_info = mbedtls_ecp_curve_list();
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++ )
-        {
-            mbedtls_ecdh_init( &ecdh );
-
-            if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 ||
-                mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
-                                  myrand, NULL ) != 0 ||
-                mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 )
-            {
-                mbedtls_exit( 1 );
-            }
-            ecp_clear_precomputed( &ecdh.grp );
-
-            mbedtls_snprintf( title, sizeof( title ), "ECDHE-%s",
-                                              curve_info->name );
-            TIME_PUBLIC( title, "handshake",
-                    ret |= mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
-                                             myrand, NULL );
-                    ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ),
-                                             myrand, NULL ) );
-            mbedtls_ecdh_free( &ecdh );
-        }
-
-        /* Curve25519 needs to be handled separately */
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-        mbedtls_ecdh_init( &ecdh );
-        mbedtls_mpi_init( &z );
-
-        if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 ||
-            mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp, myrand, NULL ) != 0 )
-        {
-            mbedtls_exit( 1 );
-        }
-
-        TIME_PUBLIC(  "ECDHE-Curve25519", "handshake",
-                ret |= mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q,
-                                        myrand, NULL );
-                ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d,
-                                            myrand, NULL ) );
-
-        mbedtls_ecdh_free( &ecdh );
-        mbedtls_mpi_free( &z );
-#endif
-
-        for( curve_info = mbedtls_ecp_curve_list();
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++ )
-        {
-            mbedtls_ecdh_init( &ecdh );
-
-            if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 0 ||
-                mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
-                                  myrand, NULL ) != 0 ||
-                mbedtls_ecp_copy( &ecdh.Qp, &ecdh.Q ) != 0 ||
-                mbedtls_ecdh_make_public( &ecdh, &olen, buf, sizeof( buf),
-                                  myrand, NULL ) != 0 )
-            {
-                mbedtls_exit( 1 );
-            }
-            ecp_clear_precomputed( &ecdh.grp );
-
-            mbedtls_snprintf( title, sizeof( title ), "ECDH-%s",
-                                              curve_info->name );
-            TIME_PUBLIC( title, "handshake",
-                    ret |= mbedtls_ecdh_calc_secret( &ecdh, &olen, buf, sizeof( buf ),
-                                             myrand, NULL ) );
-            mbedtls_ecdh_free( &ecdh );
-        }
-
-        /* Curve25519 needs to be handled separately */
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-        mbedtls_ecdh_init( &ecdh );
-        mbedtls_mpi_init( &z );
-
-        if( mbedtls_ecp_group_load( &ecdh.grp, MBEDTLS_ECP_DP_CURVE25519 ) != 0 ||
-            mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Qp,
-                             myrand, NULL ) != 0 ||
-            mbedtls_ecdh_gen_public( &ecdh.grp, &ecdh.d, &ecdh.Q, myrand, NULL ) != 0 )
-        {
-            mbedtls_exit( 1 );
-        }
-
-        TIME_PUBLIC(  "ECDH-Curve25519", "handshake",
-                ret |= mbedtls_ecdh_compute_shared( &ecdh.grp, &z, &ecdh.Qp, &ecdh.d,
-                                            myrand, NULL ) );
-
-        mbedtls_ecdh_free( &ecdh );
-        mbedtls_mpi_free( &z );
-#endif
-    }
-#endif
-
-    mbedtls_printf( "\r\n" );
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    mbedtls_memory_buffer_alloc_free();
-#endif
-
-#if defined(_WIN32)
-    mbedtls_printf( "  Press Enter to exit this program.\r\n" );
-    fflush( stdout ); getchar();
-#endif
-
-    return( 0 );
-}
-
-#include "mbed-drivers/test_env.h"
-#include "minar/minar.h"
-
-static void run() {
-    MBED_HOSTTEST_TIMEOUT(150);
-    MBED_HOSTTEST_SELECT(default);
-    MBED_HOSTTEST_DESCRIPTION(mbed TLS benchmark program);
-    MBED_HOSTTEST_START("MBEDTLS_BENCHMARK");
-    MBED_HOSTTEST_RESULT(benchmark(0, NULL) == 0);
-}
-
-void app_start(int, char*[]) {
-    /* Use 115200 bps for consistency with other examples */
-    get_stdio_serial().baud(115200);
-    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
-}
-
-#endif /* TARGET_LIKE_MBED */
diff --git a/yotta/data/example-hashing/README.md b/yotta/data/example-hashing/README.md
deleted file mode 100644
index 6f0f969..0000000
--- a/yotta/data/example-hashing/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# SHA-256 Hash Example
-
-This application performs hashing of a buffer with SHA-256 using various APIs. It serves as a tutorial for the basic hashing APIs of mbed TLS.
-
-## Pre-requisites
-
-To build and run this example you must have:
-
-* A computer with the following software installed:
-  * [CMake](http://www.cmake.org/download/).
-  * [yotta](https://github.com/ARMmbed/yotta). Please note that **yotta has its own set of dependencies**, listed in the [installation instructions](http://armmbed.github.io/yotta/#installing-on-windows).
-  * [Python](https://www.python.org/downloads/).
-  * [The ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded).
-  * A serial terminal emulator (Like screen, pySerial and cu).
-* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in which case you'll have to substitute frdm-k64f-gcc with the appropriate target in the instructions below).
-* A micro-USB cable.
-* If your OS is Windows, please follow the installation instructions [for the serial port driver](https://developer.mbed.org/handbook/Windows-serial-configuration).
-
-## Getting started
-
-1. Connect the FRDM-K64F to the computer with the micro-USB cable, being careful to use the "OpenSDA" connector on the target board.
-
-2. Navigate to the mbedtls directory supplied with your release and open a terminal.
-
-3. Set the yotta target:
-
-    ```
-    yotta target frdm-k64f-gcc
-    ```
-
-4. Build mbedtls and the examples. This may take a long time if this is your first compilation:
-
-    ```
-    $ yotta build
-    ```
-
-5. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-hashing.bin` to your mbed board and wait until the LED next to the USB port stops blinking.
-
-6. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F. 
-
-   Use the following settings:
-
-    * 115200 baud (not 9600).
-    * 8N1.
-    * No flow control.
-
-7. Press the Reset button on the board.
-
-8. The output in the terminal window should look like:
-
-    ```
-    {{timeout;10}}
-    {{host_test_name;default}}
-    {{description;mbed TLS example on hashing}}
-    {{test_id;MBEDTLS_EX_HASHING}}
-    {{start}}
-
-
-    Method 1: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
-    Method 2: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
-    Method 3: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
-    Method 4: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
-
-    DONE
-    {{success}}
-    {{end}}
-    ```
diff --git a/yotta/data/example-hashing/main.cpp b/yotta/data/example-hashing/main.cpp
deleted file mode 100644
index 574152a..0000000
--- a/yotta/data/example-hashing/main.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *  Hello world example of using the hashing functions of mbed TLS
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-/*
- * This program illustrates various ways of hashing a buffer.
- * You normally need only one of these two includes.
- */
-#include "mbedtls/sha256.h" /* SHA-256 only */
-#include "mbedtls/md.h"     /* generic interface */
-
-#if defined(TARGET_LIKE_MBED)
-#include "mbed-drivers/mbed.h"
-#endif
-#include <cstdio>
-
-static void print_hex(const char *title, const unsigned char buf[], size_t len)
-{
-    printf("%s: ", title);
-
-    for (size_t i = 0; i < len; i++)
-        printf("%02x", buf[i]);
-
-    printf("\r\n");
-}
-
-static const char hello_str[] = "Hello, world!";
-static const unsigned char *hello_buffer = (const unsigned char *) hello_str;
-static const size_t hello_len = sizeof hello_str - 1;
-
-int example(void)
-{
-    printf( "\r\n\r\n" );
-
-    /*
-     * Method 1: use all-in-one function of a specific SHA-xxx module
-     */
-    unsigned char output1[32]; /* SHA-256 outputs 32 bytes */
-
-    /* 0 here means use the full SHA-256, not the SHA-224 variant */
-    mbedtls_sha256(hello_buffer, hello_len, output1, 0);
-
-    print_hex("Method 1", output1, sizeof output1);
-
-
-    /*
-     * Method 2: use the streaming interface of a specific SHA-xxx module
-     * This is useful if we get our input piecewise.
-     */
-    unsigned char output2[32];
-    mbedtls_sha256_context ctx2;
-
-    mbedtls_sha256_init(&ctx2);
-    mbedtls_sha256_starts(&ctx2, 0); /* SHA-256, not 224 */
-
-    /* Simulating multiple fragments */
-    mbedtls_sha256_update(&ctx2, hello_buffer, 1);
-    mbedtls_sha256_update(&ctx2, hello_buffer + 1, 1);
-    mbedtls_sha256_update(&ctx2, hello_buffer + 2, hello_len - 2);
-
-    mbedtls_sha256_finish(&ctx2, output2);
-    print_hex("Method 2", output2, sizeof output2);
-
-    /* Or you could re-use the context by doing mbedtls_sha256_starts() again */
-    mbedtls_sha256_free(&ctx2);
-
-    /*
-     * Method 3: use all-in-one function of the generice interface
-     */
-    unsigned char output3[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */
-
-    /* Can easily pick any hash you want, by identifier */
-    const mbedtls_md_info_t *md_info3 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
-
-    if (md_info3 == NULL)
-    {
-        printf("SHA256 not available\r\n");
-        return 1;
-    }
-
-    int ret3 = mbedtls_md(md_info3, hello_buffer, hello_len, output3);
-
-    if (ret3 != 0)
-    {
-        printf("md() returned -0x%04X\r\n", -ret3);
-        return 1;
-    }
-
-    print_hex("Method 3", output3, mbedtls_md_get_size(md_info3));
-
-
-    /*
-     * Method 4: streaming & generic interface
-     */
-    unsigned char output4[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */
-
-    const mbedtls_md_info_t *md_info4 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
-
-    if (md_info4 == NULL)
-    {
-        printf("SHA256 not available\r\n");
-        return 1;
-    }
-
-    mbedtls_md_context_t ctx4;
-
-    mbedtls_md_init(&ctx4);
-
-    int ret4 = mbedtls_md_init_ctx(&ctx4, md_info4);
-    if (ret4 != 0)
-    {
-        printf("md_init_ctx() returned -0x%04X\r\n", -ret4);
-        return 1;
-    }
-
-    mbedtls_md_starts(&ctx4);
-
-    /* Simulating multiple fragments */
-    mbedtls_md_update(&ctx4, hello_buffer, 1);
-    mbedtls_md_update(&ctx4, hello_buffer + 1, 1);
-    mbedtls_md_update(&ctx4, hello_buffer + 2, hello_len - 2);
-
-    mbedtls_md_finish(&ctx4, output4);
-    print_hex("Method 4", output4, mbedtls_md_get_size(md_info4));
-
-    /* Or you could re-use the context by doing mbedtls_md_starts() again */
-    mbedtls_md_free(&ctx4);
-
-
-    printf("\r\nDONE\r\n");
-
-    return 0;
-}
-
-#if defined(TARGET_LIKE_MBED)
-
-#include "mbed-drivers/test_env.h"
-#include "minar/minar.h"
-
-static void run() {
-    MBED_HOSTTEST_TIMEOUT(10);
-    MBED_HOSTTEST_SELECT(default);
-    MBED_HOSTTEST_DESCRIPTION(mbed TLS example on hashing);
-    MBED_HOSTTEST_START("MBEDTLS_EX_HASHING");
-    MBED_HOSTTEST_RESULT(example() == 0);
-}
-
-void app_start(int, char*[]) {
-    /* Use 115200 bps for consistency with other examples */
-    get_stdio_serial().baud(115200);
-    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
-}
-
-#else
-
-int main() {
-    return example();
-}
-
-#endif
diff --git a/yotta/data/example-selftest/README.md b/yotta/data/example-selftest/README.md
deleted file mode 100644
index b8e9cd4..0000000
--- a/yotta/data/example-selftest/README.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# mbed TLS Selftest Example
-
-This application runs the various selftest functions of individual mbed TLS components. It serves as a basic sanity check to verify operation of mbed TLS on your platform. In the future, a wider portion of the mbed TLS test suite will become part of this example application.
-
-## Pre-requisites
-
-To build and run this example you must have:
-
-* A computer with the following software installed:
-  * [CMake](http://www.cmake.org/download/).
-  * [yotta](https://github.com/ARMmbed/yotta). Please note that **yotta has its own set of dependencies**, listed in the [installation instructions](http://armmbed.github.io/yotta/#installing-on-windows).
-  * [Python](https://www.python.org/downloads/).
-  * [The ARM GCC toolchain](https://launchpad.net/gcc-arm-embedded).
-  * A serial terminal emulator (Like screen, pySerial and cu).
-* An [FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) development board, or another board supported by mbed OS (in which case you'll have to substitute frdm-k64f-gcc with the appropriate target in the instructions below).
-* A micro-USB cable.
-* If your OS is Windows, please follow the installation instructions [for the serial port driver](https://developer.mbed.org/handbook/Windows-serial-configuration).
-
-## Getting started
-
-1. Connect the FRDM-K64F to the computer with the micro-USB cable, being careful to use the "OpenSDA" connector on the target board.
-
-2. Navigate to the mbedtls directory supplied with your release and open a terminal.
-
-3. Set the yotta target:
-
-    ```
-    yotta target frdm-k64f-gcc
-    ```
-
-4. Build mbedtls and the examples. This may take a long time if this is your first compilation:
-
-    ```
-    $ yotta build
-    ```
-
-5. Copy `build/frdm-k64f-gcc/test/mbedtls-test-example-selftest.bin` to your mbed board and wait until the LED next to the USB port stops blinking.
-
-6. Start the serial terminal emulator and connect to the virtual serial port presented by FRDM-K64F. 
-
-   Use the following settings:
-
-    * 115200 baud (not 9600).
-    * 8N1.
-    * No flow control.
-
-7. Press the Reset button on the board.
-
-8. The output in the terminal window should look like:
-
-    ```
-    {{timeout;40}}
-    {{host_test_name;default}}
-    {{description;mbed TLS selftest program}}
-    {{test_id;MBEDTLS_SELFTEST}}
-    {{start}}
-
-      SHA-224 test #1: passed
-      SHA-224 test #2: passed
-      SHA-224 test #3: passed
-      SHA-256 test #1: passed
-      SHA-256 test #2: passed
-      SHA-256 test #3: passed
-
-        [ ... several lines omitted ... ]
-
-      CTR_DRBG (PR = TRUE) : passed
-      CTR_DRBG (PR = FALSE): passed
-
-      HMAC_DRBG (PR = True) : passed
-      HMAC_DRBG (PR = False) : passed
-
-      ECP test #1 (constant op_count, base point G): passed
-      ECP test #2 (constant op_count, other point): passed
-
-      ENTROPY test: passed
-
-      [ All tests passed ]
-
-    {{success}}
-    {{end}}
-    ```
diff --git a/yotta/data/example-selftest/main.cpp b/yotta/data/example-selftest/main.cpp
deleted file mode 100644
index 0ff5b04..0000000
--- a/yotta/data/example-selftest/main.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- *  Self-test demonstration program
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if !defined(POLARSSL_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#include "mbedtls/entropy.h"
-#include "mbedtls/hmac_drbg.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/dhm.h"
-#include "mbedtls/gcm.h"
-#include "mbedtls/ccm.h"
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
-#include "mbedtls/md5.h"
-#include "mbedtls/ripemd160.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-#include "mbedtls/sha512.h"
-#include "mbedtls/arc4.h"
-#include "mbedtls/des.h"
-#include "mbedtls/aes.h"
-#include "mbedtls/camellia.h"
-#include "mbedtls/base64.h"
-#include "mbedtls/bignum.h"
-#include "mbedtls/rsa.h"
-#include "mbedtls/x509.h"
-#include "mbedtls/xtea.h"
-#include "mbedtls/pkcs5.h"
-#include "mbedtls/ecp.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf     printf
-#endif
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#include "mbedtls/memory_buffer_alloc.h"
-#endif
-
-int selftest( int argc, char *argv[] )
-{
-    int ret = 0, v;
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    unsigned char buf[1000000];
-#endif
-
-    if( argc == 2 && strcmp( argv[1], "-quiet" ) == 0 )
-        v = 0;
-    else
-    {
-        v = 1;
-        mbedtls_printf( "\n" );
-    }
-
-#if defined(MBEDTLS_SELF_TEST)
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    mbedtls_memory_buffer_alloc_init( buf, sizeof(buf) );
-#endif
-
-#if defined(MBEDTLS_MD2_C)
-    if( ( ret = mbedtls_md2_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-    if( ( ret = mbedtls_md4_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-    if( ( ret = mbedtls_md5_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-    if( ( ret = mbedtls_ripemd160_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-    if( ( ret = mbedtls_sha1_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-    if( ( ret = mbedtls_sha256_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-    if( ( ret = mbedtls_sha512_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_ARC4_C)
-    if( ( ret = mbedtls_arc4_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_DES_C)
-    if( ( ret = mbedtls_des_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_AES_C)
-    if( ( ret = mbedtls_aes_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)
-    if( ( ret = mbedtls_gcm_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)
-    if( ( ret = mbedtls_ccm_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_BASE64_C)
-    if( ( ret = mbedtls_base64_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_BIGNUM_C)
-    if( ( ret = mbedtls_mpi_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_RSA_C)
-    if( ( ret = mbedtls_rsa_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_X509_USE_C)
-    if( ( ret = mbedtls_x509_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_XTEA_C)
-    if( ( ret = mbedtls_xtea_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_CAMELLIA_C)
-    if( ( ret = mbedtls_camellia_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_CTR_DRBG_C)
-    if( ( ret = mbedtls_ctr_drbg_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_HMAC_DRBG_C)
-    if( ( ret = mbedtls_hmac_drbg_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_ECP_C)
-    if( ( ret = mbedtls_ecp_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_DHM_C)
-    if( ( ret = mbedtls_dhm_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_ENTROPY_C)
-    if( ( ret = mbedtls_entropy_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_PKCS5_C)
-    if( ( ret = mbedtls_pkcs5_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#if defined(MBEDTLS_TIMING_C)
-    if( ( ret = mbedtls_timing_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-#else
-    mbedtls_printf( " POLARSSL_SELF_TEST not defined.\n" );
-#endif
-
-    if( v != 0 )
-    {
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_memory_buffer_alloc_status();
-#endif
-    }
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    mbedtls_memory_buffer_alloc_free();
-
-    if( ( ret = mbedtls_memory_buffer_alloc_self_test( v ) ) != 0 )
-        return( ret );
-#endif
-
-    if( v != 0 )
-    {
-        mbedtls_printf( "  [ All tests passed ]\n\n" );
-#if defined(_WIN32)
-        mbedtls_printf( "  Press Enter to exit this program.\n" );
-        fflush( stdout ); getchar();
-#endif
-    }
-
-    return( ret );
-}
-
-#if defined(TARGET_LIKE_MBED)
-
-#include "mbed-drivers/test_env.h"
-#include "minar/minar.h"
-
-static void run() {
-    MBED_HOSTTEST_TIMEOUT(40);
-    MBED_HOSTTEST_SELECT(default);
-    MBED_HOSTTEST_DESCRIPTION(mbed TLS selftest program);
-    MBED_HOSTTEST_START("MBEDTLS_SELFTEST");
-    MBED_HOSTTEST_RESULT(selftest(0, NULL) == 0);
-}
-
-void app_start(int, char*[]) {
-    /* Use 115200 bps for consistency with other examples */
-    get_stdio_serial().baud(115200);
-    minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
-}
-
-#else
-
-int main() {
-    return selftest(0, NULL);
-}
-
-#endif
diff --git a/yotta/data/module.json b/yotta/data/module.json
deleted file mode 100644
index 0b8b822..0000000
--- a/yotta/data/module.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "name": "mbedtls",
-    "version": "2.3.1",
-    "description": "The mbed TLS crypto/SSL/TLS library",
-    "licenses": [
-        {
-            "url": "https://spdx.org/licenses/Apache-2.0",
-            "type": "Apache-2.0"
-        }
-    ],
-    "dependencies": {},
-    "targetDependencies": {
-        "mbed": { "cmsis-core": "^1.0.0" }
-    },
-    "testTargetDependencies": {
-        "mbed": { "mbed-drivers": "^1.0.0" }
-    }
-}
diff --git a/yotta/data/target_config.h b/yotta/data/target_config.h
deleted file mode 100644
index f350ce3..0000000
--- a/yotta/data/target_config.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Temporary target-specific config.h for entropy collection
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if defined(TARGET_LIKE_MBED)
-#define MBEDTLS_NO_PLATFORM_ENTROPY
-#undef MBEDTLS_HAVE_TIME_DATE
-#undef MBEDTLS_FS_IO
-#endif
-
-/*
- * WARNING: this is temporary!
- * This should be in a separate yotta module which would be a target
- * dependency of mbedtls (see IOTSSL-313)
- */
-#if defined(TARGET_LIKE_K64F)
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
-#endif