@@ -3220,13 +3220,18 @@ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
3220
3220
3221
3221
int mbedtls_ssl_prepare_handshake_record (mbedtls_ssl_context * ssl )
3222
3222
{
3223
- if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl )) {
3223
+ /* First handshake fragment must at least include the header. */
3224
+ if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl ) && ssl -> in_hslen == 0 ) {
3224
3225
MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
3225
3226
ssl -> in_msglen ));
3226
3227
return MBEDTLS_ERR_SSL_INVALID_RECORD ;
3227
3228
}
3228
3229
3229
- ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
3230
+ if (ssl -> in_hslen == 0 ) {
3231
+ ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
3232
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen = 0 ;
3233
+ mbedtls_ssl_get_in_ext (ssl )-> in_hshdr = ssl -> in_hdr ;
3234
+ }
3230
3235
3231
3236
MBEDTLS_SSL_DEBUG_MSG (3 , ("handshake message: msglen ="
3232
3237
" %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
@@ -3292,10 +3297,61 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
3292
3297
}
3293
3298
} else
3294
3299
#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
+ {
3301
+ if (mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen > ssl -> in_hslen ) {
3302
+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3303
+ }
3304
+ int ret ;
3305
+ const size_t hs_remain = ssl -> in_hslen - mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen ;
3306
+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3307
+ ("handshake fragment: %" MBEDTLS_PRINTF_SIZET " .. %"
3308
+ MBEDTLS_PRINTF_SIZET " of %"
3309
+ MBEDTLS_PRINTF_SIZET " msglen %" MBEDTLS_PRINTF_SIZET ,
3310
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen ,
3311
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen +
3312
+ (hs_remain <= ssl -> in_msglen ? hs_remain : ssl -> in_msglen ),
3313
+ ssl -> in_hslen , ssl -> in_msglen ));
3314
+ if (ssl -> in_msglen < hs_remain ) {
3315
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen += ssl -> in_msglen ;
3316
+ ssl -> in_hdr = ssl -> in_msg + ssl -> in_msglen ;
3317
+ ssl -> in_msglen = 0 ;
3318
+ mbedtls_ssl_update_in_pointers (ssl );
3319
+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3320
+ }
3321
+ if (mbedtls_ssl_get_in_ext (ssl )-> in_hshdr != ssl -> in_hdr ) {
3322
+ /*
3323
+ * At mbedtls_ssl_get_in_ext(ssl)->in_hshdr we have a sequence of records that cover the next handshake
3324
+ * record, each with its own record header that we need to remove.
3325
+ * Note that the reassembled record size may not equal the size of the message,
3326
+ * there maybe bytes from the next message following it.
3327
+ */
3328
+ size_t merged_rec_len = 0 ;
3329
+ unsigned char * p = mbedtls_ssl_get_in_ext (ssl )-> in_hshdr , * q = NULL ;
3330
+ do {
3331
+ mbedtls_record rec ;
3332
+ ret = ssl_parse_record_header (ssl , p , mbedtls_ssl_in_hdr_len (ssl ), & rec );
3333
+ if (ret != 0 ) {
3334
+ return ret ;
3335
+ }
3336
+ merged_rec_len += rec .data_len ;
3337
+ p = rec .buf + rec .buf_len ;
3338
+ if (q != NULL ) {
3339
+ memmove (q , rec .buf + rec .data_offset , rec .data_len );
3340
+ q += rec .data_len ;
3341
+ } else {
3342
+ q = p ;
3343
+ }
3344
+ } while (merged_rec_len < ssl -> in_hslen );
3345
+ ssl -> in_hdr = mbedtls_ssl_get_in_ext (ssl )-> in_hshdr ;
3346
+ mbedtls_ssl_update_in_pointers (ssl );
3347
+ ssl -> in_msglen = merged_rec_len ;
3348
+ /* Adjust message length. */
3349
+ MBEDTLS_PUT_UINT16_BE (merged_rec_len , ssl -> in_len , 0 );
3350
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen = 0 ;
3351
+ mbedtls_ssl_get_in_ext (ssl )-> in_hshdr = NULL ;
3352
+ MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3353
+ ssl -> in_hdr , mbedtls_ssl_in_hdr_len (ssl ) + merged_rec_len );
3354
+ }
3299
3355
}
3300
3356
3301
3357
return 0 ;
@@ -4640,6 +4696,16 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
4640
4696
return MBEDTLS_ERR_SSL_INTERNAL_ERROR ;
4641
4697
}
4642
4698
4699
+ if (mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen != 0 ) {
4700
+ /* Not all handshake fragments have arrived, do not consume. */
4701
+ MBEDTLS_SSL_DEBUG_MSG (3 ,
4702
+ ("waiting for more fragments (%" MBEDTLS_PRINTF_SIZET " of %"
4703
+ MBEDTLS_PRINTF_SIZET ", %" MBEDTLS_PRINTF_SIZET " left)" ,
4704
+ mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen , ssl -> in_hslen ,
4705
+ ssl -> in_hslen - mbedtls_ssl_get_in_ext (ssl )-> in_hsfraglen ));
4706
+ return 0 ;
4707
+ }
4708
+
4643
4709
/*
4644
4710
* Get next Handshake message in the current record
4645
4711
*/
@@ -4665,6 +4731,7 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
4665
4731
ssl -> in_msglen -= ssl -> in_hslen ;
4666
4732
memmove (ssl -> in_msg , ssl -> in_msg + ssl -> in_hslen ,
4667
4733
ssl -> in_msglen );
4734
+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
4668
4735
4669
4736
MBEDTLS_SSL_DEBUG_BUF (4 , "remaining content in record" ,
4670
4737
ssl -> in_msg , ssl -> in_msglen );
@@ -4888,7 +4955,7 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
4888
4955
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
4889
4956
ssl -> in_len = ssl -> in_cid + rec .cid_len ;
4890
4957
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
4891
- ssl -> in_iv = ssl -> in_msg = ssl -> in_len + 2 ;
4958
+ mbedtls_ssl_get_in_ext ( ssl ) -> in_iv = ssl -> in_msg = ssl -> in_len + 2 ;
4892
4959
ssl -> in_msglen = rec .data_len ;
4893
4960
4894
4961
ret = ssl_check_client_reconnect (ssl );
@@ -5007,7 +5074,7 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
5007
5074
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
5008
5075
ssl -> in_len = ssl -> in_cid + rec .cid_len ;
5009
5076
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
5010
- ssl -> in_iv = ssl -> in_len + 2 ;
5077
+ mbedtls_ssl_get_in_ext ( ssl ) -> in_iv = ssl -> in_len + 2 ;
5011
5078
5012
5079
/* The record content type may change during decryption,
5013
5080
* so re-read it. */
@@ -5319,7 +5386,7 @@ void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,
5319
5386
void mbedtls_ssl_update_in_pointers (mbedtls_ssl_context * ssl )
5320
5387
{
5321
5388
/* This function sets the pointers to match the case
5322
- * of unprotected TLS/DTLS records, with both ssl->in_iv
5389
+ * of unprotected TLS/DTLS records, with both mbedtls_ssl_get_in_ext( ssl) ->in_iv
5323
5390
* and ssl->in_msg pointing to the beginning of the record
5324
5391
* content.
5325
5392
*
@@ -5341,44 +5408,55 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
5341
5408
#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
5342
5409
ssl -> in_len = ssl -> in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5343
5410
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
5344
- ssl -> in_iv = ssl -> in_len + 2 ;
5411
+ mbedtls_ssl_get_in_ext ( ssl ) -> in_iv = ssl -> in_len + 2 ;
5345
5412
} else
5346
5413
#endif
5347
5414
{
5348
- ssl -> in_ctr = ssl -> in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5415
+ ssl -> in_ctr = ssl -> in_buf ;
5349
5416
ssl -> in_len = ssl -> in_hdr + 3 ;
5350
5417
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
5351
5418
ssl -> in_cid = ssl -> in_len ;
5352
5419
#endif
5353
- ssl -> in_iv = ssl -> in_hdr + 5 ;
5420
+ mbedtls_ssl_get_in_ext ( ssl ) -> in_iv = ssl -> in_hdr + 5 ;
5354
5421
}
5355
5422
5356
5423
/* This will be adjusted at record decryption time. */
5357
- ssl -> in_msg = ssl -> in_iv ;
5424
+ ssl -> in_msg = mbedtls_ssl_get_in_ext ( ssl ) -> in_iv ;
5358
5425
}
5359
5426
5360
5427
/*
5361
5428
* Setup an SSL context
5362
5429
*/
5363
5430
5364
- void mbedtls_ssl_reset_in_out_pointers (mbedtls_ssl_context * ssl )
5431
+ void mbedtls_ssl_reset_in_pointers (mbedtls_ssl_context * ssl )
5432
+ {
5433
+ #if defined(MBEDTLS_SSL_PROTO_DTLS )
5434
+ if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
5435
+ ssl -> in_hdr = ssl -> in_buf ;
5436
+ } else
5437
+ #endif /* MBEDTLS_SSL_PROTO_DTLS */
5438
+ {
5439
+ ssl -> in_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5440
+ }
5441
+
5442
+ /* Derive other internal pointers. */
5443
+ mbedtls_ssl_update_in_pointers (ssl );
5444
+ }
5445
+
5446
+ void mbedtls_ssl_reset_out_pointers (mbedtls_ssl_context * ssl )
5365
5447
{
5366
5448
/* Set the incoming and outgoing record pointers. */
5367
5449
#if defined(MBEDTLS_SSL_PROTO_DTLS )
5368
5450
if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
5369
5451
ssl -> out_hdr = ssl -> out_buf ;
5370
- ssl -> in_hdr = ssl -> in_buf ;
5371
5452
} else
5372
5453
#endif /* MBEDTLS_SSL_PROTO_DTLS */
5373
5454
{
5374
5455
ssl -> out_ctr = ssl -> out_buf ;
5375
- ssl -> out_hdr = ssl -> out_buf + 8 ;
5376
- ssl -> in_hdr = ssl -> in_buf + 8 ;
5456
+ ssl -> out_hdr = ssl -> out_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5377
5457
}
5378
-
5379
5458
/* Derive other internal pointers. */
5380
5459
mbedtls_ssl_update_out_pointers (ssl , NULL /* no transform enabled */ );
5381
- mbedtls_ssl_update_in_pointers (ssl );
5382
5460
}
5383
5461
5384
5462
/*
0 commit comments