Merge remote-tracking branch 'public/pr/1915' into iotssl-165-dtls-hs-fragmentation-new

* public/pr/1915:
  Adapt ChangeLog
  Fix mbedtls_ssl_get_record_expansion() for ChaChaPoly and CBC
diff --git a/ChangeLog b/ChangeLog
index d5101f4..af12f41 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,13 +2,34 @@
 
 = mbed TLS x.x.x branch released xxxx-xx-xx
 
+Features
+   * Add support for fragmentation of outoing DTLS handshake messages.
+
 Bugfix
    * 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.
+     Fix contributed by Espressif Systems.
+   * 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.
+   * 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 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.
 
+Changes
+   * Copy headers preserving timestamps when doing a "make install".
+     Contributed by xueruini.
+   * Allow the forward declaration of public structs. Contributed by Dawid
+     Drozd. Fixes #1215 raised by randombit.
+   * Improve compatibility with some alternative CCM implementations by using
+     CCM test vectors from RAM.
+
+INTERNAL NOTE: need to bump soversion of libmbedtls:
+- added new member 'mtu' to public 'mbedtls_ssl_conf' structure
+
 = mbed TLS 2.12.0 branch released 2018-07-25
 
 Security
diff --git a/Makefile b/Makefile
index a0fcb2b..78c1acb 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@
 ifndef WINDOWS
 install: no_test
 	mkdir -p $(DESTDIR)/include/mbedtls
-	cp -r include/mbedtls $(DESTDIR)/include
+	cp -rp include/mbedtls $(DESTDIR)/include
 
 	mkdir -p $(DESTDIR)/lib
 	cp -RP library/libmbedtls.*    $(DESTDIR)/lib
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index f6603d5..4c8dab3 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -79,7 +79,7 @@
 /**
  * \brief The AES context-type definition.
  */
-typedef struct
+typedef struct mbedtls_aes_context
 {
     int nr;                     /*!< The number of rounds. */
     uint32_t *rk;               /*!< AES round keys. */
@@ -98,7 +98,7 @@
 /**
  * \brief The AES XTS context-type definition.
  */
-typedef struct
+typedef struct mbedtls_aes_xts_context
 {
     mbedtls_aes_context crypt; /*!< The AES context to use for AES block
                                         encryption or decryption. */
diff --git a/include/mbedtls/arc4.h b/include/mbedtls/arc4.h
index f11fc5b..83a7461 100644
--- a/include/mbedtls/arc4.h
+++ b/include/mbedtls/arc4.h
@@ -53,7 +53,7 @@
  *            security risk. We recommend considering stronger ciphers instead.
  *
  */
-typedef struct
+typedef struct mbedtls_arc4_context
 {
     int x;                      /*!< permutation index */
     int y;                      /*!< permutation index */
diff --git a/include/mbedtls/aria.h b/include/mbedtls/aria.h
index bae0621..4a79c13 100644
--- a/include/mbedtls/aria.h
+++ b/include/mbedtls/aria.h
@@ -62,7 +62,7 @@
 /**
  * \brief The ARIA context-type definition.
  */
-typedef struct
+typedef struct mbedtls_aria_context
 {
     unsigned char nr;           /*!< The number of rounds (12, 14 or 16) */
     /*! The ARIA round keys. */
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 31383b1..732ecbe 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -177,7 +177,7 @@
 /**
  * \brief          MPI structure
  */
-typedef struct
+typedef struct mbedtls_mpi
 {
     int s;              /*!<  integer sign      */
     size_t n;           /*!<  total # of limbs  */
diff --git a/include/mbedtls/blowfish.h b/include/mbedtls/blowfish.h
index 985faa4..eea6882 100644
--- a/include/mbedtls/blowfish.h
+++ b/include/mbedtls/blowfish.h
@@ -55,7 +55,7 @@
 /**
  * \brief          Blowfish context structure
  */
-typedef struct
+typedef struct mbedtls_blowfish_context
 {
     uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2];    /*!<  Blowfish round keys    */
     uint32_t S[4][256];                 /*!<  key dependent S-boxes  */
diff --git a/include/mbedtls/camellia.h b/include/mbedtls/camellia.h
index 7e4721a..fa1e05e 100644
--- a/include/mbedtls/camellia.h
+++ b/include/mbedtls/camellia.h
@@ -51,7 +51,7 @@
 /**
  * \brief          CAMELLIA context structure
  */
-typedef struct
+typedef struct mbedtls_camellia_context
 {
     int nr;                     /*!<  number of rounds  */
     uint32_t rk[68];            /*!<  CAMELLIA round keys    */
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index 5d727e7..e1dc124 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -68,7 +68,8 @@
  * \brief    The CCM context-type definition. The CCM context is passed
  *           to the APIs called.
  */
-typedef struct {
+typedef struct mbedtls_ccm_context
+{
     mbedtls_cipher_context_t cipher_ctx;    /*!< The cipher context used. */
 }
 mbedtls_ccm_context;
diff --git a/include/mbedtls/chacha20.h b/include/mbedtls/chacha20.h
index 47bd7d3..cfea40a 100644
--- a/include/mbedtls/chacha20.h
+++ b/include/mbedtls/chacha20.h
@@ -52,7 +52,7 @@
 
 #if !defined(MBEDTLS_CHACHA20_ALT)
 
-typedef struct
+typedef struct mbedtls_chacha20_context
 {
     uint32_t state[16];          /*! The state (before round operations). */
     uint8_t  keystream8[64];     /*! Leftover keystream bytes. */
diff --git a/include/mbedtls/chachapoly.h b/include/mbedtls/chachapoly.h
index 42b2b23..7de6f4e 100644
--- a/include/mbedtls/chachapoly.h
+++ b/include/mbedtls/chachapoly.h
@@ -60,7 +60,7 @@
 
 #include "chacha20.h"
 
-typedef struct
+typedef struct mbedtls_chachapoly_context
 {
     mbedtls_chacha20_context chacha20_ctx;  /**< The ChaCha20 context. */
     mbedtls_poly1305_context poly1305_ctx;  /**< The Poly1305 context. */
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 7f3477a..dfb1541 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -236,7 +236,8 @@
  * Cipher information. Allows calling cipher functions
  * in a generic way.
  */
-typedef struct {
+typedef struct mbedtls_cipher_info_t
+{
     /** Full cipher identifier. For example,
      * MBEDTLS_CIPHER_AES_256_CBC.
      */
@@ -277,7 +278,8 @@
 /**
  * Generic cipher context.
  */
-typedef struct {
+typedef struct mbedtls_cipher_context_t
+{
     /** Information about the associated cipher. */
     const mbedtls_cipher_info_t *cipher_info;
 
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index 3835d72..3a4b7f3 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -108,7 +108,7 @@
 /**
  * \brief          The CTR_DRBG context structure.
  */
-typedef struct
+typedef struct mbedtls_ctr_drbg_context
 {
     unsigned char counter[16];  /*!< The counter (V). */
     int reseed_counter;         /*!< The reseed counter. */
diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h
index 6eb7d03..91d16b6 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -61,7 +61,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
-typedef struct
+typedef struct mbedtls_des_context
 {
     uint32_t sk[32];            /*!<  DES subkeys       */
 }
@@ -70,7 +70,7 @@
 /**
  * \brief          Triple-DES context structure
  */
-typedef struct
+typedef struct mbedtls_des3_context
 {
     uint32_t sk[96];            /*!<  3DES subkeys      */
 }
diff --git a/include/mbedtls/dhm.h b/include/mbedtls/dhm.h
index 75317a8..3e11789 100644
--- a/include/mbedtls/dhm.h
+++ b/include/mbedtls/dhm.h
@@ -96,7 +96,7 @@
 /**
  * \brief          The DHM context structure.
  */
-typedef struct
+typedef struct mbedtls_dhm_context
 {
     size_t len;         /*!<  The size of \p P in Bytes. */
     mbedtls_mpi P;      /*!<  The prime modulus. */
diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h
index 5fdf55a..95f3980 100644
--- a/include/mbedtls/ecdh.h
+++ b/include/mbedtls/ecdh.h
@@ -52,7 +52,7 @@
 /**
  * \brief           The ECDH context structure.
  */
-typedef struct
+typedef struct mbedtls_ecdh_context
 {
     mbedtls_ecp_group grp;   /*!< The elliptic curve used. */
     mbedtls_mpi d;           /*!< The private key. */
diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h
index cc2b316..59d12f0 100644
--- a/include/mbedtls/ecjpake.h
+++ b/include/mbedtls/ecjpake.h
@@ -68,7 +68,7 @@
  * convetion from the Thread v1.0 spec. Correspondance is indicated in the
  * description as a pair C: client name, S: server name
  */
-typedef struct
+typedef struct mbedtls_ecjpake_context
 {
     const mbedtls_md_info_t *md_info;   /**< Hash to use                    */
     mbedtls_ecp_group grp;              /**< Elliptic curve                 */
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 3a40798..ed1b9d7 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -92,7 +92,7 @@
 /**
  * Curve information, for use by other modules.
  */
-typedef struct
+typedef struct mbedtls_ecp_curve_info
 {
     mbedtls_ecp_group_id grp_id;    /*!< An internal identifier. */
     uint16_t tls_id;                /*!< The TLS NamedCurve identifier. */
@@ -111,7 +111,7 @@
  *                  Otherwise, \p X and \p Y are its standard (affine)
  *                  coordinates.
  */
-typedef struct
+typedef struct mbedtls_ecp_point
 {
     mbedtls_mpi X;          /*!< The X coordinate of the ECP point. */
     mbedtls_mpi Y;          /*!< The Y coordinate of the ECP point. */
@@ -156,7 +156,7 @@
  * reduction. It must return 0 on success and non-zero on failure.
  *
  */
-typedef struct
+typedef struct mbedtls_ecp_group
 {
     mbedtls_ecp_group_id id;    /*!< An internal group identifier. */
     mbedtls_mpi P;              /*!< The prime modulus of the base field. */
@@ -251,7 +251,7 @@
  * \note    Members are deliberately in the same order as in the
  *          ::mbedtls_ecdsa_context structure.
  */
-typedef struct
+typedef struct mbedtls_ecp_keypair
 {
     mbedtls_ecp_group grp;      /*!<  Elliptic curve and base point     */
     mbedtls_mpi d;              /*!<  our secret value                  */
diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h
index a5cb05a..ca06dc3 100644
--- a/include/mbedtls/entropy.h
+++ b/include/mbedtls/entropy.h
@@ -107,7 +107,7 @@
 /**
  * \brief           Entropy source state
  */
-typedef struct
+typedef struct mbedtls_entropy_source_state
 {
     mbedtls_entropy_f_source_ptr    f_source;   /**< The entropy source callback */
     void *          p_source;   /**< The callback data pointer */
@@ -120,7 +120,7 @@
 /**
  * \brief           Entropy context structure
  */
-typedef struct
+typedef struct mbedtls_entropy_context
 {
     int accumulator_started;
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 87535ab..d2098eb 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -53,7 +53,8 @@
 /**
  * \brief          The GCM context structure.
  */
-typedef struct {
+typedef struct mbedtls_gcm_context
+{
     mbedtls_cipher_context_t cipher_ctx;  /*!< The cipher context used. */
     uint64_t HL[16];                      /*!< Precalculated HTable low. */
     uint64_t HH[16];                      /*!< Precalculated HTable high. */
diff --git a/include/mbedtls/havege.h b/include/mbedtls/havege.h
index d4cb3ed..57e8c40 100644
--- a/include/mbedtls/havege.h
+++ b/include/mbedtls/havege.h
@@ -35,7 +35,7 @@
 /**
  * \brief          HAVEGE state structure
  */
-typedef struct
+typedef struct mbedtls_havege_state
 {
     int PT1, PT2, offset[2];
     int pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 2608de8..3bc675e 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -74,7 +74,7 @@
 /**
  * HMAC_DRBG context.
  */
-typedef struct
+typedef struct mbedtls_hmac_drbg_context
 {
     /* Working state: the key K is not stored explicitely,
      * but is implied by the HMAC context */
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 6b6f5c5..bf29524 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -80,7 +80,8 @@
 /**
  * The generic message-digest context.
  */
-typedef struct {
+typedef struct mbedtls_md_context_t
+{
     /** Information about the associated message digest. */
     const mbedtls_md_info_t *md_info;
 
diff --git a/include/mbedtls/md2.h b/include/mbedtls/md2.h
index 08e75b2..a46bddb 100644
--- a/include/mbedtls/md2.h
+++ b/include/mbedtls/md2.h
@@ -55,7 +55,7 @@
  *                 stronger message digests instead.
  *
  */
-typedef struct
+typedef struct mbedtls_md2_context
 {
     unsigned char cksum[16];    /*!< checksum of the data block */
     unsigned char state[48];    /*!< intermediate digest state  */
diff --git a/include/mbedtls/md4.h b/include/mbedtls/md4.h
index 8ee4e5c..1672e90 100644
--- a/include/mbedtls/md4.h
+++ b/include/mbedtls/md4.h
@@ -56,7 +56,7 @@
  *                 stronger message digests instead.
  *
  */
-typedef struct
+typedef struct mbedtls_md4_context
 {
     uint32_t total[2];          /*!< number of bytes processed  */
     uint32_t state[4];          /*!< intermediate digest state  */
diff --git a/include/mbedtls/md5.h b/include/mbedtls/md5.h
index 43ead4b..4c95090 100644
--- a/include/mbedtls/md5.h
+++ b/include/mbedtls/md5.h
@@ -55,7 +55,7 @@
  *                 stronger message digests instead.
  *
  */
-typedef struct
+typedef struct mbedtls_md5_context
 {
     uint32_t total[2];          /*!< number of bytes processed  */
     uint32_t state[4];          /*!< intermediate digest state  */
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index 9f07eeb..4c7ef00 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -84,7 +84,7 @@
  * (eg two file descriptors for combined IPv4 + IPv6 support, or additional
  * structures for hand-made UDP demultiplexing).
  */
-typedef struct
+typedef struct mbedtls_net_context
 {
     int fd;             /**< The underlying file descriptor                 */
 }
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index f825548..6fbd018 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -403,7 +403,8 @@
 /**
  * \brief Base OID descriptor structure
  */
-typedef struct {
+typedef struct mbedtls_oid_descriptor_t
+{
     const char *asn1;               /*!< OID ASN.1 representation       */
     size_t asn1_len;                /*!< length of asn1                 */
     const char *name;               /*!< official name (e.g. from RFC)  */
diff --git a/include/mbedtls/pem.h b/include/mbedtls/pem.h
index 2cf4c0a..fa82f7b 100644
--- a/include/mbedtls/pem.h
+++ b/include/mbedtls/pem.h
@@ -51,7 +51,7 @@
 /**
  * \brief       PEM context structure
  */
-typedef struct
+typedef struct mbedtls_pem_context
 {
     unsigned char *buf;     /*!< buffer for decoded data             */
     size_t buflen;          /*!< length of the buffer                */
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index ee06b2f..db54c6a 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -87,7 +87,7 @@
  * \brief           Options for RSASSA-PSS signature verification.
  *                  See \c mbedtls_rsa_rsassa_pss_verify_ext()
  */
-typedef struct
+typedef struct mbedtls_pk_rsassa_pss_options
 {
     mbedtls_md_type_t mgf1_hash_id;
     int expected_salt_len;
@@ -107,7 +107,7 @@
 /**
  * \brief           Item to send to the debug module
  */
-typedef struct
+typedef struct mbedtls_pk_debug_item
 {
     mbedtls_pk_debug_type type;
     const char *name;
@@ -125,7 +125,7 @@
 /**
  * \brief           Public key container
  */
-typedef struct
+typedef struct mbedtls_pk_context
 {
     const mbedtls_pk_info_t *   pk_info; /**< Public key informations        */
     void *                      pk_ctx;  /**< Underlying public key context  */
diff --git a/include/mbedtls/pkcs11.h b/include/mbedtls/pkcs11.h
index bf65c55..02427dd 100644
--- a/include/mbedtls/pkcs11.h
+++ b/include/mbedtls/pkcs11.h
@@ -50,7 +50,8 @@
 /**
  * Context for PKCS #11 private keys.
  */
-typedef struct {
+typedef struct mbedtls_pkcs11_context
+{
         pkcs11h_certificate_t pkcs11h_cert;
         int len;
 } mbedtls_pkcs11_context;
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index 624cc64..a40a64f 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -315,7 +315,8 @@
  * \note    This structure may be used to assist platform-specific
  *          setup or teardown operations.
  */
-typedef struct {
+typedef struct mbedtls_platform_context
+{
     char dummy; /**< A placeholder member, as empty structs are not portable. */
 }
 mbedtls_platform_context;
diff --git a/include/mbedtls/poly1305.h b/include/mbedtls/poly1305.h
index 54b50ab..c490cdf 100644
--- a/include/mbedtls/poly1305.h
+++ b/include/mbedtls/poly1305.h
@@ -52,7 +52,7 @@
 
 #if !defined(MBEDTLS_POLY1305_ALT)
 
-typedef struct
+typedef struct mbedtls_poly1305_context
 {
     uint32_t r[4];      /** The value for 'r' (low 128 bits of the key). */
     uint32_t s[4];      /** The value for 's' (high 128 bits of the key). */
diff --git a/include/mbedtls/ripemd160.h b/include/mbedtls/ripemd160.h
index a0dac0c..0c8e568 100644
--- a/include/mbedtls/ripemd160.h
+++ b/include/mbedtls/ripemd160.h
@@ -46,7 +46,7 @@
 /**
  * \brief          RIPEMD-160 context structure
  */
-typedef struct
+typedef struct mbedtls_ripemd160_context
 {
     uint32_t total[2];          /*!< number of bytes processed  */
     uint32_t state[5];          /*!< intermediate digest state  */
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 19eb2ee..6eea5af 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -92,7 +92,7 @@
  *          is deprecated. All manipulation should instead be done through
  *          the public interface functions.
  */
-typedef struct
+typedef struct mbedtls_rsa_context
 {
     int ver;                    /*!<  Always 0.*/
     size_t len;                 /*!<  The size of \p N in Bytes. */
diff --git a/include/mbedtls/sha1.h b/include/mbedtls/sha1.h
index 65a124c..7a19da0 100644
--- a/include/mbedtls/sha1.h
+++ b/include/mbedtls/sha1.h
@@ -58,7 +58,7 @@
  *                 stronger message digests instead.
  *
  */
-typedef struct
+typedef struct mbedtls_sha1_context
 {
     uint32_t total[2];          /*!< The number of Bytes processed.  */
     uint32_t state[5];          /*!< The intermediate digest state.  */
diff --git a/include/mbedtls/sha256.h b/include/mbedtls/sha256.h
index adf31a8..33aff28 100644
--- a/include/mbedtls/sha256.h
+++ b/include/mbedtls/sha256.h
@@ -53,7 +53,7 @@
  *                 checksum calculations. The choice between these two is
  *                 made in the call to mbedtls_sha256_starts_ret().
  */
-typedef struct
+typedef struct mbedtls_sha256_context
 {
     uint32_t total[2];          /*!< The number of Bytes processed.  */
     uint32_t state[8];          /*!< The intermediate digest state.  */
diff --git a/include/mbedtls/sha512.h b/include/mbedtls/sha512.h
index 5bb83f4..0145890 100644
--- a/include/mbedtls/sha512.h
+++ b/include/mbedtls/sha512.h
@@ -52,7 +52,7 @@
  *                 checksum calculations. The choice between these two is
  *                 made in the call to mbedtls_sha512_starts_ret().
  */
-typedef struct
+typedef struct mbedtls_sha512_context
 {
     uint64_t total[2];          /*!< The number of Bytes processed. */
     uint64_t state[8];          /*!< The intermediate digest state. */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 2d511a8..706e272 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -958,6 +958,10 @@
     unsigned int dhm_min_bitlen;    /*!< min. bit length of the DHM prime   */
 #endif
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    uint16_t mtu;                   /*!< path mtu, used to fragment outoing messages */
+#endif
+
     unsigned char max_major_ver;    /*!< max. major version used            */
     unsigned char max_minor_ver;    /*!< max. minor version used            */
     unsigned char min_major_ver;    /*!< min. major version used            */
@@ -2423,6 +2427,35 @@
                                           char cert_req_ca_list );
 #endif /* MBEDTLS_SSL_SRV_C */
 
+#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           This only controls the size of the packet we send.
+ *                 Client-side, you can request the server to use smaller
+ *                 records with \c mbedtls_conf_max_frag_len().
+ *
+ * \note           If both a MTU and a maximum fragment length have been
+ *                 configured (or negotiated with the peer), the lower limit
+ *                 is used.
+ *
+ * \note           Values larger than \c MBEDTLS_SSL_OUT_CONTENT_LEN have no
+ *                 effect. This can only be used to decrease the maximum size
+ *                 of datagrams sent. Values lower than record layer expansion
+ *                 are ignored.
+ *
+ * \param conf     SSL configuration
+ * \param mtu      Value of the path MTU in bytes
+ */
+void mbedtls_ssl_conf_mtu( mbedtls_ssl_config *conf, uint16_t mtu );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 /**
  * \brief          Set the maximum fragment length to emit and/or negotiate
@@ -2433,6 +2466,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 paylaod,
+ *                 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_conf_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 +2740,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 +2757,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 +2767,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_conf_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
diff --git a/include/mbedtls/ssl_cookie.h b/include/mbedtls/ssl_cookie.h
index 80b65bb..6a0ad4f 100644
--- a/include/mbedtls/ssl_cookie.h
+++ b/include/mbedtls/ssl_cookie.h
@@ -50,7 +50,7 @@
 /**
  * \brief          Context for the default cookie functions.
  */
-typedef struct
+typedef struct mbedtls_ssl_cookie_ctx
 {
     mbedtls_md_context_t    hmac_ctx;   /*!< context for the HMAC portion   */
 #if !defined(MBEDTLS_HAVE_TIME)
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index d214703..18982f8 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -298,8 +298,9 @@
 
     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
@@ -559,6 +560,7 @@
 int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
 
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
 
@@ -668,6 +670,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/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index 93ad46a..b2686df 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -44,7 +44,7 @@
 /**
  * \brief   Information for session ticket protection
  */
-typedef struct
+typedef struct mbedtls_ssl_ticket_key
 {
     unsigned char name[4];          /*!< random key identifier              */
     uint32_t generation_time;       /*!< key generation timestamp (seconds) */
@@ -55,7 +55,7 @@
 /**
  * \brief   Context for session ticket handling functions
  */
-typedef struct
+typedef struct mbedtls_ssl_ticket_context
 {
     mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys             */
     unsigned char active;           /*!< index of the currently active key  */
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index c25daa5..5112ebb 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -42,7 +42,7 @@
 
 #if defined(MBEDTLS_THREADING_PTHREAD)
 #include <pthread.h>
-typedef struct
+typedef struct mbedtls_threading_mutex_t
 {
     pthread_mutex_t mutex;
     char is_valid;
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index bbcb906..a965fe0 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -51,7 +51,7 @@
 /**
  * \brief          Context for mbedtls_timing_set/get_delay()
  */
-typedef struct
+typedef struct mbedtls_timing_delay_context
 {
     struct mbedtls_timing_hr_time   timer;
     uint32_t                        int_ms;
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index ac23cff..d41ec93 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -105,7 +105,7 @@
  *
  * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG().
  */
-typedef struct
+typedef struct mbedtls_x509_crt_profile
 {
     uint32_t allowed_mds;       /**< MDs for signatures         */
     uint32_t allowed_pks;       /**< PK algs for signatures     */
diff --git a/include/mbedtls/xtea.h b/include/mbedtls/xtea.h
index 8df708a..c70c3fe 100644
--- a/include/mbedtls/xtea.h
+++ b/include/mbedtls/xtea.h
@@ -50,7 +50,7 @@
 /**
  * \brief          XTEA context structure
  */
-typedef struct
+typedef struct mbedtls_xtea_context
 {
     uint32_t k[4];       /*!< key */
 }
diff --git a/library/ccm.c b/library/ccm.c
index 804eaf8..90cab8e 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -381,7 +381,8 @@
  */
 
 #define NB_TESTS 3
-
+#define CCM_SELFTEST_PT_MAX_LEN 24
+#define CCM_SELFTEST_CT_MAX_LEN 32
 /*
  * The data is the same for all tests, only the used length changes
  */
@@ -401,7 +402,7 @@
     0x10, 0x11, 0x12, 0x13
 };
 
-static const unsigned char msg[] = {
+static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
@@ -412,7 +413,7 @@
 static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
 static const size_t tag_len[NB_TESTS] = { 4, 6,  8  };
 
-static const unsigned char res[NB_TESTS][32] = {
+static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
     {   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
     {   0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
         0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
@@ -426,7 +427,13 @@
 int mbedtls_ccm_self_test( int verbose )
 {
     mbedtls_ccm_context ctx;
-    unsigned char out[32];
+    /*
+     * Some hardware accelerators require the input and output buffers
+     * would be in RAM, because the flash is not accessible.
+     * Use buffers on the stack to hold the test vectors data.
+     */
+    unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
+    unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
     size_t i;
     int ret;
 
@@ -445,27 +452,32 @@
         if( verbose != 0 )
             mbedtls_printf( "  CCM-AES #%u: ", (unsigned int) i + 1 );
 
+        memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
+        memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
+        memcpy( plaintext, msg, msg_len[i] );
+
         ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
-                                   iv, iv_len[i], ad, add_len[i],
-                                   msg, out,
-                                   out + msg_len[i], tag_len[i] );
+                                           iv, iv_len[i], ad, add_len[i],
+                                           plaintext, ciphertext,
+                                           ciphertext + msg_len[i], tag_len[i] );
 
         if( ret != 0 ||
-            memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+            memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
         {
             if( verbose != 0 )
                 mbedtls_printf( "failed\n" );
 
             return( 1 );
         }
+        memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
 
         ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
-                                iv, iv_len[i], ad, add_len[i],
-                                res[i], out,
-                                res[i] + msg_len[i], tag_len[i] );
+                                        iv, iv_len[i], ad, add_len[i],
+                                        ciphertext, plaintext,
+                                        ciphertext + msg_len[i], tag_len[i] );
 
         if( ret != 0 ||
-            memcmp( out, msg, msg_len[i] ) != 0 )
+            memcmp( plaintext, msg, msg_len[i] ) != 0 )
         {
             if( verbose != 0 )
                 mbedtls_printf( "failed\n" );
diff --git a/library/ecp.c b/library/ecp.c
index 41db3fb..68c6f49 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -1446,7 +1446,12 @@
 
 cleanup:
 
-    if( T != NULL && ! p_eq_g )
+    /* 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 )
     {
         for( i = 0; i < pre_len; i++ )
             mbedtls_ecp_point_free( &T[i] );
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index 59cdc7a..745474e 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -2320,7 +2320,8 @@
 
 #endif /* MBEDTLS_PK_C */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
 {
     switch( info->key_exchange )
@@ -2330,13 +2331,14 @@
         case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
         case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
             return( 1 );
 
         default:
             return( 0 );
     }
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
 
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
 int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index ba59c48..4b17dea 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -766,6 +766,10 @@
     unsigned char offer_compress;
     const int *ciphersuites;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    int uses_ec = 0;
+#endif
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
 
@@ -917,6 +921,11 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
                                     ciphersuites[i] ) );
 
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+        uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
+#endif
+
         n++;
         *p++ = (unsigned char)( ciphersuites[i] >> 8 );
         *p++ = (unsigned char)( ciphersuites[i]      );
@@ -1010,11 +1019,14 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
+    if( uses_ec )
+    {
+        ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
+        ext_len += olen;
 
-    ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
+        ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+        ext_len += olen;
+    }
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1076,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_DEBUG_MSG( 2, ( "<= write client hello" ) );
 
     return( 0 );
@@ -3063,9 +3084,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 );
     }
 
@@ -3248,9 +3269,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 );
     }
 
@@ -3390,7 +3411,7 @@
     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
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 52087ae..eda50bb 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -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_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
 
     return( 0 );
@@ -2589,8 +2598,12 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
+    if ( mbedtls_ssl_ciphersuite_uses_ec(
+         mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
+    {
+        ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+        ext_len += olen;
+    }
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -2620,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" ) );
 
@@ -2815,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" ) );
 
@@ -3332,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 );
     }
 
@@ -3359,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_DEBUG_MSG( 2, ( "<= write server hello done" ) );
 
     return( 0 );
@@ -4223,9 +4245,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 );
     }
 
@@ -4254,7 +4276,7 @@
     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
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5905a6d..ea46d85 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2822,20 +2822,52 @@
 
 /*
  * 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" ) );
+    const int ret_payload = mbedtls_ssl_get_max_out_record_payload( ssl );
+    const size_t max_record_payload = (size_t) ret_payload;
+    /* DTLS handshake headers are 12 bytes */
+    const size_t max_hs_fragment_len = max_record_payload - 12;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
+
+    if( ret_payload < 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload",
+                                  ret_payload );
+        return( ret_payload );
+    }
 
     if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise fligh transmission" ) );
+
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "max handshake fragment length: %u",
+                                    max_hs_fragment_len ) );
 
         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;
@@ -2844,8 +2876,7 @@
     while( ssl->handshake->cur_msg != NULL )
     {
         int ret;
-        mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg;
-
+        const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
         /* 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 */
@@ -2855,14 +2886,65 @@
             ssl_swap_epochs( ssl );
         }
 
-        memcpy( ssl->out_msg, cur->p, cur->len );
-        ssl->out_msglen = cur->len;
-        ssl->out_msgtype = cur->type;
+        /* CCS is copied as is, while HS messages may need fragmentation */
+        if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+        {
+            memcpy( ssl->out_msg, cur->p, cur->len );
+            ssl->out_msglen = cur->len;
+            ssl->out_msgtype = cur->type;
 
-        ssl->handshake->cur_msg = cur->next;
+            /* 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;
+            const size_t frag_len = rem_len > max_hs_fragment_len
+                                  ? max_hs_fragment_len : rem_len;
 
-        MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 );
+            /* 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] = ( ( frag_len >> 16 ) & 0xff );
+            ssl->out_msg[10] = ( ( frag_len >>  8 ) & 0xff );
+            ssl->out_msg[11] = ( ( frag_len       ) & 0xff );
+
+            MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+            /* Copy the handshame message content and set records fields */
+            memcpy( ssl->out_msg + 12, p, frag_len );
+            ssl->out_msglen = frag_len + 12;
+            ssl->out_msgtype = cur->type;
+
+            /* Update position inside current message */
+            ssl->handshake->cur_msg_p += 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 ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
@@ -2870,6 +2952,7 @@
         }
     }
 
+    /* Update state and set timer */
     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
     else
@@ -2878,7 +2961,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 );
 }
@@ -2927,43 +3010,75 @@
 #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
+ *
+ * Ouputs, 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 )
+    {
+        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
+
+    /*
+     * 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 +3095,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 +3116,22 @@
                 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 hanshake 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 ) )
+        hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
     {
         if( ( ret = ssl_flight_append( ssl ) ) != 0 )
         {
@@ -3026,7 +3139,39 @@
             return( ret );
         }
     }
+    else
 #endif
+    {
+        if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 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 )
+{
+    int ret, done = 0;
+    size_t len = ssl->out_msglen;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->transform_out != NULL &&
@@ -4542,9 +4687,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 );
     }
 
@@ -4955,9 +5100,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 );
     }
 
@@ -5583,12 +5728,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 );
@@ -5973,6 +6127,9 @@
     ssl->transform_in = NULL;
     ssl->transform_out = NULL;
 
+    ssl->session_in = NULL;
+    ssl->session_out = NULL;
+
     memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
     if( partial == 0 )
         memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
@@ -6597,6 +6754,13 @@
 }
 #endif
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+void mbedtls_ssl_conf_mtu( mbedtls_ssl_config *conf, uint16_t mtu )
+{
+    conf->mtu = mtu;
+}
+#endif
+
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code )
 {
@@ -6843,14 +7007,15 @@
     const mbedtls_ssl_transform *transform = ssl->transform_out;
     unsigned block_size;
 
+    if( transform == NULL )
+        return( (int) mbedtls_ssl_hdr_len( ssl ) );
+
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 #endif
 
-    if( transform == NULL )
-        return( (int) mbedtls_ssl_hdr_len( ssl ) );
-
     switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
     {
         case MBEDTLS_MODE_GCM:
@@ -6902,19 +7067,59 @@
      */
     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 */
 
+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)
+    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->conf->mtu != 0 )
+    {
+        const size_t mtu = ssl->conf->mtu;
+        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
+
+    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 )
 {
@@ -7002,9 +7207,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 );
     }
 
@@ -7169,7 +7374,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 );
         }
     }
@@ -7466,12 +7671,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)
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index a1c7d04..0cf288f 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -4607,6 +4607,56 @@
             -s "Async decrypt callback: using key slot " \
             -s "Async resume (slot [0-9]): decrypt done, status=0"
 
+# Tests for ECC extensions (rfc 4492)
+
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+run_test    "Force a non ECC ciphersuite in the client side" \
+            "$P_SRV debug_level=3" \
+            "$P_CLI debug_level=3 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA256" \
+            0 \
+            -C "client hello, adding supported_elliptic_curves extension" \
+            -C "client hello, adding supported_point_formats extension" \
+            -S "found supported elliptic curves extension" \
+            -S "found supported point formats extension"
+
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+run_test    "Force a non ECC ciphersuite in the server side" \
+            "$P_SRV debug_level=3 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA256" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -C "found supported_point_formats extension" \
+            -S "server hello, supported_point_formats extension"
+
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+run_test    "Force an ECC ciphersuite in the client side" \
+            "$P_SRV debug_level=3" \
+            "$P_CLI debug_level=3 force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256" \
+            0 \
+            -c "client hello, adding supported_elliptic_curves extension" \
+            -c "client hello, adding supported_point_formats extension" \
+            -s "found supported elliptic curves extension" \
+            -s "found supported point formats extension"
+
+requires_config_enabled MBEDTLS_AES_C
+requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_config_enabled MBEDTLS_SHA256_C
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+run_test    "Force an ECC ciphersuite in the server side" \
+            "$P_SRV debug_level=3 force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -c "found supported_point_formats extension" \
+            -s "server hello, supported_point_formats extension"
+
 # Tests for DTLS HelloVerifyRequest
 
 run_test    "DTLS cookie: enabled" \
@@ -4827,6 +4877,108 @@
             -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 \
+             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 \
+             max_frag_len=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
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: server only" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             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 \
+             max_frag_len=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
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: server only (more)" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             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 \
+             max_frag_len=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
+requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+run_test    "DTLS fragmenting: client-initiated, server only" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=none \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             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 \
+             max_frag_len=512" \
+            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" \
+            "$P_SRV dtls=1 debug_level=2 auth_mode=required \
+             crt_file=data_files/server7_int-ca.crt \
+             key_file=data_files/server7.key \
+             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 \
+             max_frag_len=512" \
+            0 \
+            -s "found fragmented DTLS handshake message" \
+            -c "found fragmented DTLS handshake message" \
+            -C "error"
+
 # Tests for specific things with "unreliable" UDP connection
 
 not_with_valgrind # spurious resend due to timeout