mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-01-28 00:35:21 +00:00
Merge pull request #3910 from hanno-arm/post_handshake_handling
Introduce helper for handling of post-handshake handshake messages in TLS <=1.2
This commit is contained in:
commit
5b416e95b2
@ -5112,6 +5112,120 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
|
|||||||
}
|
}
|
||||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
|
|
||||||
|
/* This function is called from mbedtls_ssl_read() when a handshake message is
|
||||||
|
* received after the initial handshake. In this context, handshake messages
|
||||||
|
* may only be sent for the purpose of initiating renegotiations.
|
||||||
|
*
|
||||||
|
* This function is introduced as a separate helper since the handling
|
||||||
|
* of post-handshake handshake messages changes significantly in TLS 1.3,
|
||||||
|
* and having a helper function allows to distinguish between TLS <= 1.2 and
|
||||||
|
* TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read().
|
||||||
|
*/
|
||||||
|
static int ssl_handle_hs_message_post_handshake( mbedtls_ssl_context *ssl )
|
||||||
|
{
|
||||||
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - For client-side, expect SERVER_HELLO_REQUEST.
|
||||||
|
* - For server-side, expect CLIENT_HELLO.
|
||||||
|
* - Fail (TLS) or silently drop record (DTLS) in other cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_CLI_C)
|
||||||
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
||||||
|
( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
|
||||||
|
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
|
||||||
|
|
||||||
|
/* With DTLS, drop the packet (probably from last handshake) */
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_SSL_CLI_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_SRV_C)
|
||||||
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||||
|
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
|
||||||
|
|
||||||
|
/* With DTLS, drop the packet (probably from last handshake) */
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_SSL_SRV_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||||
|
/* Determine whether renegotiation attempt should be accepted */
|
||||||
|
if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
|
||||||
|
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
|
||||||
|
ssl->conf->allow_legacy_renegotiation ==
|
||||||
|
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Accept renegotiation request
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* DTLS clients need to know renego is server-initiated */
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||||
|
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
||||||
|
{
|
||||||
|
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ret = mbedtls_ssl_start_renegotiation( ssl );
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
|
||||||
|
ret != 0 )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
|
||||||
|
ret );
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Refuse renegotiation
|
||||||
|
*/
|
||||||
|
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||||
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||||
|
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
|
||||||
|
{
|
||||||
|
if( ( ret = mbedtls_ssl_send_alert_message( ssl,
|
||||||
|
MBEDTLS_SSL_ALERT_LEVEL_WARNING,
|
||||||
|
MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
|
||||||
|
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receive application data decrypted from the SSL layer
|
* Receive application data decrypted from the SSL layer
|
||||||
*/
|
*/
|
||||||
@ -5210,108 +5324,17 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
|
|
||||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
|
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
|
ret = ssl_handle_hs_message_post_handshake( ssl );
|
||||||
|
if( ret != 0)
|
||||||
/*
|
|
||||||
* - For client-side, expect SERVER_HELLO_REQUEST.
|
|
||||||
* - For server-side, expect CLIENT_HELLO.
|
|
||||||
* - Fail (TLS) or silently drop record (DTLS) in other cases.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_CLI_C)
|
|
||||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
|
||||||
( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
|
|
||||||
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
|
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
|
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_handle_hs_message_post_handshake",
|
||||||
|
ret );
|
||||||
/* With DTLS, drop the packet (probably from last handshake) */
|
return( ret );
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_SSL_CLI_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_SRV_C)
|
|
||||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
|
||||||
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
|
|
||||||
|
|
||||||
/* With DTLS, drop the packet (probably from last handshake) */
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_SSL_SRV_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
|
||||||
/* Determine whether renegotiation attempt should be accepted */
|
|
||||||
if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
|
|
||||||
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
|
|
||||||
ssl->conf->allow_legacy_renegotiation ==
|
|
||||||
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Accept renegotiation request
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* DTLS clients need to know renego is server-initiated */
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
|
||||||
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
|
||||||
{
|
|
||||||
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ret = mbedtls_ssl_start_renegotiation( ssl );
|
|
||||||
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
|
|
||||||
ret != 0 )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
|
|
||||||
ret );
|
|
||||||
return( ret );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Refuse renegotiation
|
|
||||||
*/
|
|
||||||
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
|
||||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
||||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
|
|
||||||
{
|
|
||||||
if( ( ret = mbedtls_ssl_send_alert_message( ssl,
|
|
||||||
MBEDTLS_SSL_ALERT_LEVEL_WARNING,
|
|
||||||
MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
|
|
||||||
{
|
|
||||||
return( ret );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
|
|
||||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point, we don't know whether the renegotiation has been
|
/* At this point, we don't know whether the renegotiation triggered
|
||||||
* completed or not. The cases to consider are the following:
|
* by the post-handshake message has been completed or not. The cases
|
||||||
|
* to consider are the following:
|
||||||
* 1) The renegotiation is complete. In this case, no new record
|
* 1) The renegotiation is complete. In this case, no new record
|
||||||
* has been read yet.
|
* has been read yet.
|
||||||
* 2) The renegotiation is incomplete because the client received
|
* 2) The renegotiation is incomplete because the client received
|
||||||
@ -5319,7 +5342,8 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
* 3) The renegotiation is incomplete because the client received
|
* 3) The renegotiation is incomplete because the client received
|
||||||
* a non-handshake, non-application data message while awaiting
|
* a non-handshake, non-application data message while awaiting
|
||||||
* the ServerHello.
|
* the ServerHello.
|
||||||
* In each of these case, looping will be the proper action:
|
*
|
||||||
|
* In each of these cases, looping will be the proper action:
|
||||||
* - For 1), the next iteration will read a new record and check
|
* - For 1), the next iteration will read a new record and check
|
||||||
* if it's application data.
|
* if it's application data.
|
||||||
* - For 2), the loop condition isn't satisfied as application data
|
* - For 2), the loop condition isn't satisfied as application data
|
||||||
@ -5328,6 +5352,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
* will re-deliver the message that was held back by the client
|
* will re-deliver the message that was held back by the client
|
||||||
* when expecting the ServerHello.
|
* when expecting the ServerHello.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user