Merge pull request #6721 from yuhaoth/pr/tls13-early-data-extension-of-nst
TLS 1.3: EarlyData SRV: Write `early_data` extension of NewSessionTicket
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index eae192b..b9801a0 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -2113,6 +2113,7 @@
#if defined(MBEDTLS_SSL_EARLY_DATA)
int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+ int in_new_session_ticket,
unsigned char *buf,
const unsigned char *end,
size_t *out_len);
@@ -2795,6 +2796,13 @@
MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION);
}
+static inline unsigned int mbedtls_ssl_session_ticket_allow_early_data(
+ mbedtls_ssl_session *session)
+{
+ return !mbedtls_ssl_session_check_ticket_flags(session,
+ MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+}
+
static inline void mbedtls_ssl_session_set_ticket_flags(
mbedtls_ssl_session *session, unsigned int flags)
{
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 052df7e..ae11364 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -695,10 +695,8 @@
mbedtls_ssl_session *session = ssl->session_negotiate;
return ssl->handshake->resume &&
session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
- (session->ticket_flags &
- MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) &&
- mbedtls_ssl_tls13_cipher_suite_is_offered(
- ssl, session->ciphersuite);
+ mbedtls_ssl_session_ticket_allow_early_data(session) &&
+ mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite);
}
#endif
@@ -1176,7 +1174,9 @@
if (mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
ssl_tls13_early_data_has_valid_ticket(ssl) &&
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
- ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &ext_len);
+
+ ret = mbedtls_ssl_tls13_write_early_data_ext(
+ ssl, 0, p, end, &ext_len);
if (ret != 0) {
return ret;
}
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index cc77a94..fe2a2eb 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -1402,7 +1402,7 @@
*
* struct {
* select ( Handshake.msg_type ) {
- * ...
+ * case new_session_ticket: uint32 max_early_data_size;
* case client_hello: Empty;
* case encrypted_extensions: Empty;
* };
@@ -1410,20 +1410,37 @@
*/
#if defined(MBEDTLS_SSL_EARLY_DATA)
int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+ int in_new_session_ticket,
unsigned char *buf,
const unsigned char *end,
size_t *out_len)
{
unsigned char *p = buf;
- *out_len = 0;
- ((void) ssl);
- MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+#if defined(MBEDTLS_SSL_SRV_C)
+ const size_t needed = in_new_session_ticket ? 8 : 4;
+#else
+ const size_t needed = 4;
+ ((void) in_new_session_ticket);
+#endif
+
+ *out_len = 0;
+
+ MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed);
MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0);
- MBEDTLS_PUT_UINT16_BE(0, p, 2);
+ MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2);
- *out_len = 4;
+#if defined(MBEDTLS_SSL_SRV_C)
+ if (in_new_session_ticket) {
+ MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4);
+ MBEDTLS_SSL_DEBUG_MSG(
+ 4, ("Sent max_early_data_size=%u",
+ (unsigned int) ssl->conf->max_early_data_size));
+ }
+#endif
+
+ *out_len = needed;
mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA);
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index bfe805f..fe7a674 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1845,6 +1845,13 @@
}
+ if (!mbedtls_ssl_session_ticket_allow_early_data(ssl->session_negotiate)) {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1,
+ ("EarlyData: rejected, early_data not allowed in ticket "
+ "permission bits."));
+ return;
+ }
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
@@ -2517,7 +2524,8 @@
#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);
+ ret = mbedtls_ssl_tls13_write_early_data_ext(
+ ssl, 0, p, end, &output_len);
if (ret != 0) {
return ret;
}
@@ -3129,6 +3137,15 @@
mbedtls_ssl_session_set_ticket_flags(
session, ssl->handshake->tls13_kex_modes);
#endif
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED &&
+ ssl->conf->max_early_data_size > 0) {
+ mbedtls_ssl_session_set_ticket_flags(
+ session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+ }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
/* Generate ticket_age_add */
@@ -3212,12 +3229,13 @@
* The following fields are placed inside the ticket by the
* f_ticket_write() function:
*
- * - creation time (start)
- * - flags (flags)
+ * - creation time (ticket_creation_time)
+ * - flags (ticket_flags)
* - age add (ticket_age_add)
- * - key (key)
- * - key length (key_len)
+ * - key (resumption_key)
+ * - key length (resumption_key_len)
* - ciphersuite (ciphersuite)
+ * - max_early_data_size (max_early_data_size)
*/
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
@@ -3232,6 +3250,7 @@
mbedtls_ssl_session *session = ssl->session;
size_t ticket_len;
uint32_t ticket_lifetime;
+ unsigned char *p_extensions_len;
*out_len = 0;
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg"));
@@ -3293,15 +3312,35 @@
/* Ticket Extensions
*
- * Note: We currently don't have any extensions.
- * Set length to zero.
+ * Extension extensions<0..2^16-2>;
*/
ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
- MBEDTLS_PUT_UINT16_BE(0, p, 0);
+ p_extensions_len = p;
p += 2;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (mbedtls_ssl_session_ticket_allow_early_data(session)) {
+ size_t output_len;
+
+ if ((ret = mbedtls_ssl_tls13_write_early_data_ext(
+ ssl, 1, p, end, &output_len)) != 0) {
+ MBEDTLS_SSL_DEBUG_RET(
+ 1, "mbedtls_ssl_tls13_write_early_data_ext", ret);
+ return ret;
+ }
+ p += output_len;
+ } else {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 4, ("early_data not allowed, "
+ "skip early_data extension in NewSessionTicket"));
+ }
+
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+ MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);
+
*out_len = p - buf;
MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len);
MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket"));
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index c96128b..e6ebd8e 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -556,6 +556,7 @@
USAGE_GROUPS \
USAGE_SIG_ALGS \
USAGE_KEY_OPAQUE_ALGS \
+ USAGE_EARLY_DATA \
"\n"
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh
index e4df1fe..a474203 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -491,22 +491,6 @@
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 \
- 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 disabled, fail." \
- "$P_SRV force_version=tls13 debug_level=4 max_early_data_size=-1" \
- "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL -d 10 -r --earlydata $EARLY_DATA_INPUT" \
- 1 \
- -s "ClientHello: early_data(42) extension exists." \
- -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 \
@@ -518,7 +502,8 @@
"$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL:+KX-ALL \
-d 10 -r --earlydata $EARLY_DATA_INPUT " \
0 \
+ -s "NewSessionTicket: early_data(42) extension exists." \
+ -s "Sent max_early_data_size=$EARLY_DATA_INPUT_LEN" \
-s "ClientHello: early_data(42) extension exists." \
-s "EncryptedExtensions: early_data(42) extension exists." \
- -s "NewSessionTicket: early_data(42) extension does not exist." \
-s "$( tail -1 $EARLY_DATA_INPUT )"