@@ -2962,23 +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- /* First handshake fragment must at least include the header. */
2966- if (ssl -> in_msglen < mbedtls_ssl_hs_hdr_len (ssl ) && ssl -> in_hslen == 0 ) {
2967- MBEDTLS_SSL_DEBUG_MSG (1 , ("handshake message too short: %" MBEDTLS_PRINTF_SIZET ,
2968- ssl -> in_msglen ));
2969- return MBEDTLS_ERR_SSL_INVALID_RECORD ;
2970- }
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+ }
29712976
2972- if (ssl -> in_hslen == 0 ) {
29732977 ssl -> in_hslen = mbedtls_ssl_hs_hdr_len (ssl ) + ssl_get_hs_total_len (ssl );
2974- ssl -> in_hsfraglen = 0 ;
29752978 }
29762979
29772980 MBEDTLS_SSL_DEBUG_MSG (3 , ("handshake message: msglen ="
29782981 " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
29792982 MBEDTLS_PRINTF_SIZET ,
29802983 ssl -> in_msglen , ssl -> in_msg [0 ], ssl -> in_hslen ));
29812984
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+
29822993#if defined(MBEDTLS_SSL_PROTO_DTLS )
29832994 if (ssl -> conf -> transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) {
29842995 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
@@ -3038,60 +3049,105 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
30383049 }
30393050 } else
30403051#endif /* MBEDTLS_SSL_PROTO_DTLS */
3041- if (ssl -> in_hsfraglen <= ssl -> in_hslen ) {
3042- int ret ;
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. */
30433059 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+
30443069 MBEDTLS_SSL_DEBUG_MSG (3 ,
3045- ("handshake fragment: %" MBEDTLS_PRINTF_SIZET " .. %"
3046- MBEDTLS_PRINTF_SIZET " of %"
3047- MBEDTLS_PRINTF_SIZET " msglen %" MBEDTLS_PRINTF_SIZET ,
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 ,
30483080 ssl -> in_hsfraglen ,
3049- ssl -> in_hsfraglen +
3050- (hs_remain <= ssl -> in_msglen ? hs_remain : ssl -> in_msglen ),
3051- ssl -> in_hslen , ssl -> in_msglen ));
3052- if (ssl -> in_msglen < hs_remain ) {
3053- ssl -> in_hsfraglen += ssl -> in_msglen ;
3054- ssl -> in_hdr = ssl -> in_msg + ssl -> in_msglen ;
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 ;
30553120 ssl -> in_msglen = 0 ;
30563121 mbedtls_ssl_update_in_pointers (ssl );
30573122 return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3058- }
3059- if (ssl -> in_hsfraglen > 0 ) {
3060- /*
3061- * At in_first_hdr we have a sequence of records that cover the next handshake
3062- * record, each with its own record header that we need to remove.
3063- * Note that the reassembled record size may not equal the size of the message,
3064- * there may be more messages after it, complete or partial.
3065- */
3066- unsigned char * in_first_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
3067- unsigned char * p = in_first_hdr , * q = NULL ;
3068- size_t merged_rec_len = 0 ;
3069- do {
3070- mbedtls_record rec ;
3071- ret = ssl_parse_record_header (ssl , p , mbedtls_ssl_in_hdr_len (ssl ), & rec );
3072- if (ret != 0 ) {
3073- return ret ;
3074- }
3075- merged_rec_len += rec .data_len ;
3076- p = rec .buf + rec .buf_len ;
3077- if (q != NULL ) {
3078- memmove (q , rec .buf + rec .data_offset , rec .data_len );
3079- q += rec .data_len ;
3080- } else {
3081- q = p ;
3082- }
3083- } while (merged_rec_len < ssl -> in_hslen );
3084- ssl -> in_hdr = in_first_hdr ;
3085- mbedtls_ssl_update_in_pointers (ssl );
3086- ssl -> in_msglen = merged_rec_len ;
3087- /* Adjust message length. */
3088- MBEDTLS_PUT_UINT16_BE (merged_rec_len , ssl -> in_len , 0 );
3123+ } else {
3124+ ssl -> in_msglen = ssl -> in_hsfraglen ;
30893125 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 ;
30903141 MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3091- ssl -> in_hdr , mbedtls_ssl_in_hdr_len (ssl ) + merged_rec_len );
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+ }
30923150 }
3093- } else {
3094- return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
30953151 }
30963152
30973153 return 0 ;
@@ -4438,11 +4494,9 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
44384494
44394495 if (ssl -> in_hsfraglen != 0 ) {
44404496 /* Not all handshake fragments have arrived, do not consume. */
4441- MBEDTLS_SSL_DEBUG_MSG (3 ,
4442- ("waiting for more fragments (%" MBEDTLS_PRINTF_SIZET " of %"
4443- MBEDTLS_PRINTF_SIZET ", %" MBEDTLS_PRINTF_SIZET " left)" ,
4444- ssl -> in_hsfraglen , ssl -> in_hslen ,
4445- ssl -> in_hslen - ssl -> in_hsfraglen ));
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 ));
44464500 return 0 ;
44474501 }
44484502
0 commit comments