mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-26 04:45:44 +01:00
Correct length check for DTLS records from old epochs.
DTLS records from previous epochs were incorrectly checked against the current epoch transform's minimal content length, leading to the rejection of entire datagrams. This commit fixed that and adapts two test cases accordingly. Internal reference: IOTSSL-1417
This commit is contained in:
parent
d82d84664a
commit
52c6dc64c6
@ -3522,81 +3522,23 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
/* Check length against bounds of the current transform and version */
|
||||
if( ssl->transform_in == NULL )
|
||||
{
|
||||
if( ssl->in_msglen < 1 ||
|
||||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ssl->in_msglen < ssl->transform_in->minlen )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/*
|
||||
* TLS encrypted messages can have up to 256 bytes of padding
|
||||
*/
|
||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen +
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* DTLS-related tests done last, because most of them may result in
|
||||
* silently dropping the record (but not the whole datagram), and we only
|
||||
* want to consider that after ensuring that the "basic" fields (type,
|
||||
* version, length) are sane.
|
||||
* DTLS-related tests.
|
||||
* Check epoch before checking length constraint because
|
||||
* the latter varies with the epoch. E.g., if a ChangeCipherSpec
|
||||
* message gets duplicated before the corresponding Finished message,
|
||||
* the second ChangeCipherSpec should be discarded because it belongs
|
||||
* to an old epoch, but not because its length is shorter than
|
||||
* the minimum record length for packets using the new record transform.
|
||||
* Note that these two kinds of failures are handled differently,
|
||||
* as an unexpected record is silently skipped but an invalid
|
||||
* record leads to the entire datagram being dropped.
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
{
|
||||
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
|
||||
|
||||
/* Drop unexpected ChangeCipherSpec messages */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Drop unexpected ApplicationData records,
|
||||
* except at the beginning of renegotiations */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
||||
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
||||
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Check epoch (and sequence number) with DTLS */
|
||||
if( rec_epoch != ssl->in_epoch )
|
||||
{
|
||||
@ -3636,9 +3578,74 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Drop unexpected ChangeCipherSpec messages */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Drop unexpected ApplicationData records,
|
||||
* except at the beginning of renegotiations */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
||||
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
||||
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
|
||||
/* Check length against bounds of the current transform and version */
|
||||
if( ssl->transform_in == NULL )
|
||||
{
|
||||
if( ssl->in_msglen < 1 ||
|
||||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ssl->in_msglen < ssl->transform_in->minlen )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/*
|
||||
* TLS encrypted messages can have up to 256 bytes of padding
|
||||
*/
|
||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen +
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -3702,8 +3702,8 @@ run_test "DTLS proxy: duplicate every packet" \
|
||||
0 \
|
||||
-c "replayed record" \
|
||||
-s "replayed record" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-S "resend" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK"
|
||||
@ -3715,8 +3715,8 @@ run_test "DTLS proxy: duplicate every packet, server anti-replay off" \
|
||||
0 \
|
||||
-c "replayed record" \
|
||||
-S "replayed record" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-c "resend" \
|
||||
-s "resend" \
|
||||
-s "Extra-header:" \
|
||||
@ -3777,8 +3777,6 @@ run_test "DTLS proxy: delay ChangeCipherSpec" \
|
||||
0 \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user