diff --git a/ChangeLog.d/alert-getter.txt b/ChangeLog.d/alert-getter.txt new file mode 100644 index 000000000000..2b6afd225d17 --- /dev/null +++ b/ChangeLog.d/alert-getter.txt @@ -0,0 +1,6 @@ +Features + * Add the function mbedtls_ssl_get_alert() which returns the + last received fatal error alert type for a more generic + MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE return value from + mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step() or + mbedtls_ssl_read(). diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 02e527cdf5c7..c9a22007c393 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1722,6 +1722,13 @@ struct mbedtls_ssl_context { int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message on next call to record layer? */ + unsigned char MBEDTLS_PRIVATE(in_alert_recv); /*!< Determines if a fatal alert has + been received. Values: + - \c 0 , no fatal alert received. + - \c 1 , a fatal alert has been received */ + unsigned char MBEDTLS_PRIVATE(in_alert_type); /*!< Type of fatal alert if in_alert_recv + != 0 */ + /* The following three variables indicate if and, if yes, * what kind of alert is pending to be sent. */ @@ -4918,6 +4925,22 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message); + +/** + * \brief Get the received fatal alert + * + * \param ssl SSL context + * + * \return The alert description type (MBEDTLS_SSL_ALERT_MSG_*) if a fatal + * alert has been received or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + * + * \note This function can be used in case mbedtls_ssl_handshake(), + * mbedtls_ssl_handshake_step() or mbedtls_ssl_read() returned + * MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE to get the actual alert + * description type. + */ +int mbedtls_ssl_get_alert(mbedtls_ssl_context *ssl); + /** * \brief Notify the peer that the connection is being closed * diff --git a/library/ssl_msg.c b/library/ssl_msg.c index e1198fa62793..f584489dcecf 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -4932,6 +4932,8 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL) { MBEDTLS_SSL_DEBUG_MSG(1, ("is a fatal alert message (msg %d)", ssl->in_msg[1])); + ssl->in_alert_recv = 1; + ssl->in_alert_type = ssl->in_msg[1]; return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; } @@ -5016,6 +5018,14 @@ int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, return 0; } +int mbedtls_ssl_get_alert(mbedtls_ssl_context *ssl) +{ + if (ssl == NULL || ssl->in_alert_recv != 1) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + return ssl->in_alert_type; +} + int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 550f79de295a..dab7654e30d8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1297,6 +1297,8 @@ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, memset(ssl->in_buf, 0, in_buf_len); } + ssl->in_alert_recv = 0; + ssl->send_alert = 0; /* Reset outgoing message writing */ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index fa61b0f435c1..b05de38509d8 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3364,3 +3364,6 @@ ssl_tls_exporter_rejects_bad_parameters:MBEDTLS_SSL_VERSION_TLS1_3:24:250:10 TLS 1.3 Keying Material Exporter: Handshake not done depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_X509_RSASSA_PSS_SUPPORT ssl_tls_exporter_too_early:MBEDTLS_SSL_VERSION_TLS1_3:1:MBEDTLS_SSL_SERVER_CERTIFICATE + +TLS fatal alert getter +ssl_get_alert_after_fatal diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 5b6500898e2a..d4ff7fea579a 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5936,3 +5936,45 @@ exit: MD_OR_USE_PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +void ssl_get_alert_after_fatal(void) +{ + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + /* prepapre ssl context to test on*/ + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + MD_OR_USE_PSA_INIT(); + + TEST_EQUAL(mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT), 0); + + TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0); + + /* No alert has been received yet */ + TEST_ASSERT(mbedtls_ssl_get_alert(&ssl) == MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + + // prepare input message buffer with fatal alert + ssl.in_msglen = 2; + ssl.in_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl.in_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_FATAL; + ssl.in_msg[1] = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE; + + /* import prepared fatal alert and test getter */ + TEST_ASSERT(mbedtls_ssl_handle_message_type(&ssl) == MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE); + TEST_ASSERT(mbedtls_ssl_get_alert(&ssl) == MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + + /* Reset the session and check that no alert is present*/ + mbedtls_ssl_session_reset_msg_layer(&ssl, 0); + TEST_ASSERT(mbedtls_ssl_get_alert(&ssl) == MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + +exit: + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + USE_PSA_DONE(); +} +/* END_CASE */