Introduce buffering structure for handshake messages

This commit introduces, but does not yet put to use, a sub-structure
of mbedtls_ssl_handshake_params::buffering that will be used for the
buffering and/or reassembly of handshake messages with handshake
sequence numbers that are greater or equal to the next expected
sequence number.
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5e57342..7e01aa3 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -167,6 +167,8 @@
     return( (int) remaining );
 }
 
+static void ssl_buffering_free( mbedtls_ssl_context *ssl );
+
 /*
  * Double the retransmit timeout value, within the allowed range,
  * returning -1 if the maximum value has already been reached.
@@ -3072,6 +3074,9 @@
     /* We don't want to remember CCS's across flight boundaries. */
     ssl->handshake->buffering.seen_ccs = 0;
 
+    /* Clear future message buffering structure. */
+    ssl_buffering_free( ssl );
+
     /* Cancel timer */
     ssl_set_timer( ssl, 0 );
 
@@ -3747,9 +3752,9 @@
 
 void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
 {
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
-        ssl->handshake != NULL )
+    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
     {
         ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
     }
@@ -3759,7 +3764,8 @@
     if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake != NULL )
     {
-        ssl->handshake->in_msg_seq++;
+        unsigned offset;
+        mbedtls_ssl_hs_buffer *hs_buf;
 
         /* Clear up handshake reassembly structure, if any. */
         if( ssl->handshake->hs_msg != NULL )
@@ -3767,6 +3773,28 @@
             mbedtls_free( ssl->handshake->hs_msg );
             ssl->handshake->hs_msg = NULL;
         }
+
+        /* Increment handshake sequence number */
+        hs->in_msg_seq++;
+
+        /*
+         * Clear up handshake buffering and reassembly structure.
+         */
+
+        /* Free first entry */
+        hs_buf = &hs->buffering.hs[0];
+        if( hs_buf->is_valid )
+            mbedtls_free( hs_buf->data );
+
+        /* Shift all other entries */
+        for( offset = 0; offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
+             offset++, hs_buf++ )
+        {
+            *hs_buf = *(hs_buf + 1);
+        }
+
+        /* Create a fresh last entry */
+        memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
     }
 #endif
 }
@@ -8286,6 +8314,29 @@
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_buffering_free( mbedtls_ssl_context *ssl )
+{
+    unsigned offset;
+    mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+    if( hs == NULL )
+        return;
+
+    for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+    {
+        mbedtls_ssl_hs_buffer *hs_buf = &hs->buffering.hs[offset];
+        if( hs_buf->is_valid == 1 )
+        {
+            mbedtls_free( hs_buf->data );
+            memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+        }
+    }
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
 void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -8367,6 +8418,7 @@
     mbedtls_free( handshake->verify_cookie );
     mbedtls_free( handshake->hs_msg );
     ssl_flight_free( handshake->flight );
+    ssl_buffering_free( ssl );
 #endif
 
     mbedtls_platform_zeroize( handshake,