From e40e42cf21a3af4732babdaa5ed732733ff640e8 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 10:31:50 +0100 Subject: [PATCH 01/12] Add change log for early data feature Signed-off-by: Ronald Cron --- ChangeLog.d/early-data.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/early-data.txt diff --git a/ChangeLog.d/early-data.txt b/ChangeLog.d/early-data.txt new file mode 100644 index 0000000000..bb4eb45d29 --- /dev/null +++ b/ChangeLog.d/early-data.txt @@ -0,0 +1,4 @@ +Features + * Mbed TLS now supports the writing and reading of TLS 1.3 early data. + Early data is supported when the configuration option + MBEDTLS_SSL_EARLY_DATA is enabled (disabled by default). From 124ed8a775970a8df882f2b9e6eef7200d353ce9 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 10:41:37 +0100 Subject: [PATCH 02/12] tls13-support.md: Some fixes Signed-off-by: Ronald Cron --- docs/architecture/tls13-support.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index 6db0e54c39..33fe76d1a3 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -26,7 +26,7 @@ Support description - Mbed TLS supports ECDHE key establishment. - - Mbed TLS does not support DHE key establishment. + - Mbed TLS supports DHE key establishment. - Mbed TLS supports pre-shared keys for key establishment, pre-shared keys provisioned externally as well as provisioned via the ticket mechanism. @@ -51,7 +51,7 @@ Support description | signature_algorithms | YES | | use_srtp | no | | heartbeat | no | - | apln | YES | + | alpn | YES | | signed_certificate_timestamp | no | | client_certificate_type | no | | server_certificate_type | no | @@ -71,7 +71,8 @@ Support description Potentially all ECDHE groups: secp256r1, x25519, secp384r1, x448 and secp521r1. - Finite field groups (DHE) are not supported. + Potentially all DHE groups: + ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144 and ffdhe8192. - Supported signature algorithms (both for certificates and CertificateVerify): depends on the library configuration. @@ -105,7 +106,7 @@ Support description | Mbed TLS configuration option | Support | | ---------------------------------------- | ------- | - | MBEDTLS_SSL_ALL_ALERT_MESSAGES | no | + | MBEDTLS_SSL_ALL_ALERT_MESSAGES | yes | | MBEDTLS_SSL_ASYNC_PRIVATE | no | | MBEDTLS_SSL_CONTEXT_SERIALIZATION | no | | MBEDTLS_SSL_DEBUG_ALL | no | From 1b606d883575053e80809f7bb7d500afe365c024 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 10:46:21 +0100 Subject: [PATCH 03/12] tls13-support.md: Early data supported now Signed-off-by: Ronald Cron --- docs/architecture/tls13-support.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index 33fe76d1a3..39c676cb1b 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -33,7 +33,7 @@ Support description - Mbed TLS supports session resumption via the ticket mechanism. - - Mbed TLS does not support sending or receiving early data (0-RTT data). + - Mbed TLS supports sending and receiving early data (0-RTT data). - Supported cipher suites: depends on the library configuration. Potentially all of them: @@ -59,7 +59,7 @@ Support description | key_share | YES | | pre_shared_key | YES | | psk_key_exchange_modes | YES | - | early_data | no | + | early_data | YES | | cookie | no | | supported_versions | YES | | certificate_authorities | no | @@ -173,8 +173,6 @@ Prototype upstreaming status The following parts of the TLS 1.3 prototype remain to be upstreamed: -- Sending (client) and receiving (server) early data (0-RTT data). - - New TLS Message Processing Stack (MPS) The TLS 1.3 prototype is developed alongside a rewrite of the TLS messaging layer, From d76a2d8b98836e82bd4d510b09dca586865e107b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 10:49:48 +0100 Subject: [PATCH 04/12] tls13-support.md: Stop referring to the prototype Signed-off-by: Ronald Cron --- docs/architecture/tls13-support.md | 42 ++---------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index 39c676cb1b..95a0ba79a4 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -4,17 +4,8 @@ TLS 1.3 support Overview -------- -Mbed TLS provides a partial implementation of the TLS 1.3 protocol defined in -the "Support description" section below. The TLS 1.3 support enablement -is controlled by the MBEDTLS_SSL_PROTO_TLS1_3 configuration option. - -The development of the TLS 1.3 protocol is based on the TLS 1.3 prototype -located at https://github.com/hannestschofenig/mbedtls. The prototype is -itself based on a version of the development branch that we aim to keep as -recent as possible (ideally the head) by merging regularly commits of the -development branch into the prototype. The section "Prototype upstreaming -status" below describes what remains to be upstreamed. - +Mbed TLS provides an implementation of the TLS 1.3. The TLS 1.3 support +enablement is controlled by the MBEDTLS_SSL_PROTO_TLS1_3 configuration option. Support description ------------------- @@ -168,31 +159,6 @@ Support description TLS 1.3 specification. -Prototype upstreaming status ----------------------------- - -The following parts of the TLS 1.3 prototype remain to be upstreamed: - -- New TLS Message Processing Stack (MPS) - - The TLS 1.3 prototype is developed alongside a rewrite of the TLS messaging layer, - encompassing low-level details such as record parsing, handshake reassembly, and - DTLS retransmission state machine. - - MPS has the following components: - - Layer 1 (Datagram handling) - - Layer 2 (Record handling) - - Layer 3 (Message handling) - - Layer 4 (Retransmission State Machine) - - Reader (Abstracted pointer arithmetic and reassembly logic for incoming data) - - Writer (Abstracted pointer arithmetic and fragmentation logic for outgoing data) - - Of those components, the following have been upstreamed - as part of `MBEDTLS_SSL_PROTO_TLS1_3`: - - - Reader ([`library/mps_reader.h`](../../library/mps_reader.h)) - - Coding rules checklist for TLS 1.3 ---------------------------------- @@ -265,10 +231,6 @@ TLS 1.3 specific coding rules: - the macro to check for data when reading from an input buffer `MBEDTLS_SSL_CHK_BUF_READ_PTR`. - These macros were introduced after the prototype was written thus are - likely not to be used in prototype where we now would use them in - development. - The three first types, MBEDTLS_BYTE_{0-8}, MBEDTLS_PUT_UINT{8|16|32|64}_BE and MBEDTLS_GET_UINT{8|16|32|64}_BE improve the readability of the code and reduce the risk of writing or reading bytes in the wrong order. From b372b2e5bb2949a9e96f7f152a69f9db63862894 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 14:10:58 +0100 Subject: [PATCH 05/12] docs: Move TLS 1.3 early data doc to a dedicated file Signed-off-by: Ronald Cron --- docs/architecture/tls13-support.md | 172 ----------------------------- docs/tls13-early-data.md | 171 ++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 172 deletions(-) create mode 100644 docs/tls13-early-data.md diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index 95a0ba79a4..2ac3950295 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -433,175 +433,3 @@ outbound message on server side as well. * state change: the state change is done in the main state handler to ease the navigation of the state machine transitions. - - -Writing and reading early or 0-RTT data ---------------------------------------- - -An application function to write and send a buffer of data to a server through -TLS may plausibly look like: - -``` -int write_data( mbedtls_ssl_context *ssl, - const unsigned char *data_to_write, - size_t data_to_write_len, - size_t *data_written ) -{ - *data_written = 0; - - while( *data_written < data_to_write_len ) - { - ret = mbedtls_ssl_write( ssl, data_to_write + *data_written, - data_to_write_len - *data_written ); - - if( ret < 0 && - ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); - } - - *data_written += ret; - } - - return( 0 ); -} -``` -where ssl is the SSL context to use, data_to_write the address of the data -buffer and data_to_write_len the number of data bytes. The handshake may -not be completed, not even started for the SSL context ssl when the function is -called and in that case the mbedtls_ssl_write() API takes care transparently of -completing the handshake before to write and send data to the server. The -mbedtls_ssl_write() may not been able to write and send all data in one go thus -the need for a loop calling it as long as there are still data to write and -send. - -An application function to write and send early data and only early data, -data sent during the first flight of client messages while the handshake is in -its initial phase, would look completely similar but the call to -mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write(). -``` -int write_early_data( mbedtls_ssl_context *ssl, - const unsigned char *data_to_write, - size_t data_to_write_len, - size_t *data_written ) -{ - *data_written = 0; - - while( *data_written < data_to_write_len ) - { - ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written, - data_to_write_len - *data_written ); - - if( ret < 0 && - ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); - } - - *data_written += ret; - } - - return( 0 ); -} -``` -Note that compared to write_data(), write_early_data() can also return -MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled -specifically by the user of write_early_data(). A fresh SSL context (typically -just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would -be expected when calling `write_early_data`. - -All together, code to write and send a buffer of data as long as possible as -early data and then as standard post-handshake application data could -plausibly look like: - -``` -ret = write_early_data( ssl, data_to_write, data_to_write_len, - &early_data_written ); -if( ret < 0 && - ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) -{ - goto error; -} - -ret = write_data( ssl, data_to_write + early_data_written, - data_to_write_len - early_data_written, &data_written ); -if( ret < 0 ) - goto error; - -data_written += early_data_written; -``` - -Finally, taking into account that the server may reject early data, application -code to write and send a buffer of data could plausibly look like: -``` -ret = write_early_data( ssl, data_to_write, data_to_write_len, - &early_data_written ); -if( ret < 0 && - ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) -{ - goto error; -} - -/* - * Make sure the handshake is completed as it is a requisite to - * mbedtls_ssl_get_early_data_status(). - */ -while( !mbedtls_ssl_is_handshake_over( ssl ) ) -{ - ret = mbedtls_ssl_handshake( ssl ); - if( ret < 0 && - ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - goto error; - } -} - -ret = mbedtls_ssl_get_early_data_status( ssl ); -if( ret < 0 ) - goto error; - -if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED ) - early_data_written = 0; - -ret = write_data( ssl, data_to_write + early_data_written, - data_to_write_len - early_data_written, &data_written ); -if( ret < 0 ) - goto error; - -data_written += early_data_written; -``` - -Basically, the same holds for reading early data on the server side without the -complication of possible rejection. An application function to read early data -into a given buffer could plausibly look like: -``` -int read_early_data( mbedtls_ssl_context *ssl, - unsigned char *buffer, - size_t buffer_size, - size_t *data_len ) -{ - *data_len = 0; - - while( *data_len < buffer_size ) - { - ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len, - buffer_size - *data_len ); - - if( ret < 0 && - ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); - } - - *data_len += ret; - } - - return( 0 ); -} -``` -with again calls to read_early_data() expected to be done with a fresh SSL -context. diff --git a/docs/tls13-early-data.md b/docs/tls13-early-data.md new file mode 100644 index 0000000000..be05743556 --- /dev/null +++ b/docs/tls13-early-data.md @@ -0,0 +1,171 @@ + +Writing and reading early or 0-RTT data +--------------------------------------- + +An application function to write and send a buffer of data to a server through +TLS may plausibly look like: + +``` +int write_data( mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written ) +{ + *data_written = 0; + + while( *data_written < data_to_write_len ) + { + ret = mbedtls_ssl_write( ssl, data_to_write + *data_written, + data_to_write_len - *data_written ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_written += ret; + } + + return( 0 ); +} +``` +where ssl is the SSL context to use, data_to_write the address of the data +buffer and data_to_write_len the number of data bytes. The handshake may +not be completed, not even started for the SSL context ssl when the function is +called and in that case the mbedtls_ssl_write() API takes care transparently of +completing the handshake before to write and send data to the server. The +mbedtls_ssl_write() may not been able to write and send all data in one go thus +the need for a loop calling it as long as there are still data to write and +send. + +An application function to write and send early data and only early data, +data sent during the first flight of client messages while the handshake is in +its initial phase, would look completely similar but the call to +mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write(). +``` +int write_early_data( mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written ) +{ + *data_written = 0; + + while( *data_written < data_to_write_len ) + { + ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written, + data_to_write_len - *data_written ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_written += ret; + } + + return( 0 ); +} +``` +Note that compared to write_data(), write_early_data() can also return +MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled +specifically by the user of write_early_data(). A fresh SSL context (typically +just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would +be expected when calling `write_early_data`. + +All together, code to write and send a buffer of data as long as possible as +early data and then as standard post-handshake application data could +plausibly look like: + +``` +ret = write_early_data( ssl, data_to_write, data_to_write_len, + &early_data_written ); +if( ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) +{ + goto error; +} + +ret = write_data( ssl, data_to_write + early_data_written, + data_to_write_len - early_data_written, &data_written ); +if( ret < 0 ) + goto error; + +data_written += early_data_written; +``` + +Finally, taking into account that the server may reject early data, application +code to write and send a buffer of data could plausibly look like: +``` +ret = write_early_data( ssl, data_to_write, data_to_write_len, + &early_data_written ); +if( ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) +{ + goto error; +} + +/* + * Make sure the handshake is completed as it is a requisite to + * mbedtls_ssl_get_early_data_status(). + */ +while( !mbedtls_ssl_is_handshake_over( ssl ) ) +{ + ret = mbedtls_ssl_handshake( ssl ); + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + goto error; + } +} + +ret = mbedtls_ssl_get_early_data_status( ssl ); +if( ret < 0 ) + goto error; + +if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED ) + early_data_written = 0; + +ret = write_data( ssl, data_to_write + early_data_written, + data_to_write_len - early_data_written, &data_written ); +if( ret < 0 ) + goto error; + +data_written += early_data_written; +``` + +Basically, the same holds for reading early data on the server side without the +complication of possible rejection. An application function to read early data +into a given buffer could plausibly look like: +``` +int read_early_data( mbedtls_ssl_context *ssl, + unsigned char *buffer, + size_t buffer_size, + size_t *data_len ) +{ + *data_len = 0; + + while( *data_len < buffer_size ) + { + ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len, + buffer_size - *data_len ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_len += ret; + } + + return( 0 ); +} +``` +with again calls to read_early_data() expected to be done with a fresh SSL +context. From 0fce958f17db2d450d23ea49dcb938c75a187f32 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 14:22:19 +0100 Subject: [PATCH 06/12] tls13-early-data.md: Adapt code examples to new coding style Signed-off-by: Ronald Cron --- docs/tls13-early-data.md | 112 +++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/docs/tls13-early-data.md b/docs/tls13-early-data.md index be05743556..28a8cc6c18 100644 --- a/docs/tls13-early-data.md +++ b/docs/tls13-early-data.md @@ -6,29 +6,28 @@ An application function to write and send a buffer of data to a server through TLS may plausibly look like: ``` -int write_data( mbedtls_ssl_context *ssl, - const unsigned char *data_to_write, - size_t data_to_write_len, - size_t *data_written ) +int write_data(mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written) { + int ret; *data_written = 0; - while( *data_written < data_to_write_len ) - { - ret = mbedtls_ssl_write( ssl, data_to_write + *data_written, - data_to_write_len - *data_written ); + while (*data_written < data_to_write_len) { + ret = mbedtls_ssl_write(ssl, data_to_write + *data_written, + data_to_write_len - *data_written); - if( ret < 0 && + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + return ret; } *data_written += ret; } - return( 0 ); + return 0; } ``` where ssl is the SSL context to use, data_to_write the address of the data @@ -36,7 +35,7 @@ buffer and data_to_write_len the number of data bytes. The handshake may not be completed, not even started for the SSL context ssl when the function is called and in that case the mbedtls_ssl_write() API takes care transparently of completing the handshake before to write and send data to the server. The -mbedtls_ssl_write() may not been able to write and send all data in one go thus +mbedtls_ssl_write() may not be able to write and send all data in one go thus the need for a loop calling it as long as there are still data to write and send. @@ -45,29 +44,28 @@ data sent during the first flight of client messages while the handshake is in its initial phase, would look completely similar but the call to mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write(). ``` -int write_early_data( mbedtls_ssl_context *ssl, - const unsigned char *data_to_write, - size_t data_to_write_len, - size_t *data_written ) +int write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written) { + int ret; *data_written = 0; - while( *data_written < data_to_write_len ) - { - ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written, - data_to_write_len - *data_written ); + while (*data_written < data_to_write_len) { + ret = mbedtls_ssl_write_early_data(ssl, data_to_write + *data_written, + data_to_write_len - *data_written); - if( ret < 0 && + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + return ret; } *data_written += ret; } - return( 0 ); + return 0; } ``` Note that compared to write_data(), write_early_data() can also return @@ -81,18 +79,22 @@ early data and then as standard post-handshake application data could plausibly look like: ``` -ret = write_early_data( ssl, data_to_write, data_to_write_len, - &early_data_written ); -if( ret < 0 && - ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) -{ +ret = write_early_data(ssl, + data_to_write, + data_to_write_len, + &early_data_written); +if (ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { goto error; } -ret = write_data( ssl, data_to_write + early_data_written, - data_to_write_len - early_data_written, &data_written ); -if( ret < 0 ) +ret = write_data(ssl, + data_to_write + early_data_written, + data_to_write_len - early_data_written, + &data_written); +if (ret < 0) { goto error; +} data_written += early_data_written; ``` @@ -100,40 +102,44 @@ data_written += early_data_written; Finally, taking into account that the server may reject early data, application code to write and send a buffer of data could plausibly look like: ``` -ret = write_early_data( ssl, data_to_write, data_to_write_len, - &early_data_written ); -if( ret < 0 && - ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) -{ +ret = write_early_data(ssl, + data_to_write, + data_to_write_len, + &early_data_written); +if (ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { goto error; } /* - * Make sure the handshake is completed as it is a requisite to + * Make sure the handshake is completed as it is a requisite of * mbedtls_ssl_get_early_data_status(). */ -while( !mbedtls_ssl_is_handshake_over( ssl ) ) -{ - ret = mbedtls_ssl_handshake( ssl ); - if( ret < 0 && +while (!mbedtls_ssl_is_handshake_over(ssl)) { + ret = mbedtls_ssl_handshake(ssl); + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { goto error; } } -ret = mbedtls_ssl_get_early_data_status( ssl ); -if( ret < 0 ) +ret = mbedtls_ssl_get_early_data_status(ssl); +if (ret < 0) { goto error; +} -if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED ) +if (ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) { early_data_written = 0; +} -ret = write_data( ssl, data_to_write + early_data_written, - data_to_write_len - early_data_written, &data_written ); -if( ret < 0 ) +ret = write_data(ssl, + data_to_write + early_data_written, + data_to_write_len - early_data_written, + &data_written); +if (ret < 0) { goto error; +} data_written += early_data_written; ``` From d514d9c7988c39e04b3a802cd0b1ee4051b6b1c2 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 13 Mar 2024 15:19:38 +0100 Subject: [PATCH 07/12] tls13-early-data.md: Fix reading early data documentation Signed-off-by: Ronald Cron --- docs/tls13-early-data.md | 71 ++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/docs/tls13-early-data.md b/docs/tls13-early-data.md index 28a8cc6c18..4b6f5d305c 100644 --- a/docs/tls13-early-data.md +++ b/docs/tls13-early-data.md @@ -1,6 +1,6 @@ -Writing and reading early or 0-RTT data ---------------------------------------- +Writing early data +------------------ An application function to write and send a buffer of data to a server through TLS may plausibly look like: @@ -144,34 +144,49 @@ if (ret < 0) { data_written += early_data_written; ``` -Basically, the same holds for reading early data on the server side without the -complication of possible rejection. An application function to read early data -into a given buffer could plausibly look like: +Reading early data +------------------ +Mbed TLS provides the mbedtls_ssl_read_early_data() API to read the early data +that a TLS 1.3 server might receive during the TLS 1.3 handshake. + +While establishing a TLS 1.3 connection with a client using a combination +of the mbedtls_ssl_handshake(), mbedtls_ssl_read() and mbedtls_ssl_write() APIs, +the reception of early data is signaled by an API returning the +MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA error code. Early data can then be read +with the mbedtls_ssl_read_early_data() API. + +For example, a typical code to establish a TLS connection, where ssl is the SSL +context to use: ``` -int read_early_data( mbedtls_ssl_context *ssl, - unsigned char *buffer, - size_t buffer_size, - size_t *data_len ) -{ - *data_len = 0; +while ((int ret = mbedtls_ssl_handshake(&ssl)) != 0) { - while( *data_len < buffer_size ) - { - ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len, - buffer_size - *data_len ); - - if( ret < 0 && - ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) - { - return( ret ); - } - - *data_len += ret; + if (ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + break; + } +} +``` +could be adapted to handle early data in the following way: +``` +size_t data_read_len = 0; +while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { + + if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) { + ret = mbedtls_ssl_read_early_data(&ssl, + buffer + data_read_len, + sizeof(buffer) - data_read_len); + if (ret < 0) { + break; + } + data_read_len += ret; + continue; + } + + if (ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + break; } - - return( 0 ); } ``` -with again calls to read_early_data() expected to be done with a fresh SSL -context. From 1987a7c0681f9c307daa4239fdea01963bbd6c28 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 14 Mar 2024 19:05:26 +0100 Subject: [PATCH 08/12] Document that we do not implement the anti-replay defenses Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 39bea79092..3a0800b36d 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5224,6 +5224,11 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); * same warnings apply to any use of the * early_exporter_master_secret. * + * Mbed TLS does not implement one of the anti-replay defenses + * defined in section 8 of the TLS 1.3 specification: + * single-ticket use or ClientHello recording within a given + * time window. + * * \note This function is used in conjunction with * mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), * mbedtls_ssl_read() and mbedtls_ssl_write() to read early From 933aec86fdbc4e1e6bec6de0f5f9463415b91ff2 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 15 Mar 2024 10:43:56 +0100 Subject: [PATCH 09/12] Remove experimental warnings related to early data Signed-off-by: Ronald Cron --- include/mbedtls/mbedtls_config.h | 7 ------- include/mbedtls/ssl.h | 6 ------ 2 files changed, 13 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index feb2054902..60f24105da 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -1854,9 +1854,6 @@ * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3 * is not enabled, this option does not have any effect on the build. * - * This feature is experimental, not completed and thus not ready for - * production. - * * \note The maximum amount of early data can be set with * MBEDTLS_SSL_MAX_EARLY_DATA_SIZE. * @@ -4145,10 +4142,6 @@ * * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not * have any impact on the build. - * - * This feature is experimental, not completed and thus not ready for - * production. - * */ //#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 3a0800b36d..46a624e864 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2097,9 +2097,6 @@ void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode); * MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have * been received. To read the early data, call mbedtls_ssl_read_early_data() * before calling the original function again. - * - * \warning This interface is experimental and may change without notice. - * */ void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, int early_data_enabled); @@ -2125,12 +2122,9 @@ void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, * \param[in] conf The SSL configuration to use. * \param[in] max_early_data_size The maximum amount of 0-RTT data. * - * \warning This interface is experimental and may change without notice. - * * \warning This interface DOES NOT influence/limit the amount of early data * that can be received through previously created and issued tickets, * which clients may have stored. - * */ void mbedtls_ssl_conf_max_early_data_size( mbedtls_ssl_config *conf, uint32_t max_early_data_size); From 582865fbfb970bd043a62caa60ce9d94f43acb71 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 15 Mar 2024 14:48:34 +0100 Subject: [PATCH 10/12] Improve the change log Signed-off-by: Ronald Cron --- ChangeLog.d/early-data.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog.d/early-data.txt b/ChangeLog.d/early-data.txt index bb4eb45d29..3c3826c954 100644 --- a/ChangeLog.d/early-data.txt +++ b/ChangeLog.d/early-data.txt @@ -1,4 +1,5 @@ Features - * Mbed TLS now supports the writing and reading of TLS 1.3 early data. - Early data is supported when the configuration option - MBEDTLS_SSL_EARLY_DATA is enabled (disabled by default). + * Mbed TLS now supports the writing and reading of TLS 1.3 early data (see + docs/tls13-early-data.md). The support enablement is controlled at build + time by the MBEDTLS_SSL_EARLY_DATA configuration option and at runtime by + the mbedtls_ssl_conf_early_data() API (by default disabled in both cases). From 3996ebc037f8d5bdc7d2c35aea65b3d86faee87b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 15 Mar 2024 14:57:05 +0100 Subject: [PATCH 11/12] Fix documentation about anti-replay defenses Signed-off-by: Ronald Cron --- include/mbedtls/ssl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 46a624e864..429127893e 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -5218,10 +5218,10 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); * same warnings apply to any use of the * early_exporter_master_secret. * - * Mbed TLS does not implement one of the anti-replay defenses + * \warning Mbed TLS does not implement any of the anti-replay defenses * defined in section 8 of the TLS 1.3 specification: - * single-ticket use or ClientHello recording within a given - * time window. + * single-use of tickets or ClientHello recording within a + * given time window. * * \note This function is used in conjunction with * mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), From a9bdc8fbb8b26112115b9fd735bd2c1226d52db5 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 15 Mar 2024 15:52:04 +0100 Subject: [PATCH 12/12] Improve tls13-support.md Signed-off-by: Ronald Cron --- docs/architecture/tls13-support.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index 2ac3950295..d6fc19e4a3 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -4,8 +4,8 @@ TLS 1.3 support Overview -------- -Mbed TLS provides an implementation of the TLS 1.3. The TLS 1.3 support -enablement is controlled by the MBEDTLS_SSL_PROTO_TLS1_3 configuration option. +Mbed TLS provides an implementation of the TLS 1.3 protocol. The TLS 1.3 support +may be enabled using the MBEDTLS_SSL_PROTO_TLS1_3 configuration option. Support description -------------------