Merge pull request #6720 from yuhaoth/pr/tls13-early-data-receive-0_rtt-and-eoed
TLS 1.3: EarlyData SRV: Write early data extension in EncryptedExtension
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 97ae51c..eac6326 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1892,36 +1892,6 @@
ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
goto cleanup;
}
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA) &&
- (handshake->selected_identity != 0 ||
- handshake->ciphersuite_info->id !=
- ssl->session_negotiate->ciphersuite)) {
- /* RFC8446 4.2.11
- * If the server supplies an "early_data" extension, the
- * client MUST verify that the server's selected_identity
- * is 0. If any other value is returned, the client MUST
- * abort the handshake with an "illegal_parameter" alert.
- *
- * RFC 8446 4.2.10
- * In order to accept early data, the server MUST have accepted a PSK
- * cipher suite and selected the first key offered in the client's
- * "pre_shared_key" extension. In addition, it MUST verify that the
- * following values are the same as those associated with the
- * selected PSK:
- * - The TLS version number
- * - The selected cipher suite
- * - The selected ALPN [RFC7301] protocol, if any
- *
- * We check here that when early data is involved the server
- * selected the cipher suite associated to the pre-shared key
- * as it must have.
- */
- MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
- MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
- return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
- }
-#endif
if (!mbedtls_ssl_conf_tls13_check_kex_modes(
ssl, handshake->key_exchange_mode)) {
@@ -2197,6 +2167,9 @@
int ret;
unsigned char *buf;
size_t buf_len;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+#endif
MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions"));
@@ -2209,8 +2182,37 @@
ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len));
#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (ssl->handshake->received_extensions &
- MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+ /* RFC8446 4.2.11
+ * If the server supplies an "early_data" extension, the
+ * client MUST verify that the server's selected_identity
+ * is 0. If any other value is returned, the client MUST
+ * abort the handshake with an "illegal_parameter" alert.
+ *
+ * RFC 8446 4.2.10
+ * In order to accept early data, the server MUST have accepted a PSK
+ * cipher suite and selected the first key offered in the client's
+ * "pre_shared_key" extension. In addition, it MUST verify that the
+ * following values are the same as those associated with the
+ * selected PSK:
+ * - The TLS version number
+ * - The selected cipher suite
+ * - The selected ALPN [RFC7301] protocol, if any
+ *
+ * We check here that when early data is involved the server
+ * selected the cipher suite associated to the pre-shared key
+ * as it must have.
+ */
+ if (handshake->selected_identity != 0 ||
+ handshake->ciphersuite_info->id !=
+ ssl->session_negotiate->ciphersuite) {
+
+ MBEDTLS_SSL_PEND_FATAL_ALERT(
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+ MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+ return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+ }
+
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
}
#endif
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 954ddff..061dcf7 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -152,6 +152,12 @@
/* We delete the temporary buffer */
mbedtls_free(ticket_buffer);
+ if (ret == 0 && session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+ MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
+ /* TODO: Define new return value for this case. */
+ ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+ }
+
if (ret != 0) {
goto exit;
}
@@ -1784,9 +1790,59 @@
return;
}
- /* We do not accept early data for the time being */
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+ if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1,
+ ("EarlyData: rejected, feature disabled in server configuration."));
+ return;
+ }
+
+ if (!handshake->resume) {
+ /* We currently support early data only in the case of PSKs established
+ via a NewSessionTicket message thus in the case of a session
+ resumption. */
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1, ("EarlyData: rejected, not a session resumption."));
+ return;
+ }
+
+ /* RFC 8446 4.2.10
+ *
+ * In order to accept early data, the server MUST have accepted a PSK cipher
+ * suite and selected the first key offered in the client's "pre_shared_key"
+ * extension. In addition, it MUST verify that the following values are the
+ * same as those associated with the selected PSK:
+ * - The TLS version number
+ * - The selected cipher suite
+ * - The selected ALPN [RFC7301] protocol, if any
+ *
+ * NOTE:
+ * - The TLS version number is checked in
+ * ssl_tls13_offered_psks_check_identity_match_ticket().
+ * - ALPN is not checked for the time being (TODO).
+ */
+
+ if (handshake->selected_identity != 0) {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1, ("EarlyData: rejected, the selected key in "
+ "`pre_shared_key` is not the first one."));
+ return;
+ }
+
+ if (handshake->ciphersuite_info->id !=
+ ssl->session_negotiate->ciphersuite) {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1, ("EarlyData: rejected, the selected ciphersuite is not the one "
+ "of the selected pre-shared key."));
+ return;
+
+ }
+
+
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -2446,6 +2502,16 @@
p += output_len;
#endif /* MBEDTLS_SSL_ALPN */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+ ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &output_len);
+ if (ret != 0) {
+ return ret;
+ }
+ p += output_len;
+ }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
extensions_len = (p - p_extensions_len) - 2;
MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);
diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh
index 27c3453..3816a2b 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -485,6 +485,9 @@
-s "found matched identity" \
-s "key exchange mode: psk_ephemeral"
+EARLY_DATA_INPUT_LEN_BLOCKS=$(( ( $( cat $EARLY_DATA_INPUT | wc -c ) + 31 ) / 32 ))
+EARLY_DATA_INPUT_LEN=$(( $EARLY_DATA_INPUT_LEN_BLOCKS * 32 ))
+
requires_gnutls_next
requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \
MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
@@ -500,3 +503,20 @@
-s "EncryptedExtensions: early_data(42) extension does not exist." \
-s "NewSessionTicket: early_data(42) extension does not exist." \
-s "Last error was: -29056 - SSL - Verification of the message MAC failed"
+
+requires_gnutls_next
+requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \
+ MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 G->m: EarlyData: feature is enabled, fail." \
+ "$P_SRV force_version=tls13 debug_level=4 max_early_data_size=$EARLY_DATA_INPUT_LEN" \
+ "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL:+KX-ALL \
+ -d 10 -r --earlydata $EARLY_DATA_INPUT " \
+ 1 \
+ -s "ClientHello: early_data(42) extension exists." \
+ -s "EncryptedExtensions: early_data(42) extension exists." \
+ -s "NewSessionTicket: early_data(42) extension does not exist." \
+ -s "Last error was: -29056 - SSL - Verification of the message MAC failed"