@@ -3049,64 +3049,117 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
30493049 }
30503050 } else
30513051#endif /* MBEDTLS_SSL_PROTO_DTLS */
3052- if (ssl -> in_hsfraglen <= ssl -> in_hslen ) {
3053- int ret ;
3054- const size_t hs_remain = ssl -> in_hslen - ssl -> in_hsfraglen ;
3055- MBEDTLS_SSL_DEBUG_MSG (3 ,
3056- ("handshake fragment: %" MBEDTLS_PRINTF_SIZET
3057- ", %" MBEDTLS_PRINTF_SIZET
3058- "..%" MBEDTLS_PRINTF_SIZET
3059- " of %" MBEDTLS_PRINTF_SIZET ,
3060- ssl -> in_msglen ,
3061- ssl -> in_hsfraglen ,
3062- ssl -> in_hsfraglen + ssl -> in_msglen ,
3063- ssl -> in_hslen ));
3064- if (ssl -> in_msglen < hs_remain ) {
3065- ssl -> in_hsfraglen += ssl -> in_msglen ;
3066- ssl -> in_hdr = ssl -> in_msg + ssl -> in_msglen ;
3067- ssl -> in_msglen = 0 ;
3068- mbedtls_ssl_update_in_pointers (ssl );
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+
3059+ if (ssl -> in_hsfraglen != 0 ) {
3060+ /* We already had a handshake fragment. Prepare to append
3061+ * to the initial segment. */
3062+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3063+ ("subsequent handshake fragment: %" MBEDTLS_PRINTF_SIZET
3064+ ", %" MBEDTLS_PRINTF_SIZET
3065+ "..%" MBEDTLS_PRINTF_SIZET
3066+ " of %" MBEDTLS_PRINTF_SIZET ,
3067+ ssl -> in_msglen ,
3068+ ssl -> in_hsfraglen ,
3069+ ssl -> in_hsfraglen + ssl -> in_msglen ,
3070+ ssl -> in_hslen ));
3071+
3072+ const size_t hs_remain = ssl -> in_hslen - ssl -> in_hsfraglen ;
3073+ if (ssl -> in_msglen > hs_remain ) {
3074+ MBEDTLS_SSL_DEBUG_MSG (1 , ("Handshake fragment too long: %"
3075+ MBEDTLS_PRINTF_SIZET " but only %"
3076+ MBEDTLS_PRINTF_SIZET " of %"
3077+ MBEDTLS_PRINTF_SIZET " remain" ,
3078+ ssl -> in_msglen ,
3079+ hs_remain ,
3080+ ssl -> in_hslen ));
3081+ return MBEDTLS_ERR_SSL_INVALID_RECORD ;
3082+ }
3083+ } else if (ssl -> in_msglen == ssl -> in_hslen ) {
3084+ /* This is the sole fragment. */
3085+ /* Emit a log message in the same format as when there are
3086+ * multiple fragments, for ease of matching. */
3087+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3088+ ("sole handshake fragment: %" MBEDTLS_PRINTF_SIZET
3089+ ", %" MBEDTLS_PRINTF_SIZET
3090+ "..%" MBEDTLS_PRINTF_SIZET
3091+ " of %" MBEDTLS_PRINTF_SIZET ,
3092+ ssl -> in_msglen ,
3093+ ssl -> in_hsfraglen ,
3094+ ssl -> in_hsfraglen + ssl -> in_msglen ,
3095+ ssl -> in_hslen ));
3096+ } else {
3097+ /* This is the first fragment of many. */
3098+ MBEDTLS_SSL_DEBUG_MSG (3 ,
3099+ ("initial handshake fragment: %" MBEDTLS_PRINTF_SIZET
3100+ ", %" MBEDTLS_PRINTF_SIZET
3101+ "..%" MBEDTLS_PRINTF_SIZET
3102+ " of %" MBEDTLS_PRINTF_SIZET ,
3103+ ssl -> in_msglen ,
3104+ ssl -> in_hsfraglen ,
3105+ ssl -> in_hsfraglen + ssl -> in_msglen ,
3106+ ssl -> in_hslen ));
3107+ }
3108+
3109+ /* Move the received handshake fragment to have the whole message
3110+ * (at least the part received so far) in a single segment at a
3111+ * known offset in the input buffer.
3112+ * - When receiving a non-initial handshake fragment, append it to
3113+ * the initial segment.
3114+ * - Even the initial handshake fragment is moved, if it was
3115+ * encrypted with an explicit IV: decryption leaves the payload
3116+ * after the explicit IV, but here we move it to start where the
3117+ * IV was.
3118+ */
3119+ if (payload_end + ssl -> in_hsfraglen > ssl -> in_buf + ssl -> in_buf_len ) {
3120+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3121+ ("Shouldn't happen: no room to move handshake fragment %"
3122+ MBEDTLS_PRINTF_SIZET " from %p to %p (buf=%p len=%"
3123+ MBEDTLS_PRINTF_SIZET ")" ,
3124+ ssl -> in_msglen ,
3125+ ssl -> in_msg , payload_end ,
3126+ ssl -> in_buf , ssl -> in_buf_len ));
3127+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3128+ }
3129+ memmove (payload_end , ssl -> in_msg , ssl -> in_msglen );
3130+
3131+ ssl -> in_hsfraglen += ssl -> in_msglen ;
3132+ payload_end += ssl -> in_msglen ;
3133+
3134+ if (ssl -> in_hsfraglen < ssl -> in_hslen ) {
30693135 MBEDTLS_SSL_DEBUG_MSG (3 , ("Prepare: waiting for more handshake fragments %"
3070- MBEDTLS_PRINTF_SIZET "/%" MBEDTLS_PRINTF_SIZET ,
3136+ MBEDTLS_PRINTF_SIZET "/%"
3137+ MBEDTLS_PRINTF_SIZET ,
30713138 ssl -> in_hsfraglen , ssl -> in_hslen ));
3072- return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3073- }
3074- if (ssl -> in_hsfraglen > 0 ) {
3075- /*
3076- * At in_first_hdr we have a sequence of records that cover the next handshake
3077- * record, each with its own record header that we need to remove.
3078- * Note that the reassembled record size may not equal the size of the message,
3079- * there may be more messages after it, complete or partial.
3080- */
3081- unsigned char * in_first_hdr = ssl -> in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ;
3082- unsigned char * p = in_first_hdr , * q = NULL ;
3083- size_t merged_rec_len = 0 ;
3084- do {
3085- mbedtls_record rec ;
3086- ret = ssl_parse_record_header (ssl , p , mbedtls_ssl_in_hdr_len (ssl ), & rec );
3087- if (ret != 0 ) {
3088- return ret ;
3089- }
3090- merged_rec_len += rec .data_len ;
3091- p = rec .buf + rec .buf_len ;
3092- if (q != NULL ) {
3093- memmove (q , rec .buf + rec .data_offset , rec .data_len );
3094- q += rec .data_len ;
3095- } else {
3096- q = p ;
3097- }
3098- } while (merged_rec_len < ssl -> in_hslen );
3099- ssl -> in_hdr = in_first_hdr ;
3139+ ssl -> in_hdr = payload_end ;
3140+ ssl -> in_msglen = 0 ;
31003141 mbedtls_ssl_update_in_pointers (ssl );
3101- ssl -> in_msglen = merged_rec_len ;
3102- /* Adjust message length. */
3103- MBEDTLS_PUT_UINT16_BE ( merged_rec_len , ssl -> in_len , 0 ) ;
3142+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ;
3143+ } else {
3144+ ssl -> in_msglen = ssl -> in_hsfraglen ;
31043145 ssl -> in_hsfraglen = 0 ;
3146+ ssl -> in_hdr = reassembled_record_start ;
3147+ mbedtls_ssl_update_in_pointers (ssl );
3148+
3149+ /* Update the record length in the fully reassembled record */
3150+ if (ssl -> in_msglen > 0xffff ) {
3151+ MBEDTLS_SSL_DEBUG_MSG (1 ,
3152+ ("Shouldn't happen: in_msglen=%"
3153+ MBEDTLS_PRINTF_SIZET " > 0xffff" ,
3154+ ssl -> in_msglen ));
3155+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
3156+ }
3157+ MBEDTLS_PUT_UINT16_BE (ssl -> in_msglen , ssl -> in_len , 0 );
3158+
31053159 MBEDTLS_SSL_DEBUG_BUF (4 , "reassembled record" ,
3106- ssl -> in_hdr , mbedtls_ssl_in_hdr_len (ssl ) + merged_rec_len );
3160+ ssl -> in_hdr ,
3161+ mbedtls_ssl_in_hdr_len (ssl ) + ssl -> in_msglen );
31073162 }
3108- } else {
3109- return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
31103163 }
31113164
31123165 return 0 ;
0 commit comments