2525#include "constant_time_internal.h"
2626#include "mbedtls/constant_time.h"
2727
28+ #include <limits.h>
2829#include <string.h>
2930
3031#if defined(MBEDTLS_USE_PSA_CRYPTO )
@@ -3220,13 +3221,17 @@ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
32203221
32213222int mbedtls_ssl_prepare_handshake_record (mbedtls_ssl_context * ssl )
32223223{
3223- if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl )) {
3224+ /* First handshake fragment must at least include the header. */
3225+ if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl ) && ssl -> in_hslen == 0 ) {
32243226 MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
32253227 ssl -> in_msglen ));
32263228 return MBEDTLS_ERR_SSL_INVALID_RECORD ;
32273229 }
32283230
3229- ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
3231+ if (ssl -> in_hslen == 0 ) {
3232+ ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
3233+ ssl -> badmac_seen_or_in_hsfraglen = 0 ;
3234+ }
32303235
32313236 MBEDTLS_SSL_DEBUG_MSG (3 , ("handshake message: msglen ="
32323237 " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
@@ -3292,10 +3297,67 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
32923297 }
32933298 } else
32943299#endif /* MBEDTLS_SSL_PROTO_DTLS */
3295- /* With TLS we don't handle fragmentation (for now) */
3296- if (ssl -> in_msglen < ssl -> in_hslen ) {
3297- MBEDTLS_SSL_DEBUG_MSG (1 , ("TLS handshake fragmentation not supported" ));
3298- return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ;
3300+ if (ssl -> badmac_seen_or_in_hsfraglen <= ssl -> in_hslen ) {
3301+ int ret ;
3302+ const size_t hs_remain = ssl -> in_hslen - ssl -> badmac_seen_or_in_hsfraglen ;
3303+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3304+ ("handshake fragment: %u .. %"
3305+ MBEDTLS_PRINTF_SIZET " of %"
3306+ MBEDTLS_PRINTF_SIZET " msglen %" MBEDTLS_PRINTF_SIZET ,
3307+ ssl -> badmac_seen_or_in_hsfraglen ,
3308+ (size_t ) ssl -> badmac_seen_or_in_hsfraglen +
3309+ (hs_remain <= ssl -> in_msglen ? hs_remain : ssl -> in_msglen ),
3310+ ssl -> in_hslen , ssl -> in_msglen ));
3311+ if (ssl -> in_msglen < hs_remain ) {
3312+ /* ssl->in_msglen is a 25-bit value since it is the sum of the
3313+ * header length plus the payload length, the header length is 4
3314+ * and the payload length was received on the wire encoded as
3315+ * 3 octets. We don't support 16-bit platforms; more specifically,
3316+ * we assume that both unsigned and size_t are at least 32 bits.
3317+ * Therefore there is no possible integer overflow here.
3318+ */
3319+ ssl -> badmac_seen_or_in_hsfraglen += (unsigned ) ssl -> in_msglen ;
3320+ ssl -> in_hdr = ssl -> in_msg + ssl -> in_msglen ;
3321+ ssl -> in_msglen = 0 ;
3322+ mbedtls_ssl_update_in_pointers (ssl );
3323+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3324+ }
3325+ if (ssl -> badmac_seen_or_in_hsfraglen > 0 ) {
3326+ /*
3327+ * At in_first_hdr we have a sequence of records that cover the next handshake
3328+ * record, each with its own record header that we need to remove.
3329+ * Note that the reassembled record size may not equal the size of the message,
3330+ * there may be more messages after it, complete or partial.
3331+ */
3332+ unsigned char * in_first_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
3333+ unsigned char * p = in_first_hdr , * q = NULL ;
3334+ size_t merged_rec_len = 0 ;
3335+ do {
3336+ mbedtls_record rec ;
3337+ ret = ssl_parse_record_header (ssl , p , mbedtls_ssl_in_hdr_len (ssl ), & rec );
3338+ if (ret != 0 ) {
3339+ return ret ;
3340+ }
3341+ merged_rec_len += rec .data_len ;
3342+ p = rec .buf + rec .buf_len ;
3343+ if (q != NULL ) {
3344+ memmove (q , rec .buf + rec .data_offset , rec .data_len );
3345+ q += rec .data_len ;
3346+ } else {
3347+ q = p ;
3348+ }
3349+ } while (merged_rec_len < ssl -> in_hslen );
3350+ ssl -> in_hdr = in_first_hdr ;
3351+ mbedtls_ssl_update_in_pointers (ssl );
3352+ ssl -> in_msglen = merged_rec_len ;
3353+ /* Adjust message length. */
3354+ MBEDTLS_PUT_UINT16_BE (merged_rec_len , ssl -> in_len , 0 );
3355+ ssl -> badmac_seen_or_in_hsfraglen = 0 ;
3356+ MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3357+ ssl -> in_hdr , mbedtls_ssl_in_hdr_len (ssl ) + merged_rec_len );
3358+ }
3359+ } else {
3360+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
32993361 }
33003362
33013363 return 0 ;
@@ -4640,6 +4702,16 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
46404702 return MBEDTLS_ERR_SSL_INTERNAL_ERROR ;
46414703 }
46424704
4705+ if (ssl -> badmac_seen_or_in_hsfraglen != 0 ) {
4706+ /* Not all handshake fragments have arrived, do not consume. */
4707+ MBEDTLS_SSL_DEBUG_MSG (3 ,
4708+ ("waiting for more fragments (%u of %"
4709+ MBEDTLS_PRINTF_SIZET ", %" MBEDTLS_PRINTF_SIZET " left)" ,
4710+ ssl -> badmac_seen_or_in_hsfraglen , ssl -> in_hslen ,
4711+ ssl -> in_hslen - ssl -> badmac_seen_or_in_hsfraglen ));
4712+ return 0 ;
4713+ }
4714+
46434715 /*
46444716 * Get next Handshake message in the current record
46454717 */
@@ -4665,6 +4737,7 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
46654737 ssl -> in_msglen -= ssl -> in_hslen ;
46664738 memmove (ssl -> in_msg , ssl -> in_msg + ssl -> in_hslen ,
46674739 ssl -> in_msglen );
4740+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
46684741
46694742 MBEDTLS_SSL_DEBUG_BUF (4 , "remaining content in record" ,
46704743 ssl -> in_msg , ssl -> in_msglen );
@@ -4967,10 +5040,12 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
49675040 return ret ;
49685041 }
49695042
4970- if (ssl -> conf -> badmac_limit != 0 &&
4971- ++ ssl -> badmac_seen >= ssl -> conf -> badmac_limit ) {
4972- MBEDTLS_SSL_DEBUG_MSG (1 , ("too many records with bad MAC" ));
4973- return MBEDTLS_ERR_SSL_INVALID_MAC ;
5043+ if (ssl -> conf -> badmac_limit != 0 ) {
5044+ ++ ssl -> badmac_seen_or_in_hsfraglen ;
5045+ if (ssl -> badmac_seen_or_in_hsfraglen >= ssl -> conf -> badmac_limit ) {
5046+ MBEDTLS_SSL_DEBUG_MSG (1 , ("too many records with bad MAC" ));
5047+ return MBEDTLS_ERR_SSL_INVALID_MAC ;
5048+ }
49745049 }
49755050
49765051 /* As above, invalid records cause
@@ -5339,7 +5414,7 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
53395414 } else
53405415#endif
53415416 {
5342- ssl -> in_ctr = ssl -> in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5417+ ssl -> in_ctr = ssl -> in_buf ;
53435418 ssl -> in_len = ssl -> in_hdr + 3 ;
53445419#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
53455420 ssl -> in_cid = ssl -> in_len ;
@@ -5355,24 +5430,35 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
53555430 * Setup an SSL context
53565431 */
53575432
5358- void mbedtls_ssl_reset_in_out_pointers (mbedtls_ssl_context * ssl )
5433+ void mbedtls_ssl_reset_in_pointers (mbedtls_ssl_context * ssl )
5434+ {
5435+ #if defined(MBEDTLS_SSL_PROTO_DTLS )
5436+ if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
5437+ ssl -> in_hdr = ssl -> in_buf ;
5438+ } else
5439+ #endif /* MBEDTLS_SSL_PROTO_DTLS */
5440+ {
5441+ ssl -> in_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5442+ }
5443+
5444+ /* Derive other internal pointers. */
5445+ mbedtls_ssl_update_in_pointers (ssl );
5446+ }
5447+
5448+ void mbedtls_ssl_reset_out_pointers (mbedtls_ssl_context * ssl )
53595449{
53605450 /* Set the incoming and outgoing record pointers. */
53615451#if defined(MBEDTLS_SSL_PROTO_DTLS )
53625452 if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
53635453 ssl -> out_hdr = ssl -> out_buf ;
5364- ssl -> in_hdr = ssl -> in_buf ;
53655454 } else
53665455#endif /* MBEDTLS_SSL_PROTO_DTLS */
53675456 {
53685457 ssl -> out_ctr = ssl -> out_buf ;
5369- ssl -> out_hdr = ssl -> out_buf + 8 ;
5370- ssl -> in_hdr = ssl -> in_buf + 8 ;
5458+ ssl -> out_hdr = ssl -> out_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
53715459 }
5372-
53735460 /* Derive other internal pointers. */
53745461 mbedtls_ssl_update_out_pointers (ssl , NULL /* no transform enabled */ );
5375- mbedtls_ssl_update_in_pointers (ssl );
53765462}
53775463
53785464/*
0 commit comments