From d4069247b828fee6423a28811e41e14ad223f768 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 21 Feb 2024 13:45:52 +0100 Subject: [PATCH] Improve comments/documentation Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 32 +++++++++++++++++++++++++--- library/ssl_msg.c | 19 ++++++++++++----- tests/suites/test_suite_ssl.function | 7 ++++-- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 6727419c71..83d2ab8347 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5199,17 +5199,43 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, * \brief Try to write exactly 'len' application data bytes while * performing the handshake (early data). * + * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. + * IMPORTANT NOTE from section 2.3 of the specification: + * + * The security properties for 0-RTT data are weaker than + * those for other kinds of TLS data. Specifically: + * - This data is not forward secret, as it is encrypted + * solely under keys derived using the offered PSK. + * - There are no guarantees of non-replay between connections. + * Protection against replay for ordinary TLS 1.3 1-RTT data + * is provided via the server's Random value, but 0-RTT data + * does not depend on the ServerHello and therefore has + * weaker guarantees. This is especially relevant if the + * data is authenticated either with TLS client + * authentication or inside the application protocol. The + * same warnings apply to any use of the + * early_exporter_master_secret. + * * \note This function behaves mainly as mbedtls_ssl_write(). The * specification of mbedtls_ssl_write() relevant to TLS 1.3 * (thus not the parts specific to (D)TLS1.2) applies to this - * function and the present documentation is restricted to the - * differences with mbedtls_ssl_write(). + * function and the present documentation is mainly restricted + * to the differences with mbedtls_ssl_write(). One noticeable + * difference though is that mbedtls_ssl_write() aims to + * complete the handshake before to write application data + * while mbedtls_ssl_write_early() aims to drive the handshake + * just past the point where it is not possible to send early + * data anymore. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * - * \return One additional specific return value: + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * + * \return One additional specific error code compared to + * mbedtls_ssl_write(): * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. * * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 68f5cf10d6..2a6d4341be 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6087,14 +6087,17 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, } /* - * If we are at the beginning of the handshake, advance the handshake just + * If we are at the beginning of the handshake, the early data status being + * equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just * enough to be able to send early data if possible. That way, we can * guarantee that when starting the handshake with this function we will - * send at least one record of early data. - * Otherwise, resume the handshake and if the handshake sequence stops - * waiting for some message from the server, send early data if we can. + * send at least one record of early data. Note that when the status is + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet + * MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet + * as the early data outbound transform has not been set as we may have to + * first send a dummy CCS in clear. */ - if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || @@ -6112,6 +6115,12 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, } } } else { + /* + * If we are past the point where we can send early data, return + * immediatly. Otherwise, progress the handshake as much as possible to + * not delay it too much. If we reach a point where we can still send + * early data, then we will send some. + */ if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index eb5fc120ed..f6319eeb86 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -4217,8 +4217,11 @@ void tls13_write_early_data(int scenario) TEST_EQUAL(ret, 0); /* - * Run handshakes and test the writing of early data in each possible - * state. + * Run handshakes going one state further in the handshake sequence at each + * loop up to the point where we reach the MBEDTLS_SSL_HANDSHAKE_OVER + * state. For each reached handshake state, check the result of the call + * to mbedtls_ssl_write_early_data() and then restart the handshake from + * scratch (see reset label). */ previous_client_state = MBEDTLS_SSL_HELLO_REQUEST; client_state = MBEDTLS_SSL_HELLO_REQUEST;