Implement parsing of CID-based records
Previously, ssl_get_next_record() would fetch 13 Bytes for the record header and hand over to ssl_parse_record_header() to parse and validate these. With the introduction of CID-based records, the record length is not known in advance, and parsing and validating must happen at the same time. ssl_parse_record_header() is therefore rewritten in the following way: 1. Fetch and validate record content type and version. 2. If the record content type indicates a record including a CID, adjust the record header pointers accordingly; here, we use the statically configured length of incoming CIDs, avoiding any elaborate CID parsing mechanism or dependency on the record epoch, as explained in the previous commit. 3. Fetch the rest of the record header (note: this doesn't actually fetch anything, but makes sure that the datagram fetched in the earlier call to ssl_fetch_input() contains enough data). 4. Parse and validate the rest of the record header as before.
This commit is contained in:
parent
6430faf098
commit
ca59c2b486
1 changed files with 59 additions and 9 deletions
|
@ -4850,19 +4850,38 @@ static int ssl_check_record_type( uint8_t record_type )
|
|||
static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int major_ver, minor_ver;
|
||||
int ret;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_in_hdr_len( ssl ) );
|
||||
/* Parse and validate record content type and version */
|
||||
|
||||
ssl->in_msgtype = ssl->in_hdr[0];
|
||||
ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
|
||||
mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
|
||||
"version = [%d:%d], msglen = %d",
|
||||
ssl->in_msgtype,
|
||||
major_ver, minor_ver, ssl->in_msglen ) );
|
||||
|
||||
/* Check record type */
|
||||
#if defined(MBEDTLS_SSL_CID)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_CID &&
|
||||
ssl->conf->cid_len != 0 )
|
||||
{
|
||||
/* Shift pointers to account for record header including CID
|
||||
* struct {
|
||||
* ContentType special_type = tls12_cid;
|
||||
* ProtocolVersion version;
|
||||
* uint16 epoch;
|
||||
* uint48 sequence_number;
|
||||
* opaque cid[cid_length]; // New field
|
||||
* uint16 length;
|
||||
* opaque enc_content[DTLSCiphertext.length];
|
||||
* } DTLSCiphertext;
|
||||
*/
|
||||
|
||||
/* So far, we only support static CID lengths
|
||||
* fixed in the configuration. */
|
||||
ssl->in_len = ssl->in_cid + ssl->conf->cid_len;
|
||||
ssl->in_iv = ssl->in_msg = ssl->in_len + 2;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_CID */
|
||||
if( ssl_check_record_type( ssl->in_msgtype ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
|
||||
|
@ -4891,7 +4910,24 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
/* Check length against the size of our buffer */
|
||||
/* Now that the total length of the record header is known, ensure
|
||||
* that the current datagram is large enough to hold it.
|
||||
* This would fail, for example, if we received a datagram of
|
||||
* size 13 + n Bytes where n is less than the size of incoming CIDs. */
|
||||
ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
|
||||
return( ret );
|
||||
}
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_in_hdr_len( ssl ) );
|
||||
|
||||
/* Parse and validate record length
|
||||
* This must happen after the CID parsing because
|
||||
* its position in the record header depends on
|
||||
* the presence of a CID. */
|
||||
|
||||
ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
|
||||
if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
|
||||
- (size_t)( ssl->in_msg - ssl->in_buf ) )
|
||||
{
|
||||
|
@ -4899,6 +4935,11 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
|
||||
"version = [%d:%d], msglen = %d",
|
||||
ssl->in_msgtype,
|
||||
major_ver, minor_ver, ssl->in_msglen ) );
|
||||
|
||||
/*
|
||||
* DTLS-related tests.
|
||||
* Check epoch before checking length constraint because
|
||||
|
@ -5861,7 +5902,16 @@ static int ssl_get_next_record( mbedtls_ssl_context *ssl )
|
|||
return( ret );
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ) ) != 0 )
|
||||
/* Reset in pointers to default state for TLS/DTLS records,
|
||||
* assuming no CID and no offset between record content and
|
||||
* record plaintext. */
|
||||
ssl_update_in_pointers( ssl );
|
||||
|
||||
/* Ensure that we have enough space available for the default form
|
||||
* of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
|
||||
* with no space for CIDs counted in). */
|
||||
ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
|
||||
return( ret );
|
||||
|
|
Loading…
Reference in a new issue