Squashed commit upgrading to mbedtls-2.27.0

Squash merging branch import/mbedtls-2.27.0

 335b95f50f90 ("core: libmbedtls: add ctr_drbg.c to core sources")
 9ad9df8b36e4 ("core: libtomcrypt: libmbedtls: mbedtls_mpi_montred() now returns void")
 ade0994c57b3 ("libmbedtls: add SM2 curve")
 3041cf9726e2 ("libmbedtls: mbedtls_mpi_exp_mod(): optimize mempool usage")
 a2e7a4cd262d ("libmbedtls: mbedtls_mpi_exp_mod(): reduce stack usage")
 87efbd27f8e0 ("libmbedtls: mbedtls_mpi_exp_mod() initialize W")
 e7c59b9b1d5f ("libmbedtls: fix no CRT issue")
 d76bd278d9e2 ("libmbedtls: add interfaces in mbedtls for context memory operation")
 e5b6c167f809 ("libmedtls: mpi_miller_rabin: increase count limit")
 b81d896a903d ("libmbedtls: add mbedtls_mpi_init_mempool()")
 3fbd8660c09d ("libmbedtls: make mbedtls_mpi_mont*() available")
 2cc759c67e37 ("mbedtls: configure mbedtls to reach for config")
 48bf81758c6e ("mbedtls: remove default include/mbedtls/config.h")
 3602df84d7b3 ("Import mbedtls-2.27.0")

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cli.c b/lib/libmbedtls/mbedtls/library/ssl_cli.c
index 47b6d0c..f49178c 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cli.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cli.c
@@ -1,8 +1,8 @@
-// SPDX-License-Identifier: Apache-2.0
 /*
  *  SSLv3/TLSv1 client-side functions
  *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright The Mbed TLS Contributors
+ *  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.
@@ -15,15 +15,9 @@
  *  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(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "common.h"
 
 #if defined(MBEDTLS_SSL_CLI_C)
 
@@ -69,7 +63,7 @@
         return( 1 );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
         return( 1 );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -95,29 +89,26 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
-                                    unsigned char *buf,
-                                    size_t *olen )
+static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
+                                   unsigned char *buf,
+                                   const unsigned char *end,
+                                   size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t hostname_len;
 
     *olen = 0;
 
     if( ssl->hostname == NULL )
-        return;
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
-                   ssl->hostname ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding server name extension: %s",
+          ssl->hostname ) );
 
     hostname_len = strlen( ssl->hostname );
 
-    if( end < p || (size_t)( end - p ) < hostname_len + 9 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 );
 
     /*
      * Sect. 3, RFC 6066 (TLS Extensions Definitions)
@@ -161,16 +152,18 @@
     memcpy( p, ssl->hostname, hostname_len );
 
     *olen = hostname_len + 9;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         size_t *olen )
+static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
+                                        unsigned char *buf,
+                                        const unsigned char *end,
+                                        size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -178,21 +171,20 @@
      * initial ClientHello, in which case also adding the renegotiation
      * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */
     if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-        return;
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding renegotiation extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len );
 
     /*
      * Secure renegotiation
      */
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 )
+                            & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      )
+                            & 0xFF );
 
     *p++ = 0x00;
     *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
@@ -201,6 +193,8 @@
     memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
 
     *olen = 5 + ssl->verify_data_len;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
@@ -209,14 +203,15 @@
  */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
-                                                unsigned char *buf,
-                                                size_t *olen )
+static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
+                                               unsigned char *buf,
+                                               const unsigned char *end,
+                                               size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t sig_alg_len = 0;
     const int *md;
+
 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
     unsigned char *sig_alg_list = buf + 6;
 #endif
@@ -224,9 +219,13 @@
     *olen = 0;
 
     if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-        return;
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding signature_algorithms extension" ) );
+
+    if( ssl->conf->sig_hashes == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
 
     for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
     {
@@ -236,13 +235,19 @@
 #if defined(MBEDTLS_RSA_C)
         sig_alg_len += 2;
 #endif
+        if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "length in bytes of sig-hash-alg extension too big" ) );
+            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+        }
     }
 
-    if( end < p || (size_t)( end - p ) < sig_alg_len + 6 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    /* Empty signature algorithms list, this is a configuration error. */
+    if( sig_alg_len == 0 )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 );
 
     /*
      * Prepare signature_algorithms extension (TLS 1.2)
@@ -288,75 +293,75 @@
     *p++ = (unsigned char)( ( sig_alg_len      ) & 0xFF );
 
     *olen = 6 + sig_alg_len;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
           MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
-                                                     unsigned char *buf,
-                                                     size_t *olen )
+static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
+                                                    unsigned char *buf,
+                                                    const unsigned char *end,
+                                                    size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     unsigned char *elliptic_curve_list = p + 6;
     size_t elliptic_curve_len = 0;
     const mbedtls_ecp_curve_info *info;
-#if defined(MBEDTLS_ECP_C)
     const mbedtls_ecp_group_id *grp_id;
-#else
-    ((void) ssl);
-#endif
 
     *olen = 0;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding supported_elliptic_curves extension" ) );
 
-#if defined(MBEDTLS_ECP_C)
-    for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
-#else
-    for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
-#endif
+    if( ssl->conf->curve_list == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    for( grp_id = ssl->conf->curve_list;
+         *grp_id != MBEDTLS_ECP_DP_NONE;
+         grp_id++ )
     {
-#if defined(MBEDTLS_ECP_C)
         info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
-#endif
         if( info == NULL )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) );
-            return;
+            MBEDTLS_SSL_DEBUG_MSG( 1,
+                ( "invalid curve in ssl configuration" ) );
+            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
         }
-
         elliptic_curve_len += 2;
+
+        if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "malformed supported_elliptic_curves extension in config" ) );
+            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+        }
     }
 
-    if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    /* Empty elliptic curve list, this is a configuration error. */
+    if( elliptic_curve_len == 0 )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len );
 
     elliptic_curve_len = 0;
 
-#if defined(MBEDTLS_ECP_C)
-    for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
-#else
-    for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
-#endif
+    for( grp_id = ssl->conf->curve_list;
+         *grp_id != MBEDTLS_ECP_DP_NONE;
+         grp_id++ )
     {
-#if defined(MBEDTLS_ECP_C)
         info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
-#endif
         elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
         elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
     }
 
-    if( elliptic_curve_len == 0 )
-        return;
-
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES      ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 )
+                            & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES      )
+                            & 0xFF );
 
     *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 )      ) & 0xFF );
@@ -365,27 +370,28 @@
     *p++ = (unsigned char)( ( ( elliptic_curve_len     )      ) & 0xFF );
 
     *olen = 6 + elliptic_curve_len;
+
+    return( 0 );
 }
 
-static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
-                                                   unsigned char *buf,
-                                                   size_t *olen )
+static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
+                                                  unsigned char *buf,
+                                                  const unsigned char *end,
+                                                  size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+    (void) ssl; /* ssl used for debugging only */
 
     *olen = 0;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding supported_point_formats extension" ) );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
 
-    if( end < p || (size_t)( end - p ) < 6 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
-
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 )
+                            & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      )
+                            & 0xFF );
 
     *p++ = 0x00;
     *p++ = 2;
@@ -394,33 +400,32 @@
     *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
 
     *olen = 6;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
-                                        unsigned char *buf,
-                                        size_t *olen )
+static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
+                                       unsigned char *buf,
+                                       const unsigned char *end,
+                                       size_t *olen )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t kkpp_len;
 
     *olen = 0;
 
     /* Skip costly extension if we can't use EC J-PAKE anyway */
     if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
-        return;
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding ecjpake_kkpp extension" ) );
 
-    if( end - p < 4 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP      ) & 0xFF );
@@ -436,19 +441,20 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) );
 
         ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
-                                        p + 2, end - p - 2, &kkpp_len,
-                                        ssl->conf->f_rng, ssl->conf->p_rng );
+                                               p + 2, end - p - 2, &kkpp_len,
+                                               ssl->conf->f_rng, ssl->conf->p_rng );
         if( ret != 0 )
         {
-            MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret );
-            return;
+            MBEDTLS_SSL_DEBUG_RET( 1 ,
+                "mbedtls_ecjpake_write_round_one", ret );
+            return( ret );
         }
 
         ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len );
         if( ssl->handshake->ecjpake_cache == NULL )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) );
-            return;
+            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
         }
 
         memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len );
@@ -459,12 +465,7 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) );
 
         kkpp_len = ssl->handshake->ecjpake_cache_len;
-
-        if( (size_t)( end - p - 2 ) < kkpp_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-            return;
-        }
+        MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len );
 
         memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len );
     }
@@ -473,17 +474,19 @@
     *p++ = (unsigned char)( ( kkpp_len      ) & 0xFF );
 
     *olen = kkpp_len + 4;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-static void ssl_write_cid_ext( mbedtls_ssl_context *ssl,
-                               unsigned char *buf,
-                               size_t *olen )
+static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
+                              unsigned char *buf,
+                              const unsigned char *end,
+                              size_t *olen )
 {
     unsigned char *p = buf;
     size_t ext_len;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     /*
      * Quoting draft-ietf-tls-dtls-connection-id-05
@@ -498,17 +501,13 @@
     if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
         ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
     {
-        return;
+        return( 0 );
     }
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) );
 
     /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
      * which is at most 255, so the increment cannot overflow. */
-    if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) );
 
     /* Add extension ID + size */
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
@@ -521,33 +520,33 @@
     memcpy( p, ssl->own_cid, ssl->own_cid_len );
 
     *olen = ssl->own_cid_len + 5;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
-                                               unsigned char *buf,
-                                               size_t *olen )
+static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              const unsigned char *end,
+                                              size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
-    if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) {
-        return;
-    }
+    if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE )
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding max_fragment_length extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 5 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 )
+                            & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      )
+                            & 0xFF );
 
     *p++ = 0x00;
     *p++ = 1;
@@ -555,30 +554,28 @@
     *p++ = ssl->conf->mfl_code;
 
     *olen = 5;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
-                                          unsigned char *buf, size_t *olen )
+static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
+                                         unsigned char *buf,
+                                         const unsigned char *end,
+                                         size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
     if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
-    {
-        return;
-    }
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding truncated_hmac extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 4 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
@@ -587,32 +584,29 @@
     *p++ = 0x00;
 
     *olen = 4;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
-                                       unsigned char *buf, size_t *olen )
+static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
+                                           unsigned char *buf,
+                                           const unsigned char *end,
+                                           size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
     if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
         ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        return;
-    }
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
-                        "extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding encrypt_then_mac extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 4 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
@@ -621,65 +615,63 @@
     *p++ = 0x00;
 
     *olen = 4;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
-                                       unsigned char *buf, size_t *olen )
+static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
+                                      unsigned char *buf,
+                                      const unsigned char *end,
+                                      size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
     if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
         ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        return;
-    }
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret "
-                        "extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding extended_master_secret extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 4 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 )
+                            & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      )
+                            & 0xFF );
 
     *p++ = 0x00;
     *p++ = 0x00;
 
     *olen = 4;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
-                                          unsigned char *buf, size_t *olen )
+static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
+                                         unsigned char *buf,
+                                         const unsigned char *end,
+                                         size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t tlen = ssl->session_negotiate->ticket_len;
 
     *olen = 0;
 
     if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED )
-    {
-        return;
-    }
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, adding session ticket extension" ) );
 
-    if( end < p || (size_t)( end - p ) < 4 + tlen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    /* The addition is safe here since the ticket length is 16 bit. */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen );
 
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET      ) & 0xFF );
@@ -690,44 +682,40 @@
     *olen = 4;
 
     if( ssl->session_negotiate->ticket == NULL || tlen == 0 )
-    {
-        return;
-    }
+        return( 0 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) );
 
     memcpy( p, ssl->session_negotiate->ticket, tlen );
 
     *olen += tlen;
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
 #if defined(MBEDTLS_SSL_ALPN)
-static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
-                                unsigned char *buf, size_t *olen )
+static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
+                               unsigned char *buf,
+                               const unsigned char *end,
+                               size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t alpnlen = 0;
     const char **cur;
 
     *olen = 0;
 
     if( ssl->conf->alpn_list == NULL )
-    {
-        return;
-    }
+        return( 0 );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
 
     for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
-        alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1;
+        alpnlen += strlen( *cur ) + 1;
 
-    if( end < p || (size_t)( end - p ) < 6 + alpnlen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen );
 
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN      ) & 0xFF );
@@ -745,7 +733,11 @@
 
     for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
     {
-        *p = (unsigned char)( strlen( *cur ) & 0xFF );
+        /*
+         * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of
+         * protocol names is less than 255.
+         */
+        *p = (unsigned char)strlen( *cur );
         memcpy( p + 1, *cur, *p );
         p += 1 + *p;
     }
@@ -759,9 +751,131 @@
     /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
     buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
     buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                   unsigned char *buf,
+                                   const unsigned char *end,
+                                   size_t *olen )
+{
+    unsigned char *p = buf;
+    size_t protection_profiles_index = 0, ext_len = 0;
+    uint16_t mki_len = 0, profile_value = 0;
+
+    *olen = 0;
+
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
+        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
+    {
+        return( 0 );
+    }
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     */
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
+    {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+    /* Extension length = 2 bytes for profiles length,
+     *                    ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ),
+     *                    1 byte for srtp_mki vector length and the mki_len value
+     */
+    ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) );
+
+    /* Check there is room in the buffer for the extension + 4 bytes
+     * - the extension tag (2 bytes)
+     * - the extension length (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 );
+
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP      ) & 0xFF );
+
+
+    *p++ = (unsigned char)( ( ( ext_len & 0xFF00 ) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ext_len & 0xFF );
+
+    /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */
+    /* micro-optimization:
+     * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH
+     * which is lower than 127, so the upper byte of the length is always 0
+     * For the documentation, the more generic code is left in comments
+     * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
+     *                        >> 8 ) & 0xFF );
+     */
+    *p++ = 0;
+    *p++ = (unsigned char)( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
+                            & 0xFF );
+
+    for( protection_profiles_index=0;
+         protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;
+         protection_profiles_index++ )
+    {
+        profile_value = mbedtls_ssl_check_srtp_profile_value
+                ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] );
+        if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x",
+                                        profile_value ) );
+            *p++ = ( ( profile_value >> 8 ) & 0xFF );
+            *p++ = ( profile_value & 0xFF );
+        }
+        else
+        {
+            /*
+             * Note: we shall never arrive here as protection profiles
+             * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function
+             */
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                    ( "client hello, "
+                      "illegal DTLS-SRTP protection profile %d",
+                      ssl->conf->dtls_srtp_profile_list[protection_profiles_index]
+                    ) );
+            return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+        }
+    }
+
+    *p++ = mki_len & 0xFF;
+
+    if( mki_len != 0 )
+    {
+        memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len );
+        /*
+         * Increment p to point to the current position.
+         */
+        p += mki_len;
+        MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki",  ssl->dtls_srtp_info.mki_value,
+                               ssl->dtls_srtp_info.mki_len );
+    }
+
+    /*
+     * total extension length: extension type (2 bytes)
+     *                         + extension length (2 bytes)
+     *                         + protection profile length (2 bytes)
+     *                         + 2 * number of protection profiles
+     *                         + srtp_mki vector length(1 byte)
+     *                         + mki value
+     */
+    *olen = p - buf;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * Generate random bytes for ClientHello
  */
@@ -791,7 +905,8 @@
     *p++ = (unsigned char)( t >>  8 );
     *p++ = (unsigned char)( t       );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+                                (long long) t ) );
 #else
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
         return( ret );
@@ -815,9 +930,10 @@
  *
  * \return          0 if valid, else 1
  */
-static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info,
-                                     const mbedtls_ssl_context * ssl,
-                                     int min_minor_ver, int max_minor_ver )
+static int ssl_validate_ciphersuite(
+    const mbedtls_ssl_ciphersuite_t * suite_info,
+    const mbedtls_ssl_context * ssl,
+    int min_minor_ver, int max_minor_ver )
 {
     (void) ssl;
     if( suite_info == NULL )
@@ -861,8 +977,11 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n, olen, ext_len = 0;
+
     unsigned char *buf;
     unsigned char *p, *q;
+    const unsigned char *end;
+
     unsigned char offer_compress;
     const int *ciphersuites;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
@@ -889,23 +1008,41 @@
 
     if( ssl->conf->max_major_ver == 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, "
-                            "consider using mbedtls_ssl_config_defaults()" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
+    buf = ssl->out_msg;
+    end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
     /*
-     *     0  .   0   handshake type
-     *     1  .   3   handshake length
+     * Check if there's enough space for the first part of the ClientHello
+     * consisting of the 38 bytes described below, the session identifier (at
+     * most 32 bytes) and its length (1 byte).
+     *
+     * Use static upper bounds instead of the actual values
+     * to allow the compiler to optimize this away.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );
+
+    /*
+     * The 38 first bytes of the ClientHello:
+     *     0  .   0   handshake type (written later)
+     *     1  .   3   handshake length (written later)
      *     4  .   5   highest version supported
      *     6  .   9   current UNIX time
      *    10  .  37   random bytes
+     *
+     * The current UNIX time (4 bytes) and following 28 random bytes are written
+     * by ssl_generate_random() into ssl->handshake->randbytes buffer and then
+     * copied from there into the output buffer.
      */
-    buf = ssl->out_msg;
-    p = buf + 4;
 
-    mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver,
-                       ssl->conf->transport, p );
+    p = buf + 4;
+    mbedtls_ssl_write_version( ssl->conf->max_major_ver,
+                               ssl->conf->max_minor_ver,
+                               ssl->conf->transport, p );
     p += 2;
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
@@ -925,7 +1062,7 @@
      *    38  .  38   session id length
      *    39  . 39+n  session id
      *   39+n . 39+n  DTLS only: cookie length (1 byte)
-     *   40+n .  ..   DTSL only: cookie
+     *   40+n .  ..   DTLS only: cookie
      *   ..   . ..    ciphersuitelist length (2 bytes)
      *   ..   . ..    ciphersuitelist
      *   ..   . ..    compression methods length (1 byte)
@@ -956,7 +1093,8 @@
         if( ssl->session_negotiate->ticket != NULL &&
                 ssl->session_negotiate->ticket_len != 0 )
         {
-            ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 );
+            ret = ssl->conf->f_rng( ssl->conf->p_rng,
+                                    ssl->session_negotiate->id, 32 );
 
             if( ret != 0 )
                 return( ret );
@@ -966,20 +1104,41 @@
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+    /*
+     * The first check of the output buffer size above (
+     * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );)
+     * has checked that there is enough space in the output buffer for the
+     * session identifier length byte and the session identifier (n <= 32).
+     */
     *p++ = (unsigned char) n;
 
     for( i = 0; i < n; i++ )
         *p++ = ssl->session_negotiate->id[i];
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
 
     /*
+     *   With 'n' being the length of the session identifier
+     *
+     *   39+n . 39+n  DTLS only: cookie length (1 byte)
+     *   40+n .  ..   DTLS only: cookie
+     *   ..   . ..    ciphersuitelist length (2 bytes)
+     *   ..   . ..    ciphersuitelist
+     *   ..   . ..    compression methods length (1 byte)
+     *   ..   . ..    compression methods
+     *   ..   . ..    extensions length (2 bytes)
+     *   ..   . ..    extensions
+     */
+
+    /*
      * DTLS cookie
      */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
     {
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 );
+
         if( ssl->handshake->verify_cookie == NULL )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) );
@@ -992,6 +1151,9 @@
                               ssl->handshake->verify_cookie_len );
 
             *p++ = ssl->handshake->verify_cookie_len;
+
+            MBEDTLS_SSL_CHK_BUF_PTR( p, end,
+                                     ssl->handshake->verify_cookie_len );
             memcpy( p, ssl->handshake->verify_cookie,
                        ssl->handshake->verify_cookie_len );
             p += ssl->handshake->verify_cookie_len;
@@ -1007,6 +1169,8 @@
     /* Skip writing ciphersuite length for now */
     n = 0;
     q = p;
+
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
     p += 2;
 
     for( i = 0; ciphersuites[i] != 0; i++ )
@@ -1018,20 +1182,23 @@
                                       ssl->conf->max_minor_ver ) != 0 )
             continue;
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
-                                    ciphersuites[i] ) );
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)",
+                                    (unsigned int)ciphersuites[i], ciphersuite_info->name ) );
 
 #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
 
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
+
         n++;
         *p++ = (unsigned char)( ciphersuites[i] >> 8 );
         *p++ = (unsigned char)( ciphersuites[i]      );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) );
 
     /*
      * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
@@ -1041,6 +1208,7 @@
 #endif
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
         *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
         *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO      );
         n++;
@@ -1051,6 +1219,8 @@
     if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
+
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
         *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 );
         *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE      );
         n++;
@@ -1081,8 +1251,10 @@
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
-                            MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) );
+                                    MBEDTLS_SSL_COMPRESS_DEFLATE,
+                                    MBEDTLS_SSL_COMPRESS_NULL ) );
 
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 );
         *p++ = 2;
         *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE;
         *p++ = MBEDTLS_SSL_COMPRESS_NULL;
@@ -1093,27 +1265,45 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d",
                             MBEDTLS_SSL_COMPRESS_NULL ) );
 
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
         *p++ = 1;
         *p++ = MBEDTLS_SSL_COMPRESS_NULL;
     }
 
-    // First write extensions, then the total length
-    //
+    /* First write extensions, then the total length */
+
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
+
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len,
+                                        end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
     /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added
      * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len,
+                                             end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len,
+                                                    end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
@@ -1121,62 +1311,123 @@
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     if( uses_ec )
     {
-        ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
+        if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len,
+                                                             end, &olen ) ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret );
+            return( ret );
+        }
         ext_len += olen;
 
-        ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+        if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len,
+                                                           end, &olen ) ) != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret );
+            return( ret );
+        }
         ext_len += olen;
     }
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len,
+                                            end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_cid_ext( ssl, p + 2 + ext_len, end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_cid_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len,
+                                                   end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len,
+                                              end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len,
+                                                end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len,
+                                           end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_ALPN)
-    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len,
+                                    end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret );
+        return( ret );
+    }
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len,
+                                        end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
+    if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len,
+                                              end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret );
+        return( ret );
+    }
     ext_len += olen;
 #endif
 
     /* olen unused if all extensions are disabled */
     ((void) olen);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
-                   ext_len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
+                                ext_len ) );
 
     if( ext_len > 0 )
     {
+        /* No need to check for space here, because the extension
+         * writing functions already took care of that. */
         *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
         *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
         p += ext_len;
@@ -1229,8 +1480,10 @@
                           ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
     }
@@ -1239,9 +1492,12 @@
     {
         if( len != 1 || buf[0] != 0x00 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_DEBUG_MSG( 1,
+                ( "non-zero length renegotiation info" ) );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
 
@@ -1264,9 +1520,12 @@
         len != 1 ||
         buf[0] != ssl->conf->mfl_code )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "non-matching max fragment length extension" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1282,9 +1541,12 @@
     if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ||
         len != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "non-matching truncated HMAC extension" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1310,7 +1572,7 @@
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+                                     MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1361,9 +1623,12 @@
         ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
         len != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "non-matching encrypt-then-MAC extension" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1384,9 +1649,12 @@
         ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
         len != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "non-matching extended master secret extension" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1406,9 +1674,12 @@
     if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
         len != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "non-matching session ticket extension" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1489,8 +1760,10 @@
                                                 buf, len ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
         return( ret );
     }
 
@@ -1509,8 +1782,10 @@
     if( ssl->conf->alpn_list == NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1566,6 +1841,123 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                   const unsigned char *buf,
+                                   size_t len )
+{
+    mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET;
+    size_t i, mki_len = 0;
+    uint16_t server_protection_profile_value = 0;
+
+    /* If use_srtp is not configured, just ignore the extension */
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
+        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
+        return( 0 );
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     *
+     */
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
+    {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+
+    /*
+     * Length is 5 + optional mki_value : one protection profile length (2 bytes)
+     *                                      + protection profile (2 bytes)
+     *                                      + mki_len(1 byte)
+     *                                      and optional srtp_mki
+     */
+    if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) )
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /*
+     * get the server protection profile
+     */
+
+    /*
+     * protection profile length must be 0x0002 as we must have only
+     * one protection profile in server Hello
+     */
+    if( (  buf[0] != 0 ) || ( buf[1] != 2 ) )
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    server_protection_profile_value = ( buf[2] << 8 ) | buf[3];
+    server_protection = mbedtls_ssl_check_srtp_profile_value(
+                    server_protection_profile_value );
+    if( server_protection != MBEDTLS_TLS_SRTP_UNSET )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                              server_protection ) ) );
+    }
+
+    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
+
+    /*
+     * Check we have the server profile in our list
+     */
+    for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++)
+    {
+        if( server_protection == ssl->conf->dtls_srtp_profile_list[i] )
+        {
+            ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                              server_protection ) ) );
+            break;
+        }
+    }
+
+    /* If no match was found : server problem, it shall never answer with incompatible profile */
+    if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    /* If server does not use mki in its reply, make sure the client won't keep
+     * one as negotiated */
+    if( len == 5 )
+    {
+        ssl->dtls_srtp_info.mki_len = 0;
+    }
+
+    /*
+     * RFC5764:
+     *  If the client detects a nonzero-length MKI in the server's response
+     *  that is different than the one the client offered, then the client
+     *  MUST abort the handshake and SHOULD send an invalid_parameter alert.
+     */
+    if( len > 5  && ( buf[4] != mki_len ||
+        ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+#if defined (MBEDTLS_DEBUG_C)
+    if( len > 5 )
+    {
+        MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value,
+                                                  ssl->dtls_srtp_info.mki_len );
+    }
+#endif
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * Parse HelloVerifyRequest.  Only called after verifying the HS type.
  */
@@ -1690,12 +2082,13 @@
             if( ssl->conf->renego_max_records >= 0 &&
                 ssl->renego_records_seen > ssl->conf->renego_max_records )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
-                                    "but not honored by server" ) );
+                MBEDTLS_SSL_DEBUG_MSG( 1,
+                    ( "renegotiation requested, but not honored by server" ) );
                 return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
             }
 
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 1,
+                ( "non-handshake message during renegotiation" ) );
 
             ssl->keep_current_message = 1;
             return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
@@ -1703,8 +2096,10 @@
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
@@ -1758,11 +2153,13 @@
         ssl->major_ver > ssl->conf->max_major_ver ||
         ssl->minor_ver > ssl->conf->max_minor_ver )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - "
-                            " min: [%d:%d], server: [%d:%d], max: [%d:%d]",
-                            ssl->conf->min_major_ver, ssl->conf->min_minor_ver,
-                            ssl->major_ver, ssl->minor_ver,
-                            ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "server version out of bounds -  min: [%d:%d], server: [%d:%d], max: [%d:%d]",
+              ssl->conf->min_major_ver,
+              ssl->conf->min_minor_ver,
+              ssl->major_ver, ssl->minor_ver,
+              ssl->conf->max_major_ver,
+              ssl->conf->max_minor_ver ) );
 
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                      MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
@@ -1771,10 +2168,10 @@
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu",
-                           ( (uint32_t) buf[2] << 24 ) |
-                           ( (uint32_t) buf[3] << 16 ) |
-                           ( (uint32_t) buf[4] <<  8 ) |
-                           ( (uint32_t) buf[5]       ) ) );
+                                     ( (unsigned long) buf[2] << 24 ) |
+                                     ( (unsigned long) buf[3] << 16 ) |
+                                     ( (unsigned long) buf[4] <<  8 ) |
+                                     ( (unsigned long) buf[5]       ) ) );
 
     memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
 
@@ -1799,8 +2196,10 @@
             ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
     }
@@ -1839,9 +2238,12 @@
     if( comp != MBEDTLS_SSL_COMPRESS_NULL )
 #endif/* MBEDTLS_ZLIB_SUPPORT */
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "server hello, bad compression: %d", comp ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
         return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
     }
 
@@ -1851,7 +2253,8 @@
     ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
     if( ssl->handshake->ciphersuite_info == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "ciphersuite info for %04x not found", (unsigned int)i ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                         MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -1859,7 +2262,7 @@
 
     mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 35, n );
 
     /*
@@ -1891,8 +2294,10 @@
         if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
             return( ret );
         }
     }
@@ -1900,8 +2305,9 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
                    ssl->handshake->resume ? "a" : "no" ) );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
+                                buf[37 + n] ) );
 
     /*
      * Perform cipher suite validation in same way as in ssl_write_client_hello.
@@ -1912,8 +2318,10 @@
         if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
 
@@ -1924,16 +2332,21 @@
         }
     }
 
-    suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
-    if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 )
+    suite_info = mbedtls_ssl_ciphersuite_from_id(
+        ssl->session_negotiate->ciphersuite );
+    if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver,
+                                  ssl->minor_ver ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+        ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
 
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
     if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
@@ -1950,15 +2363,18 @@
       )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
     ssl->session_negotiate->compression = comp;
 
     ext = buf + 40 + n;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2,
+        ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) );
 
     while( ext_len )
     {
@@ -1970,8 +2386,9 @@
         if( ext_size + 4 > ext_len )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
         }
 
@@ -1991,7 +2408,8 @@
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
         case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "found max_fragment_length extension" ) );
 
             if( ( ret = ssl_parse_max_fragment_length_ext( ssl,
                             ext + 4, ext_size ) ) != 0 )
@@ -2044,7 +2462,8 @@
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
         case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "found extended_master_secret extension" ) );
 
             if( ( ret = ssl_parse_extended_ms_ext( ssl,
                             ext + 4, ext_size ) ) != 0 )
@@ -2071,7 +2490,8 @@
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
         case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "found supported_point_formats extension" ) );
 
             if( ( ret = ssl_parse_supported_point_formats_ext( ssl,
                             ext + 4, ext_size ) ) != 0 )
@@ -2106,9 +2526,19 @@
             break;
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+        case MBEDTLS_TLS_EXT_USE_SRTP:
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) );
+
+            if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 )
+                return( ret );
+
+            break;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
         default:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
-                           ext_id ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "unknown extension found: %u (ignoring)", ext_id ) );
         }
 
         ext_len -= 4 + ext_size;
@@ -2125,9 +2555,11 @@
      * Renegotiation security checks
      */
     if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        ssl->conf->allow_legacy_renegotiation ==
+        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
     }
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -2135,12 +2567,14 @@
              ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
              renegotiation_info_seen == 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "renegotiation_info extension missing (secure)" ) );
         handshake_failure = 1;
     }
     else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
+             ssl->conf->allow_legacy_renegotiation ==
+             MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
         handshake_failure = 1;
@@ -2149,15 +2583,18 @@
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
              renegotiation_info_seen == 1 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "renegotiation_info extension present (legacy)" ) );
         handshake_failure = 1;
     }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
     if( handshake_failure == 1 )
     {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -2168,10 +2605,12 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
     defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p,
+static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
+                                       unsigned char **p,
                                        unsigned char *end )
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t dhm_actual_bitlen;
 
     /*
      * Ephemeral DH parameters:
@@ -2182,16 +2621,18 @@
      *     opaque dh_Ys<1..2^16-1>;
      * } ServerDHParams;
      */
-    if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 )
+    if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx,
+                                         p, end ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret );
         return( ret );
     }
 
-    if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
+    dhm_actual_bitlen = mbedtls_mpi_bitlen( &ssl->handshake->dhm_ctx.P );
+    if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
-                                    ssl->handshake->dhm_ctx.len * 8,
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u",
+                                    dhm_actual_bitlen,
                                     ssl->conf->dhm_min_bitlen ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
@@ -2340,7 +2781,8 @@
 
     if( ssl_check_server_ecdh_params( ssl ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "bad server key exchange message (ECDHE curve)" ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
@@ -2366,8 +2808,8 @@
      */
     if( end - (*p) < 2 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
-                                    "(psk_identity_hint length)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "bad server key exchange message (psk_identity_hint length)" ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
     len = (*p)[0] << 8 | (*p)[1];
@@ -2375,8 +2817,8 @@
 
     if( end - (*p) < len )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
-                                    "(psk_identity_hint length)" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "bad server key exchange message (psk_identity_hint length)" ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
@@ -2419,8 +2861,9 @@
      *      opaque random[46];
      *  } PreMasterSecret;
      */
-    mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver,
-                       ssl->conf->transport, p );
+    mbedtls_ssl_write_version( ssl->conf->max_major_ver,
+                               ssl->conf->max_minor_ver,
+                               ssl->conf->transport, p );
 
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 )
     {
@@ -2506,20 +2949,22 @@
     /*
      * Get hash algorithm
      */
-    if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE )
+    if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) )
+        == MBEDTLS_MD_NONE )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported "
-                            "HashAlgorithm %d", *(p)[0] ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
     /*
      * Get signature algorithm
      */
-    if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE )
+    if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) )
+        == MBEDTLS_PK_NONE )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported "
-                            "SignatureAlgorithm %d", (*p)[1] ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
@@ -2528,13 +2973,15 @@
      */
     if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered",
-                                    *(p)[0] ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d",
+                                (*p)[1] ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d",
+                                (*p)[0] ) );
     *p += 2;
 
     return( 0 );
@@ -2625,8 +3072,10 @@
         if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
             return( ret );
         }
 
@@ -2656,8 +3105,10 @@
     if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
@@ -2676,10 +3127,12 @@
             goto exit;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must "
-                                    "not be skipped" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "server key exchange message must not be skipped" ) );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
 
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
@@ -2703,8 +3156,10 @@
         if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
     } /* FALLTROUGH */
@@ -2726,8 +3181,10 @@
         if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
     }
@@ -2743,8 +3200,10 @@
         if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
     }
@@ -2762,8 +3221,10 @@
         if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
     }
@@ -2779,8 +3240,10 @@
         if( ret != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
     }
@@ -2813,17 +3276,24 @@
             if( ssl_parse_signature_algorithm( ssl, &p, end,
                                                &md_alg, &pk_alg ) != 0 )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+                MBEDTLS_SSL_DEBUG_MSG( 1,
+                    ( "bad server key exchange message" ) );
+                mbedtls_ssl_send_alert_message(
+                    ssl,
+                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
                 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
             }
 
-            if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
+            if( pk_alg !=
+                mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+                MBEDTLS_SSL_DEBUG_MSG( 1,
+                    ( "bad server key exchange message" ) );
+                mbedtls_ssl_send_alert_message(
+                    ssl,
+                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
                 return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
             }
         }
@@ -2853,8 +3323,10 @@
         if( p > end - 2 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
         sig_len = ( p[0] << 8 ) | p[1];
@@ -2863,8 +3335,10 @@
         if( p != end - sig_len )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
             return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
 
@@ -2924,8 +3398,10 @@
         if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
             return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
         }
 
@@ -2940,8 +3416,10 @@
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
             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_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_ENABLED)
             if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
@@ -3013,8 +3491,10 @@
     if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
@@ -3090,8 +3570,9 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
     {
-        size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] <<  8 )
-                             | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n]       ) );
+        size_t sig_alg_len =
+            ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] <<  8 )
+              | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n]   ) );
 #if defined(MBEDTLS_DEBUG_C)
         unsigned char* sig_alg;
         size_t i;
@@ -3109,11 +3590,14 @@
          *     buf[...hdr_len + 3 + n + sig_alg_len],
          * which is one less than we need the buf to be.
          */
-        if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len )
+        if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl )
+                                + 3 + n + sig_alg_len )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
             return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
         }
 
@@ -3121,8 +3605,9 @@
         sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
         for( i = 0; i < sig_alg_len; i += 2 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d"
-                                        ",%d", sig_alg[i], sig_alg[i + 1]  ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                ( "Supported Signature Algorithm found: %d,%d",
+                  sig_alg[i], sig_alg[i + 1]  ) );
         }
 #endif
 
@@ -3213,9 +3698,9 @@
         header_len = 6;
 
         ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
-                           (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
-                           &ssl->out_msg[header_len], content_len,
-                           ssl->conf->f_rng, ssl->conf->p_rng );
+                          (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
+                          &ssl->out_msg[header_len], content_len,
+                          ssl->conf->f_rng, ssl->conf->p_rng );
         if( ret != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
@@ -3226,10 +3711,10 @@
         MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
 
         if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                   ssl->handshake->premaster,
-                                   MBEDTLS_PREMASTER_SIZE,
-                                   &ssl->handshake->pmslen,
-                                   ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+                                  ssl->handshake->premaster,
+                                  MBEDTLS_PREMASTER_SIZE,
+                                  &ssl->handshake->pmslen,
+                                  ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
             return( ret );
@@ -3320,7 +3805,7 @@
         status = psa_destroy_key( handshake->ecdh_psa_privkey );
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        handshake->ecdh_psa_privkey = 0;
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
     }
     else
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
@@ -3379,10 +3864,10 @@
             content_len = ssl->handshake->ecrs_n;
 #endif
         if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
-                                   &ssl->handshake->pmslen,
-                                   ssl->handshake->premaster,
-                                   MBEDTLS_MPI_MAX_SIZE,
-                                   ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+                                  &ssl->handshake->pmslen,
+                                  ssl->handshake->premaster,
+                                  MBEDTLS_MPI_MAX_SIZE,
+                                  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_ENABLED)
@@ -3419,8 +3904,8 @@
 
         if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
-                                        "SSL buffer too short" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 1,
+                ( "psk identity too long or SSL buffer too short" ) );
             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
         }
 
@@ -3471,8 +3956,8 @@
             if( header_len + 2 + content_len >
                 MBEDTLS_SSL_OUT_CONTENT_LEN )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
-                                            " or SSL buffer too short" ) );
+                MBEDTLS_SSL_DEBUG_MSG( 1,
+                    ( "psk identity or DHM size too long or SSL buffer too short" ) );
                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
             }
 
@@ -3530,7 +4015,8 @@
             ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
             ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 1,
+                ( "skip PMS generation for opaque PSK" ) );
         }
         else
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
@@ -3538,7 +4024,8 @@
         if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
                         ciphersuite_info->key_exchange ) ) != 0 )
         {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
+            MBEDTLS_SSL_DEBUG_RET( 1,
+                "mbedtls_ssl_psk_derive_premaster", ret );
             return( ret );
         }
     }
@@ -3736,8 +4223,9 @@
          * Until we encounter a server that does not, we will take this
          * shortcut.
          *
-         * Reason: Otherwise we should have running hashes for SHA512 and SHA224
-         *         in order to satisfy 'weird' needs from the server side.
+         * Reason: Otherwise we should have running hashes for SHA512 and
+         *         SHA224 in order to satisfy 'weird' needs from the server
+         *         side.
          */
         if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
         {
@@ -3821,8 +4309,10 @@
     if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
 
@@ -3860,7 +4350,7 @@
         return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) );
 
     /* We're not waiting for a NewSessionTicket message any more */
     ssl->handshake->new_session_ticket = 0;