Adapt record encryption/decryption routines to change of record type

This commit modifies the code surrounding the invocations of
ssl_decrypt_buf() and ssl_encrypt_buf() to deal with a change
of record content type during CID-based record encryption/decryption.
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index b7e6cea..6115743 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4136,7 +4136,9 @@
         unsigned i;
         size_t protected_record_size;
 
-        ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+        /* Skip writing the record content type to after the encryption,
+         * as it may change when using the CID extension. */
+
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                            ssl->conf->transport, ssl->out_hdr + 1 );
 
@@ -4177,6 +4179,8 @@
                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
             }
 
+            /* Update the record content type and CID. */
+            ssl->out_msgtype = rec.type;
 #if defined(MBEDTLS_SSL_CID )
             memcpy( ssl->out_cid, rec.cid, rec.cid_len );
 #endif /* MBEDTLS_SSL_CID */
@@ -4204,6 +4208,9 @@
         }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+        /* Now write the potentially updated record content type. */
+        ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
                                     "version = [%d:%d], msglen = %d",
                                     ssl->out_hdr[0], ssl->out_hdr[1],
@@ -5056,6 +5063,20 @@
             return( ret );
         }
 
+        if( ssl->in_msgtype != rec.type )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
+                                        ssl->in_msgtype, rec.type ) );
+        }
+
+        /* The record content type may change during decryption,
+         * so re-read it. */
+        ssl->in_msgtype = rec.type;
+        /* Also update the input buffer, because unfortunately
+         * the server-side ssl_parse_client_hello() reparses the
+         * record header when receiving a ClientHello initiating
+         * a renegotiation. */
+        ssl->in_hdr[0] = rec.type;
         ssl->in_msg    = rec.buf + rec.data_offset;
         ssl->in_msglen = rec.data_len;
         ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
@@ -5064,6 +5085,21 @@
         MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
                        ssl->in_msg, ssl->in_msglen );
 
+#if defined(MBEDTLS_SSL_CID)
+        /* We have already checked the record content type
+         * in ssl_parse_record_header(), failing or silently
+         * dropping the record in the case of an unknown type.
+         *
+         * Since with the use of CIDs, the record content type
+         * might change during decryption, re-check the record
+         * content type, but treat a failure as fatal this time. */
+        if( ssl_check_record_type( ssl->in_msgtype ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+#endif /* MBEDTLS_SSL_CID */
+
         if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );