Merge pull request #8930 from ronald-cron-arm/tls13-doc-update

TLS 1.3: Documentation update for 3.6 release
diff --git a/ChangeLog.d/early-data.txt b/ChangeLog.d/early-data.txt
new file mode 100644
index 0000000..3c3826c
--- /dev/null
+++ b/ChangeLog.d/early-data.txt
@@ -0,0 +1,5 @@
+Features
+   * 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).
diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md
index 6db0e54..d6fc19e 100644
--- a/docs/architecture/tls13-support.md
+++ b/docs/architecture/tls13-support.md
@@ -4,17 +4,8 @@
 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 protocol. The TLS 1.3 support
+may be enabled using the MBEDTLS_SSL_PROTO_TLS1_3 configuration option.
 
 Support description
 -------------------
@@ -26,14 +17,14 @@
 
   - 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.
 
   - 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:
@@ -51,7 +42,7 @@
   | signature_algorithms         | YES     |
   | use_srtp                     | no      |
   | heartbeat                    | no      |
-  | apln                         | YES     |
+  | alpn                         | YES     |
   | signed_certificate_timestamp | no      |
   | client_certificate_type      | no      |
   | server_certificate_type      | no      |
@@ -59,7 +50,7 @@
   | 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      |
@@ -71,7 +62,8 @@
   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 +97,7 @@
 
   | 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      |
@@ -167,33 +159,6 @@
     TLS 1.3 specification.
 
 
-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,
-  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
 ----------------------------------
 
@@ -266,10 +231,6 @@
     - 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.
@@ -472,175 +433,3 @@
 
 * 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 0000000..4b6f5d3
--- /dev/null
+++ b/docs/tls13-early-data.md
@@ -0,0 +1,192 @@
+
+Writing early 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)
+{
+    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);
+
+        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 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.
+
+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)
+{
+    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);
+
+        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 of
+ * 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;
+```
+
+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:
+```
+while ((int ret = mbedtls_ssl_handshake(&ssl)) != 0) {
+
+    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;
+    }
+}
+```
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 5f550c8..cf6d406 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 57d7bc6..172d469 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -2102,9 +2102,6 @@
  *  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);
@@ -2130,12 +2127,9 @@
  * \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);
@@ -5229,6 +5223,11 @@
  *                   same warnings apply to any use of the
  *                   early_exporter_master_secret.
  *
+ * \warning        Mbed TLS does not implement any of the anti-replay defenses
+ *                 defined in section 8 of the TLS 1.3 specification:
+ *                 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(),
  *                 mbedtls_ssl_read() and mbedtls_ssl_write() to read early