@@ -2962,19 +2962,34 @@ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
29622962
29632963int mbedtls_ssl_prepare_handshake_record (mbedtls_ssl_context * ssl )
29642964{
2965- if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl )) {
2966- MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
2967- ssl -> in_msglen ));
2968- return MBEDTLS_ERR_SSL_INVALID_RECORD ;
2969- }
2965+ if (ssl -> in_hsfraglen == 0 ) {
2966+ /* The handshake message must at least include the header.
2967+ * We may not have the full message yet in case of fragmentation.
2968+ * To simplify the code, we insist on having the header (and in
2969+ * particular the handshake message length) in the first
2970+ * fragment. */
2971+ if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl )) {
2972+ MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
2973+ ssl -> in_msglen ));
2974+ return MBEDTLS_ERR_SSL_INVALID_RECORD ;
2975+ }
29702976
2971- ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
2977+ ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
2978+ }
29722979
29732980 MBEDTLS_SSL_DEBUG_MSG (3 , ("handshake message: msglen ="
29742981 " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
29752982 MBEDTLS_PRINTF_SIZET ,
29762983 ssl -> in_msglen , ssl -> in_msg [0 ], ssl -> in_hslen ));
29772984
2985+ if (ssl -> transform_in != NULL ) {
2986+ MBEDTLS_SSL_DEBUG_MSG (4 , ("decrypted handshake message:"
2987+ " iv-buf=%d hdr-buf=%d hdr-buf=%d" ,
2988+ (int ) (ssl -> in_iv - ssl -> in_buf ),
2989+ (int ) (ssl -> in_hdr - ssl -> in_buf ),
2990+ (int ) (ssl -> in_msg - ssl -> in_buf )));
2991+ }
2992+
29782993#if defined(MBEDTLS_SSL_PROTO_DTLS )
29792994 if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
29802995 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
@@ -3034,10 +3049,105 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
30343049 }
30353050 } else
30363051#endif /* MBEDTLS_SSL_PROTO_DTLS */
3037- /* With TLS we don't handle fragmentation (for now) */
3038- if (ssl -> in_msglen < ssl -> in_hslen ) {
3039- MBEDTLS_SSL_DEBUG_MSG (1 , ("TLS handshake fragmentation not supported" ));
3040- return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ;
3052+ {
3053+ unsigned char * const reassembled_record_start =
3054+ ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
3055+ unsigned char * const payload_start =
3056+ reassembled_record_start + mbedtls_ssl_in_hdr_len (ssl );
3057+ unsigned char * payload_end = payload_start + ssl -> in_hsfraglen ;
3058+ /* How many more bytes we want to have a complete handshake message. */
3059+ const size_t hs_remain = ssl -> in_hslen - ssl -> in_hsfraglen ;
3060+ /* How many bytes of the current record are part of the first
3061+ * handshake message. There may be more handshake messages (possibly
3062+ * incomplete) in the same record; if so, we leave them after the
3063+ * current record, and ssl_consume_current_message() will take
3064+ * care of consuming the next handshake message. */
3065+ const size_t hs_this_fragment_len =
3066+ ssl -> in_msglen > hs_remain ? hs_remain : ssl -> in_msglen ;
3067+ (void ) hs_this_fragment_len ;
3068+
3069+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3070+ ("%s handshake fragment: %" MBEDTLS_PRINTF_SIZET
3071+ ", %" MBEDTLS_PRINTF_SIZET
3072+ "..%" MBEDTLS_PRINTF_SIZET
3073+ " of %" MBEDTLS_PRINTF_SIZET ,
3074+ (ssl -> in_hsfraglen != 0 ?
3075+ "subsequent" :
3076+ hs_this_fragment_len == ssl -> in_hslen ?
3077+ "sole" :
3078+ "initial" ),
3079+ ssl -> in_msglen ,
3080+ ssl -> in_hsfraglen ,
3081+ ssl -> in_hsfraglen + hs_this_fragment_len ,
3082+ ssl -> in_hslen ));
3083+
3084+ /* Move the received handshake fragment to have the whole message
3085+ * (at least the part received so far) in a single segment at a
3086+ * known offset in the input buffer.
3087+ * - When receiving a non-initial handshake fragment, append it to
3088+ * the initial segment.
3089+ * - Even the initial handshake fragment is moved, if it was
3090+ * encrypted with an explicit IV: decryption leaves the payload
3091+ * after the explicit IV, but here we move it to start where the
3092+ * IV was.
3093+ */
3094+ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH )
3095+ size_t const in_buf_len = ssl -> in_buf_len ;
3096+ #else
3097+ size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN ;
3098+ #endif
3099+ if (payload_end + ssl -> in_msglen > ssl -> in_buf + in_buf_len ) {
3100+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3101+ ("Shouldn't happen: no room to move handshake fragment %"
3102+ MBEDTLS_PRINTF_SIZET " from %p to %p (buf=%p len=%"
3103+ MBEDTLS_PRINTF_SIZET ")" ,
3104+ ssl -> in_msglen ,
3105+ (void * ) ssl -> in_msg , (void * ) payload_end ,
3106+ (void * ) ssl -> in_buf , in_buf_len ));
3107+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3108+ }
3109+ memmove (payload_end , ssl -> in_msg , ssl -> in_msglen );
3110+
3111+ ssl -> in_hsfraglen += ssl -> in_msglen ;
3112+ payload_end += ssl -> in_msglen ;
3113+
3114+ if (ssl -> in_hsfraglen < ssl -> in_hslen ) {
3115+ MBEDTLS_SSL_DEBUG_MSG (3 , ("Prepare: waiting for more handshake fragments %"
3116+ MBEDTLS_PRINTF_SIZET "/%"
3117+ MBEDTLS_PRINTF_SIZET ,
3118+ ssl -> in_hsfraglen , ssl -> in_hslen ));
3119+ ssl -> in_hdr = payload_end ;
3120+ ssl -> in_msglen = 0 ;
3121+ mbedtls_ssl_update_in_pointers (ssl );
3122+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3123+ } else {
3124+ ssl -> in_msglen = ssl -> in_hsfraglen ;
3125+ ssl -> in_hsfraglen = 0 ;
3126+ ssl -> in_hdr = reassembled_record_start ;
3127+ mbedtls_ssl_update_in_pointers (ssl );
3128+
3129+ /* Update the record length in the fully reassembled record */
3130+ if (ssl -> in_msglen > 0xffff ) {
3131+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3132+ ("Shouldn't happen: in_msglen=%"
3133+ MBEDTLS_PRINTF_SIZET " > 0xffff" ,
3134+ ssl -> in_msglen ));
3135+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3136+ }
3137+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
3138+
3139+ size_t record_len = mbedtls_ssl_in_hdr_len (ssl ) + ssl -> in_msglen ;
3140+ (void ) record_len ;
3141+ MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3142+ ssl -> in_hdr , record_len );
3143+ if (ssl -> in_hslen < ssl -> in_msglen ) {
3144+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3145+ ("More handshake messages in the record: "
3146+ "%" MBEDTLS_PRINTF_SIZET " + %" MBEDTLS_PRINTF_SIZET ,
3147+ ssl -> in_hslen ,
3148+ ssl -> in_msglen - ssl -> in_hslen ));
3149+ }
3150+ }
30413151 }
30423152
30433153 return 0 ;
@@ -4382,6 +4492,14 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
43824492 return MBEDTLS_ERR_SSL_INTERNAL_ERROR ;
43834493 }
43844494
4495+ if (ssl -> in_hsfraglen != 0 ) {
4496+ /* Not all handshake fragments have arrived, do not consume. */
4497+ MBEDTLS_SSL_DEBUG_MSG (3 , ("Consume: waiting for more handshake fragments %"
4498+ MBEDTLS_PRINTF_SIZET "/%" MBEDTLS_PRINTF_SIZET ,
4499+ ssl -> in_hsfraglen , ssl -> in_hslen ));
4500+ return 0 ;
4501+ }
4502+
43854503 /*
43864504 * Get next Handshake message in the current record
43874505 */
@@ -4407,6 +4525,7 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
44074525 ssl -> in_msglen -= ssl -> in_hslen ;
44084526 memmove (ssl -> in_msg , ssl -> in_msg + ssl -> in_hslen ,
44094527 ssl -> in_msglen );
4528+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
44104529
44114530 MBEDTLS_SSL_DEBUG_BUF (4 , "remaining content in record" ,
44124531 ssl -> in_msg , ssl -> in_msglen );
@@ -4770,6 +4889,18 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl)
47704889{
47714890 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
47724891
4892+ /* If we're in the middle of a fragmented TLS handshake message,
4893+ * we don't accept any other message type. For TLS 1.3, the spec forbids
4894+ * interleaving other message types between handshake fragments. For TLS
4895+ * 1.2, the spec does not forbid it but we do. */
4896+ if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_STREAM &&
4897+ ssl -> in_hsfraglen != 0 &&
4898+ ssl -> in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) {
4899+ MBEDTLS_SSL_DEBUG_MSG (1 , ("non-handshake message in the middle"
4900+ " of a fragmented handshake message" ));
4901+ return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ;
4902+ }
4903+
47734904 /*
47744905 * Handle particular types of records
47754906 */
@@ -5081,7 +5212,7 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
50815212 } else
50825213#endif
50835214 {
5084- ssl -> in_ctr = ssl -> in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5215+ ssl -> in_ctr = ssl -> in_buf ;
50855216 ssl -> in_len = ssl -> in_hdr + 3 ;
50865217#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
50875218 ssl -> in_cid = ssl -> in_len ;
@@ -5097,24 +5228,35 @@ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
50975228 * Setup an SSL context
50985229 */
50995230
5100- void mbedtls_ssl_reset_in_out_pointers (mbedtls_ssl_context * ssl )
5231+ void mbedtls_ssl_reset_in_pointers (mbedtls_ssl_context * ssl )
5232+ {
5233+ #if defined(MBEDTLS_SSL_PROTO_DTLS )
5234+ if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
5235+ ssl -> in_hdr = ssl -> in_buf ;
5236+ } else
5237+ #endif /* MBEDTLS_SSL_PROTO_DTLS */
5238+ {
5239+ ssl -> in_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
5240+ }
5241+
5242+ /* Derive other internal pointers. */
5243+ mbedtls_ssl_update_in_pointers (ssl );
5244+ }
5245+
5246+ void mbedtls_ssl_reset_out_pointers (mbedtls_ssl_context * ssl )
51015247{
51025248 /* Set the incoming and outgoing record pointers. */
51035249#if defined(MBEDTLS_SSL_PROTO_DTLS )
51045250 if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
51055251 ssl -> out_hdr = ssl -> out_buf ;
5106- ssl -> in_hdr = ssl -> in_buf ;
51075252 } else
51085253#endif /* MBEDTLS_SSL_PROTO_DTLS */
51095254 {
51105255 ssl -> out_ctr = ssl -> out_buf ;
5111- ssl -> out_hdr = ssl -> out_buf + 8 ;
5112- ssl -> in_hdr = ssl -> in_buf + 8 ;
5256+ ssl -> out_hdr = ssl -> out_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
51135257 }
5114-
51155258 /* Derive other internal pointers. */
51165259 mbedtls_ssl_update_out_pointers (ssl , NULL /* no transform enabled */ );
5117- mbedtls_ssl_update_in_pointers (ssl );
51185260}
51195261
51205262/*
0 commit comments