Merge pull request #5653 from paul-elliott-arm/handshake_over
Add mbedtls_ssl_is_handshake_over()
diff --git a/ChangeLog.d/add_handshake_completion_accessor b/ChangeLog.d/add_handshake_completion_accessor
new file mode 100644
index 0000000..e2b28cf
--- /dev/null
+++ b/ChangeLog.d/add_handshake_completion_accessor
@@ -0,0 +1,4 @@
+Features
+ * Add function mbedtls_ssl_is_handshake_over() to enable querying if the SSL
+ Handshake has completed or not, and thus whether to continue calling
+ mbedtls_ssl_handshake_step(), requested in #4383
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index b819bba..8751fa8 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -4358,11 +4358,40 @@
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
/**
+ * \brief After calling mbedtls_ssl_handshake() to start the SSL
+ * handshake you can call this function to check whether the
+ * handshake is over for a given SSL context. This function
+ * should be also used to determine when to stop calling
+ * mbedtls_handshake_step() for that context.
+ *
+ * \param ssl SSL context
+ *
+ * \return \c 1 if handshake is over, \c 0 if it is still ongoing.
+ */
+static inline int mbedtls_ssl_is_handshake_over( mbedtls_ssl_context *ssl )
+{
+ return( ssl->MBEDTLS_PRIVATE( state ) == MBEDTLS_SSL_HANDSHAKE_OVER );
+}
+
+/**
* \brief Perform a single step of the SSL handshake
*
* \note The state of the context (ssl->state) will be at
* the next state after this function returns \c 0. Do not
- * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
+ * call this function if mbedtls_ssl_is_handshake_over()
+ * returns \c 1.
+ *
+ * \warning Whilst in the past you may have used direct access to the
+ * context state (ssl->state) in order to ascertain when to
+ * stop calling this function and although you can still do
+ * so with something like ssl->MBEDTLS_PRIVATE(state) or by
+ * defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now
+ * considered deprecated and could be broken in any future
+ * release. If you still find you have good reason for such
+ * direct access, then please do contact the team to explain
+ * this (raise an issue or post to the mailing list), so that
+ * we can add a solution to your problem that will be
+ * guaranteed to work in the future.
*
* \param ssl SSL context
*
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index c2effb6..82a4cee 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -1921,7 +1921,7 @@
{
len = in_buf_len - ( ssl->in_hdr - ssl->in_buf );
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
timeout = ssl->handshake->retransmit_timeout;
else
timeout = ssl->conf->read_timeout;
@@ -1945,7 +1945,7 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
mbedtls_ssl_set_timer( ssl, 0 );
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
if( ssl_double_retransmit_timeout( ssl ) != 0 )
{
@@ -2380,7 +2380,7 @@
return( ret );
/* Update state and set timer */
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 1 )
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
else
{
@@ -2937,9 +2937,9 @@
}
if( ssl->handshake != NULL &&
- ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
+ ( ( mbedtls_ssl_is_handshake_over( ssl ) == 0 &&
recv_msg_seq != ssl->handshake->in_msg_seq ) ||
- ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+ ( mbedtls_ssl_is_handshake_over( ssl ) == 1 &&
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
{
if( recv_msg_seq > ssl->handshake->in_msg_seq )
@@ -3005,7 +3005,7 @@
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 && hs != NULL )
{
ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
}
@@ -3626,7 +3626,7 @@
*/
if( rec_epoch == 0 &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+ mbedtls_ssl_is_handshake_over( ssl ) == 1 &&
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
ssl->in_left > 13 &&
ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
@@ -4783,7 +4783,7 @@
/* 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
+ mbedtls_ssl_is_handshake_over( ssl ) == 0
#if defined(MBEDTLS_SSL_RENEGOTIATION)
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
@@ -4795,7 +4795,7 @@
}
if( ssl->handshake != NULL &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ mbedtls_ssl_is_handshake_over( ssl ) == 1 )
{
mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
}
@@ -5219,7 +5219,7 @@
int in_ctr_cmp;
int out_ctr_cmp;
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 ||
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
{
@@ -5397,7 +5397,7 @@
}
#endif
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
ret = mbedtls_ssl_handshake( ssl );
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
@@ -5508,7 +5508,7 @@
/* We're going to return something now, cancel timer,
* except if handshake (renegotiation) is in progress */
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 1 )
mbedtls_ssl_set_timer( ssl, 0 );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -5652,7 +5652,7 @@
}
#endif
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
{
@@ -5683,7 +5683,7 @@
if( ssl->out_left != 0 )
return( mbedtls_ssl_flush_output( ssl ) );
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 1 )
{
if( ( ret = mbedtls_ssl_send_alert_message( ssl,
MBEDTLS_SSL_ALERT_LEVEL_WARNING,
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5c65cc5..dbfb0e3 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -120,7 +120,7 @@
*enabled = MBEDTLS_SSL_CID_DISABLED;
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
- ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -2770,7 +2770,7 @@
if( ssl == NULL ||
ssl->conf == NULL ||
ssl->handshake == NULL ||
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ mbedtls_ssl_is_handshake_over( ssl ) == 1 )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -2853,7 +2853,7 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
/* Main handshake loop */
- while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ while( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
ret = mbedtls_ssl_handshake_step( ssl );
@@ -2953,7 +2953,7 @@
/* On server, just send the request */
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
{
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
@@ -2973,7 +2973,7 @@
*/
if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
{
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 )
@@ -3257,7 +3257,7 @@
* (only DTLS) but are currently used to simplify the implementation.
*/
/* The initial handshake must be over */
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( mbedtls_ssl_is_handshake_over( ssl ) == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index ec50ae5..f71e154 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -1044,7 +1044,7 @@
{
/* If /p second_ssl ends the handshake procedure before /p ssl then
* there is no need to call the next step */
- if( second_ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ if( !mbedtls_ssl_is_handshake_over( second_ssl ) )
{
ret = mbedtls_ssl_handshake_step( second_ssl );
if( ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ &&
@@ -2089,8 +2089,8 @@
goto exit;
}
- TEST_ASSERT( client.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER );
- TEST_ASSERT( server.ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER );
+ TEST_ASSERT( mbedtls_ssl_is_handshake_over( &client.ssl ) == 1 );
+ TEST_ASSERT( mbedtls_ssl_is_handshake_over( &server.ssl ) == 1 );
/* Check that both sides have negotiated the expected version. */
mbedtls_test_set_step( 0 );