Skip to content

Commit

Permalink
Add draft version of get_early_data_status.
Browse files Browse the repository at this point in the history
Signed-off-by: Jerry Yu <jerry.h.yu@arm.com>
  • Loading branch information
yuhaoth committed Nov 17, 2022
1 parent f808f82 commit a392b0a
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 20 deletions.
85 changes: 85 additions & 0 deletions include/mbedtls/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ typedef enum
MBEDTLS_SSL_FLUSH_BUFFERS,
MBEDTLS_SSL_HANDSHAKE_WRAPUP,
MBEDTLS_SSL_HANDSHAKE_OVER,
MBEDTLS_SSL_END_OF_EARLY_DATA,
MBEDTLS_SSL_NEW_SESSION_TICKET,
MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT,
MBEDTLS_SSL_HELLO_RETRY_REQUEST,
Expand Down Expand Up @@ -1802,6 +1803,12 @@ struct mbedtls_ssl_context
* and #MBEDTLS_SSL_CID_DISABLED. */
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */

#if defined(MBEDTLS_SSL_EARLY_DATA) || \
( defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
defined(MBEDTLS_SSL_SRV_C) )
int MBEDTLS_PRIVATE(early_data_status);
#endif /* MBEDTLS_SSL_EARLY_DATA */

/** Callback to export key block and master secret */
mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys);
void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */
Expand Down Expand Up @@ -4903,6 +4910,84 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
*/
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );

/* Initial status
* Client: The SSL context has passed basic check like resumption, vaild ticket,
* kex modes and so on.
* Server: Same with client side.
*
* TODO: Is it right name? How about MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_DO //no-check-names
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0
/* Client: Allow early data transfter.
* Server: non-exist, server receive early data in fixed states between
* SERVER_FINISHED and EndOfEarlyData for 0-RTT. If no 0-RTT supported,
* ealy data will be skiped. See RFC 8446 A.2 and 4.2.10.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_SENT 1
/* Client: early data indaction of EE IS NOT received.
* Update in MBEDTLS_SSL_ENCRYPTED_EXTENSIONS.
* Sever: early data indaction of EE WON'T be sent. Ignore decrypt errors
* while perform handshake and next state is wait_eoed.
* Update in MBEDTLS_SSL_CLIENT_HELLO.
*
* How about change it to negative value?
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2
/* Client: early data indaction of EE IS received.
* Update in MBEDTLS_SSL_ENCRYPTED_EXTENSIONS.
* Sever: early data indaction of EE WILL be sent. Next state is wait_eoed.
* Update in MBEDTLS_SSL_CLIENT_HELLO.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 3

/**
* \brief Get information about the use of 0-RTT in a TLS 1.3 handshake
*
* \param ssl The SSL context to query
*
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA
* - If this function is called from the server-side. Or,
* - If the session is not resumption session.
* - If the ticket is not valid.
* - If the ticket is not allowed for early data.
* - If early_data is disabled.
* \return other negative value that reported in negotiation
*
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN the SSL context \p ssl
* is allowed to send early data, but not ready for sending
* early data.
*
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_SENT it is possible to
* send early data for the SSL context \p ssl.
*
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has
* indicated the use of early data but the server has rejected
* it. In this situation, the client may want to re-send the
* early data, it may have sent early data as ordinary
* post-handshake application data via mbedtls_ssl_write().
*
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has
* indicated the use of early data and the server has accepted
* it.
*/
#if defined(MBEDTLS_SSL_EARLY_DATA)
int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_EARLY_DATA */

#if !defined(MBEDTLS_SSL_EARLY_DATA) && \
defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* TODO: move it to ssl_misc.h if design review finished.
*
* This is prepare for ignore decrypt error. When !defined(MBEDTLS_SSL_EARLY_DATA)
* That is described in section A.2 and 4.2.10.
*/
static inline int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl )
{
return( ssl->MBEDTLS_PRIVATE(early_data_status) );
}
#endif /* !MBEDTLS_SSL_EARLY_DATA */

/**
* \brief Free referenced items in an SSL context and clear memory
*
Expand Down
29 changes: 29 additions & 0 deletions library/ssl_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,35 @@ int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg( ssl,
buf_len,
msg_len ) );

#if defined(MBEDTLS_SSL_EARLY_DATA)
/* RFC 8446 section A.1
* START <----+
* Send ClientHello | | Recv HelloRetryRequest
* [K_send = early data] | |
* v |
* / WAIT_SH ----+
*
* Consider about hybrid mode, early tranform MUST be set only in TLS 1.3.
* And 2nd ClientHello should be encrypted with early traffic.
*
* NOTICE: Above points should be discuss when code review.
*/
if( mbedtls_ssl_conf_is_tls13_only( ssl->conf ) &&
mbedtls_ssl_get_early_data_status( ssl ) ==
MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN )
{
/* TODO: Add early transform here */

/* Switch outbound traffic to early */
MBEDTLS_SSL_DEBUG_MSG(
1, ( "Switch to early keys for outbound traffic."
" [K_send = early data]" ) );
mbedtls_ssl_set_outbound_transform(
ssl, ssl->handshake->transform_earlydata );
}
#endif /* MBEDTLS_SSL_EARLY_DATA */

mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO );
}

Expand Down
129 changes: 129 additions & 0 deletions library/ssl_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,131 @@ void mbedtls_ssl_tls13_conf_early_data_cb(
conf->early_data_conext = context;
}
#endif /* MBEDTLS_SSL_SRV_C */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_early_data_common_static_check( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_session *session = ssl->session_negotiate;

if( ssl == NULL || ssl->conf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSL context is not available." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if( ssl->conf->max_early_data_size == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ("early data is disabled." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_STREAM )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS not supported yet." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if( ! mbedtls_ssl_conf_tls13_some_psk_enabled( ssl ) )
{
MBEDTLS_SSL_DEBUG_MSG(
1, ( "psk or psk_ephemeral is not available." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if( ssl->handshake && ( ssl->handshake->resume != 1 || session == NULL ) )
{
MBEDTLS_SSL_DEBUG_MSG(
1, ( "early data is only available for resumption session." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if(session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3 )
{
MBEDTLS_SSL_DEBUG_MSG(
1, ( "early data is only available for TLS 1.3 ticket." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

if( ! mbedtls_ssl_tls13_cipher_suite_is_offered(
ssl, session->ciphersuite ) )
{
MBEDTLS_SSL_DEBUG_MSG(
1, ( "ciphersuite is not valid." ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}

return( 0 );
}

#if defined(MBEDTLS_SSL_SRV_C)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_early_data_srv_status_check( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

if( ! ( ssl->state == MBEDTLS_SSL_HELLO_REQUEST ||
ssl->state == MBEDTLS_SSL_CLIENT_HELLO ) )
{
if( ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN &&
ssl->transform_in != NULL &&
ssl->transform_in == ssl->handshake->transform_earlydata )
{
return( MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_SENT );
}
return( ssl->early_data_status );
}
ret = ssl_tls13_early_data_common_static_check( ssl );
if( ret != 0 )
return( ret );
/* Add server special check here. */

return( ret );
}
#endif /* MBEDTLS_SSL_SRV_C */

#if defined(MBEDTLS_SSL_CLI_C)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_early_data_cli_status_check( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST )
{
if( ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN &&
ssl->transform_out != NULL &&
ssl->transform_out == ssl->handshake->transform_earlydata )
{
return( MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_SENT );
}

return( ssl->early_data_status );
}

ret = ssl_tls13_early_data_common_static_check( ssl );
if( ret != 0 )
return( ret );
/* Add client special check here. */

return( ret );
}
#endif /* MBEDTLS_SSL_CLI_C */

int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl )
{
if( mbedtls_ssl_is_handshake_over( ssl ) )
return( ssl->early_data_status );

#if defined(MBEDTLS_SSL_SRV_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
return( ssl_tls13_early_data_srv_status_check( ssl ) );
#endif
#if defined(MBEDTLS_SSL_CLI_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
return( ssl_tls13_early_data_cli_status_check( ssl ) );
#endif
return( 0 );
}

#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

Expand Down Expand Up @@ -3643,6 +3768,10 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
case MBEDTLS_SSL_HELLO_REQUEST:
ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
ret = 0;
#if defined(MBEDTLS_SSL_EARLY_DATA)
ssl->early_data_status =
mbedtls_ssl_get_early_data_status( ssl );
#endif /* MBEDTLS_SSL_EARLY_DATA */
break;

case MBEDTLS_SSL_CLIENT_HELLO:
Expand Down
Loading

0 comments on commit a392b0a

Please sign in to comment.