@@ -3221,23 +3221,34 @@ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
32213221
32223222int mbedtls_ssl_prepare_handshake_record (mbedtls_ssl_context * ssl )
32233223{
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 ) {
3226- MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
3227- ssl -> in_msglen ));
3228- return MBEDTLS_ERR_SSL_INVALID_RECORD ;
3229- }
3224+ if (ssl -> badmac_seen_or_in_hsfraglen == 0 ) {
3225+ /* The handshake message must at least include the header.
3226+ * We may not have the full message yet in case of fragmentation.
3227+ * To simplify the code, we insist on having the header (and in
3228+ * particular the handshake message length) in the first
3229+ * fragment. */
3230+ if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl )) {
3231+ MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
3232+ ssl -> in_msglen ));
3233+ return MBEDTLS_ERR_SSL_INVALID_RECORD ;
3234+ }
32303235
3231- if (ssl -> in_hslen == 0 ) {
32323236 ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
3233- ssl -> badmac_seen_or_in_hsfraglen = 0 ;
32343237 }
32353238
32363239 MBEDTLS_SSL_DEBUG_MSG (3 , ("handshake message: msglen ="
32373240 " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
32383241 MBEDTLS_PRINTF_SIZET ,
32393242 ssl -> in_msglen , ssl -> in_msg [0 ], ssl -> in_hslen ));
32403243
3244+ if (ssl -> transform_in != NULL ) {
3245+ MBEDTLS_SSL_DEBUG_MSG (4 , ("decrypted handshake message:"
3246+ " iv-buf=%d hdr-buf=%d hdr-buf=%d" ,
3247+ (int ) (ssl -> in_iv - ssl -> in_buf ),
3248+ (int ) (ssl -> in_hdr - ssl -> in_buf ),
3249+ (int ) (ssl -> in_msg - ssl -> in_buf )));
3250+ }
3251+
32413252#if defined(MBEDTLS_SSL_PROTO_DTLS )
32423253 if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
32433254 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
@@ -3297,67 +3308,103 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
32973308 }
32983309 } else
32993310#endif /* MBEDTLS_SSL_PROTO_DTLS */
3300- if (ssl -> badmac_seen_or_in_hsfraglen <= ssl -> in_hslen ) {
3301- int ret ;
3311+ {
3312+ unsigned char * const reassembled_record_start =
3313+ ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
3314+ unsigned char * const payload_start =
3315+ reassembled_record_start + mbedtls_ssl_in_hdr_len (ssl );
3316+ unsigned char * payload_end = payload_start + ssl -> badmac_seen_or_in_hsfraglen ;
3317+ /* How many more bytes we want to have a complete handshake message. */
33023318 const size_t hs_remain = ssl -> in_hslen - ssl -> badmac_seen_or_in_hsfraglen ;
3319+ /* How many bytes of the current record are part of the first
3320+ * handshake message. There may be more handshake messages (possibly
3321+ * incomplete) in the same record; if so, we leave them after the
3322+ * current record, and ssl_consume_current_message() will take
3323+ * care of consuming the next handshake message. */
3324+ const size_t hs_this_fragment_len =
3325+ ssl -> in_msglen > hs_remain ? hs_remain : ssl -> in_msglen ;
3326+ (void ) hs_this_fragment_len ;
3327+
33033328 MBEDTLS_SSL_DEBUG_MSG (3 ,
3304- ("handshake fragment: %u .. %"
3305- MBEDTLS_PRINTF_SIZET " of %"
3306- MBEDTLS_PRINTF_SIZET " msglen %" MBEDTLS_PRINTF_SIZET ,
3329+ ("%s handshake fragment: %" MBEDTLS_PRINTF_SIZET
3330+ ", %u..%u of %" MBEDTLS_PRINTF_SIZET ,
3331+ (ssl -> badmac_seen_or_in_hsfraglen != 0 ?
3332+ "subsequent" :
3333+ hs_this_fragment_len == ssl -> in_hslen ?
3334+ "sole" :
3335+ "initial" ),
3336+ ssl -> in_msglen ,
33073337 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 ;
3338+ ssl -> badmac_seen_or_in_hsfraglen +
3339+ (unsigned ) hs_this_fragment_len ,
3340+ ssl -> in_hslen ));
3341+
3342+ /* Move the received handshake fragment to have the whole message
3343+ * (at least the part received so far) in a single segment at a
3344+ * known offset in the input buffer.
3345+ * - When receiving a non-initial handshake fragment, append it to
3346+ * the initial segment.
3347+ * - Even the initial handshake fragment is moved, if it was
3348+ * encrypted with an explicit IV: decryption leaves the payload
3349+ * after the explicit IV, but here we move it to start where the
3350+ * IV was.
3351+ */
3352+ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH )
3353+ size_t const in_buf_len = ssl -> in_buf_len ;
3354+ #else
3355+ size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN ;
3356+ #endif
3357+ if (payload_end + ssl -> in_msglen > ssl -> in_buf + in_buf_len ) {
3358+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3359+ ("Shouldn't happen: no room to move handshake fragment %"
3360+ MBEDTLS_PRINTF_SIZET " from %p to %p (buf=%p len=%"
3361+ MBEDTLS_PRINTF_SIZET ")" ,
3362+ ssl -> in_msglen ,
3363+ (void * ) ssl -> in_msg , (void * ) payload_end ,
3364+ (void * ) ssl -> in_buf , in_buf_len ));
3365+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3366+ }
3367+ memmove (payload_end , ssl -> in_msg , ssl -> in_msglen );
3368+
3369+ ssl -> badmac_seen_or_in_hsfraglen += (unsigned ) ssl -> in_msglen ;
3370+ payload_end += ssl -> in_msglen ;
3371+
3372+ if (ssl -> badmac_seen_or_in_hsfraglen < ssl -> in_hslen ) {
3373+ MBEDTLS_SSL_DEBUG_MSG (3 , ("Prepare: waiting for more handshake fragments "
3374+ "%u/%" MBEDTLS_PRINTF_SIZET ,
3375+ ssl -> badmac_seen_or_in_hsfraglen , ssl -> in_hslen ));
3376+ ssl -> in_hdr = payload_end ;
33213377 ssl -> in_msglen = 0 ;
33223378 mbedtls_ssl_update_in_pointers (ssl );
33233379 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 );
3380+ } else {
3381+ ssl -> in_msglen = ssl -> badmac_seen_or_in_hsfraglen ;
33553382 ssl -> badmac_seen_or_in_hsfraglen = 0 ;
3383+ ssl -> in_hdr = reassembled_record_start ;
3384+ mbedtls_ssl_update_in_pointers (ssl );
3385+
3386+ /* Update the record length in the fully reassembled record */
3387+ if (ssl -> in_msglen > 0xffff ) {
3388+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3389+ ("Shouldn't happen: in_msglen=%"
3390+ MBEDTLS_PRINTF_SIZET " > 0xffff" ,
3391+ ssl -> in_msglen ));
3392+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3393+ }
3394+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
3395+
3396+ size_t record_len = mbedtls_ssl_in_hdr_len (ssl ) + ssl -> in_msglen ;
3397+ (void ) record_len ;
33563398 MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3357- ssl -> in_hdr , mbedtls_ssl_in_hdr_len (ssl ) + merged_rec_len );
3399+ ssl -> in_hdr , record_len );
3400+ if (ssl -> in_hslen < ssl -> in_msglen ) {
3401+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3402+ ("More handshake messages in the record: "
3403+ "%" MBEDTLS_PRINTF_SIZET " + %" MBEDTLS_PRINTF_SIZET ,
3404+ ssl -> in_hslen ,
3405+ ssl -> in_msglen - ssl -> in_hslen ));
3406+ }
33583407 }
3359- } else {
3360- return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
33613408 }
33623409
33633410 return 0 ;
@@ -4704,11 +4751,9 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
47044751
47054752 if (ssl -> badmac_seen_or_in_hsfraglen != 0 ) {
47064753 /* 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 ));
4754+ MBEDTLS_SSL_DEBUG_MSG (3 , ("Consume: waiting for more handshake fragments "
4755+ "%u/%" MBEDTLS_PRINTF_SIZET ,
4756+ ssl -> badmac_seen_or_in_hsfraglen , ssl -> in_hslen ));
47124757 return 0 ;
47134758 }
47144759
0 commit comments