aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbedtls/ssl.h117
-rw-r--r--library/ssl_debug_helpers.h4
-rw-r--r--library/ssl_misc.h77
-rw-r--r--library/ssl_msg.c88
-rw-r--r--library/ssl_tls13_client.c63
-rw-r--r--library/ssl_tls13_generic.c8
-rw-r--r--library/ssl_tls13_server.c15
-rw-r--r--programs/ssl/ssl_client2.c189
-rw-r--r--tests/include/test/ssl_helpers.h4
-rwxr-xr-xtests/opt-testcases/tls13-misc.sh29
-rw-r--r--tests/suites/test_suite_ssl.data27
-rw-r--r--tests/suites/test_suite_ssl.function480
12 files changed, 875 insertions, 226 deletions
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 08c628a..78395d2 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -734,6 +734,51 @@ typedef enum {
}
mbedtls_ssl_states;
+/*
+ * Early data status, client side only.
+ */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+typedef enum {
+/*
+ * The client has not sent the first ClientHello yet, it is unknown if the
+ * client will send an early data indication extension or not.
+ */
+ MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN,
+
+/*
+ * See documentation of mbedtls_ssl_get_early_data_status().
+ */
+ MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT,
+ MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED,
+ MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * is not set and early data cannot be sent yet.
+ */
+ MBEDTLS_SSL_EARLY_DATA_STATUS_SENT,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * has been set and early data can be written now.
+ */
+ MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, the server has accepted them and the client has received the
+ * server Finished message. It cannot send early data to the server anymore.
+ */
+ MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED,
+} mbedtls_ssl_early_data_status;
+
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
+
/**
* \brief Callback type: send data on the network.
*
@@ -1673,33 +1718,29 @@ struct mbedtls_ssl_context {
#endif /* MBEDTLS_SSL_RENEGOTIATION */
/**
- * Maximum TLS version to be negotiated, then negotiated TLS version.
+ * Maximum TLS version to be negotiated, then negotiated TLS version.
*
- * It is initialized as the configured maximum TLS version to be
- * negotiated by mbedtls_ssl_setup().
+ * It is initialized as the configured maximum TLS version to be
+ * negotiated by mbedtls_ssl_setup().
*
- * When renegotiating or resuming a session, it is overwritten in the
- * ClientHello writing preparation stage with the previously negotiated
- * TLS version.
+ * When renegotiating or resuming a session, it is overwritten in the
+ * ClientHello writing preparation stage with the previously negotiated
+ * TLS version.
*
- * On client side, it is updated to the TLS version selected by the server
- * for the handshake when the ServerHello is received.
+ * On client side, it is updated to the TLS version selected by the server
+ * for the handshake when the ServerHello is received.
*
- * On server side, it is updated to the TLS version the server selects for
- * the handshake when the ClientHello is received.
+ * On server side, it is updated to the TLS version the server selects for
+ * the handshake when the ClientHello is received.
*/
mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version);
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
/**
- * Status of the negotiation of the use of early data.
- * See the documentation of mbedtls_ssl_get_early_data_status() for more
- * information.
- *
- * Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT when the context is
- * reset.
+ * Status of the negotiation of the use of early data. Reset to
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is reset.
*/
- int MBEDTLS_PRIVATE(early_data_status);
+ mbedtls_ssl_early_data_status MBEDTLS_PRIVATE(early_data_status);
#endif
unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */
@@ -5150,10 +5191,6 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl);
#if defined(MBEDTLS_SSL_EARLY_DATA)
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 2
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 3
-
#if defined(MBEDTLS_SSL_SRV_C)
/**
* \brief Read at most 'len' bytes of early data
@@ -5206,17 +5243,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
@@ -5237,9 +5300,11 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
* already completed.
*
* It is not possible to write early data for the SSL context
- * \p ssl but this does not preclude for using it with
+ * \p ssl and any subsequent call to this API will return this
+ * error code. But this does not preclude for using it with
* mbedtls_ssl_write(), mbedtls_ssl_read() or
- * mbedtls_ssl_handshake().
+ * mbedtls_ssl_handshake() and the handshake can be
+ * completed by calling one of these APIs.
*
* \note This function may write early data only if the SSL context
* has been configured for the handshake with a PSK for which
diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h
index 2b0e737..a8e3140 100644
--- a/library/ssl_debug_helpers.h
+++ b/library/ssl_debug_helpers.h
@@ -21,6 +21,10 @@
const char *mbedtls_ssl_states_str(mbedtls_ssl_states in);
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);
+#endif
+
const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);
const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in);
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 942d4ad..d8844fc 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -665,21 +665,21 @@ struct mbedtls_ssl_handshake_params {
#if defined(MBEDTLS_SSL_CLI_C)
/** Minimum TLS version to be negotiated.
*
- * It is set up in the ClientHello writing preparation stage and used
- * throughout the ClientHello writing. Not relevant anymore as soon as
- * the protocol version has been negotiated thus as soon as the
- * ServerHello is received.
- * For a fresh handshake not linked to any previous handshake, it is
- * equal to the configured minimum minor version to be negotiated. When
- * renegotiating or resuming a session, it is equal to the previously
- * negotiated minor version.
+ * It is set up in the ClientHello writing preparation stage and used
+ * throughout the ClientHello writing. Not relevant anymore as soon as
+ * the protocol version has been negotiated thus as soon as the
+ * ServerHello is received.
+ * For a fresh handshake not linked to any previous handshake, it is
+ * equal to the configured minimum minor version to be negotiated. When
+ * renegotiating or resuming a session, it is equal to the previously
+ * negotiated minor version.
*
- * There is no maximum TLS version field in this handshake context.
- * From the start of the handshake, we need to define a current protocol
- * version for the record layer which we define as the maximum TLS
- * version to be negotiated. The `tls_version` field of the SSL context is
- * used to store this maximum value until it contains the actual
- * negotiated value.
+ * There is no maximum TLS version field in this handshake context.
+ * From the start of the handshake, we need to define a current protocol
+ * version for the record layer which we define as the maximum TLS
+ * version to be negotiated. The `tls_version` field of the SSL context is
+ * used to store this maximum value until it contains the actual
+ * negotiated value.
*/
mbedtls_ssl_protocol_version min_tls_version;
#endif
@@ -730,16 +730,21 @@ struct mbedtls_ssl_handshake_params {
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
uint8_t key_exchange_mode; /*!< Selected key exchange mode */
- /** Number of HelloRetryRequest messages received/sent from/to the server. */
- uint8_t hello_retry_request_count;
+ /**
+ * Flag indicating if, in the course of the current handshake, an
+ * HelloRetryRequest message has been sent by the server or received by
+ * the client (<> 0) or not (0).
+ */
+ uint8_t hello_retry_request_flag;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/**
- * Number of dummy change_cipher_spec (CCS) record sent. Used to send only
- * one CCS per handshake without having to complicate the handshake state
- * transitions.
+ * Flag indicating if, in the course of the current handshake, a dummy
+ * change_cipher_spec (CCS) record has already been sent. Used to send only
+ * one CCS per handshake while not complicating the handshake state
+ * transitions for that purpose.
*/
- uint8_t ccs_count;
+ uint8_t ccs_sent;
#endif
#if defined(MBEDTLS_SSL_SRV_C)
@@ -2145,38 +2150,6 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
size_t *out_len);
-
-#if defined(MBEDTLS_SSL_CLI_C)
-/*
- * The client has not sent the first ClientHello yet, it is unknown if the
- * client will send an early data indication extension or not.
- */
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, it has not received the response (ServerHello or
- * HelloRetryRequest) from the server yet. The transform to protect early data
- * is not set and early data cannot be sent yet.
- */
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_SENT 4
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, it has not received the response (ServerHello or
- * HelloRetryRequest) from the server yet. The transform to protect early data
- * has been set and early data can be written now.
- */
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE 5
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, the server has accepted them and the client has received the
- * server Finished message. It cannot send early data to the server anymore.
- */
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED 6
-#endif /* MBEDTLS_SSL_CLI_C */
-
#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index c2e64c6..2a6d434 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -6058,6 +6058,94 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t
return ret;
}
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
+ const unsigned char *buf, size_t len)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const struct mbedtls_ssl_config *conf;
+ int written_data_len = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));
+
+ if (ssl == NULL || (conf = ssl->conf) == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) ||
+ (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+ (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ /*
+ * 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. 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) ||
+ (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
+ ret = mbedtls_ssl_handshake_step(ssl);
+ if (ret != 0) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
+ return ret;
+ }
+
+ ret = mbedtls_ssl_flush_output(ssl);
+ if (ret != 0) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
+ return ret;
+ }
+ }
+ } 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;
+ }
+
+ ret = mbedtls_ssl_handshake(ssl);
+ if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+ return ret;
+ }
+ }
+
+ 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;
+ }
+
+ written_data_len = ssl_write_real(ssl, buf, len);
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len));
+
+ return written_data_len;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
+
/*
* Notify the peer that the connection is being closed
*/
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 1e8df1b..88d6c9e 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1180,7 +1180,15 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
#endif
#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (ssl->handshake->hello_retry_request_count == 0) {
+ /* In the first ClientHello, write the early data indication extension if
+ * necessary and update the early data status.
+ * If an HRR has been received and thus we are currently writing the
+ * second ClientHello, the second ClientHello must not contain an early
+ * data extension and the early data status must stay as it is:
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED.
+ */
+ if (!ssl->handshake->hello_retry_request_flag) {
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
ssl_tls13_early_data_has_valid_ticket(ssl) &&
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
@@ -1495,7 +1503,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
* to a HelloRetryRequest), it MUST abort the handshake with an
* "unexpected_message" alert.
*/
- if (handshake->hello_retry_request_count > 0) {
+ if (handshake->hello_retry_request_flag) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received"));
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
@@ -1517,7 +1525,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
- handshake->hello_retry_request_count++;
+ handshake->hello_retry_request_flag = 1;
break;
}
@@ -1672,7 +1680,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,
* proposed in the HRR, we abort the handshake and send an
* "illegal_parameter" alert.
*/
- else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) &&
+ else if ((!is_hrr) && handshake->hello_retry_request_flag &&
(cipher_suite != ssl->session_negotiate->ciphersuite)) {
fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
}
@@ -2270,6 +2278,7 @@ cleanup:
}
+#if defined(MBEDTLS_SSL_EARLY_DATA)
/*
* Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
*
@@ -2308,6 +2317,32 @@ cleanup:
return ret;
}
+int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl)
+{
+ if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) ||
+ (!mbedtls_ssl_is_handshake_over(ssl))) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ switch (ssl->early_data_status) {
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+ break;
+
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+ break;
+
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+ break;
+
+ default:
+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ }
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* STATE HANDLING: CertificateRequest
@@ -3030,9 +3065,11 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
ret = ssl_tls13_process_server_finished(ssl);
break;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
case MBEDTLS_SSL_END_OF_EARLY_DATA:
ret = ssl_tls13_write_end_of_early_data(ssl);
break;
+#endif
case MBEDTLS_SSL_CLIENT_CERTIFICATE:
ret = ssl_tls13_write_client_certificate(ssl);
@@ -3061,23 +3098,17 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
*/
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
- ret = 0;
- if (ssl->handshake->ccs_count == 0) {
- ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret != 0) {
- break;
- }
+ ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+ if (ret != 0) {
+ break;
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
break;
case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
- ret = 0;
- if (ssl->handshake->ccs_count == 0) {
- ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret != 0) {
- break;
- }
+ ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+ if (ret != 0) {
+ break;
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
break;
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 064f616..bc73704 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -1379,6 +1379,12 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec"));
+ /* Only one CCS to send. */
+ if (ssl->handshake->ccs_sent) {
+ ret = 0;
+ goto cleanup;
+ }
+
/* Write CCS message */
MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(
ssl, ssl->out_msg,
@@ -1390,7 +1396,7 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
/* Dispatch message */
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));
- ssl->handshake->ccs_count++;
+ ssl->handshake->ccs_sent = 1;
cleanup:
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 1411446..3a968aa 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1531,7 +1531,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
const unsigned char *extension_data_end;
uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH;
- if (ssl->handshake->hello_retry_request_count > 0) {
+ if (ssl->handshake->hello_retry_request_flag) {
/* Do not accept early data extension in 2nd ClientHello */
allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA);
}
@@ -2427,7 +2427,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if (ssl->handshake->hello_retry_request_count > 0) {
+ if (ssl->handshake->hello_retry_request_flag) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs"));
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
@@ -2474,7 +2474,7 @@ static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl)
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,
msg_len));
- ssl->handshake->hello_retry_request_count++;
+ ssl->handshake->hello_retry_request_flag = 1;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* The server sends a dummy change_cipher_spec record immediately
@@ -3477,12 +3477,9 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
break;
case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
- ret = 0;
- if (ssl->handshake->ccs_count == 0) {
- ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret != 0) {
- break;
- }
+ ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+ if (ret != 0) {
+ break;
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
break;
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 05bb2ff..8a9aff9 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -52,7 +52,7 @@ int main(void)
#define DFL_KEY_OPAQUE 0
#define DFL_KEY_PWD ""
#define DFL_PSK ""
-#define DFL_EARLY_DATA ""
+#define DFL_EARLY_DATA -1
#define DFL_PSK_OPAQUE 0
#define DFL_PSK_IDENTITY "Client_identity"
#define DFL_ECJPAKE_PW NULL
@@ -347,9 +347,8 @@ int main(void)
#if defined(MBEDTLS_SSL_EARLY_DATA)
#define USAGE_EARLY_DATA \
- " early_data=%%s The file path to read early data from\n" \
- " default: \"\" (do nothing)\n" \
- " option: a file path\n"
+ " early_data=%%d default: library default\n" \
+ " options: 0 (disabled), 1 (enabled)\n"
#else
#define USAGE_EARLY_DATA ""
#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_PROTO_TLS1_3 */
@@ -544,7 +543,7 @@ struct options {
int reproducible; /* make communication reproducible */
int skip_close_notify; /* skip sending the close_notify alert */
#if defined(MBEDTLS_SSL_EARLY_DATA)
- const char *early_data; /* the path of the file to read early data from */
+ int early_data; /* early data enablement flag */
#endif
int query_config_mode; /* whether to read config */
int use_srtp; /* Support SRTP */
@@ -717,9 +716,64 @@ exit:
return ret;
}
+/*
+ * Build HTTP request
+ */
+static int build_http_request(unsigned char *buf, size_t buf_size, size_t *request_len)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len, tail_len, request_size;
+
+ ret = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page);
+ if (ret < 0) {
+ return ret;
+ }
+
+ len = (size_t) ret;
+ tail_len = strlen(GET_REQUEST_END);
+ if (opt.request_size != DFL_REQUEST_SIZE) {
+ request_size = (size_t) opt.request_size;
+ } else {
+ request_size = len + tail_len;
+ }
+
+ if (request_size > buf_size) {
+ return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+ }
+
+ /* Add padding to GET request to reach opt.request_size in length */
+ if (opt.request_size != DFL_REQUEST_SIZE &&
+ len + tail_len < request_size) {
+ memset(buf + len, 'A', request_size - len - tail_len);
+ len = request_size - tail_len;
+ }
+
+ strncpy((char *) buf + len, GET_REQUEST_END, buf_size - len);
+ len += tail_len;
+
+ /* Truncate if request size is smaller than the "natural" size */
+ if (opt.request_size != DFL_REQUEST_SIZE &&
+ len > request_size) {
+ len = request_size;
+
+ /* Still end with \r\n unless that's really not possible */
+ if (len >= 2) {
+ buf[len - 2] = '\r';
+ }
+ if (len >= 1) {
+ buf[len - 1] = '\n';
+ }
+ }
+
+ *request_len = len;
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
- int ret = 0, len, tail_len, i, written, frags, retry_left;
+ int ret = 0, i;
+ size_t len, written, frags, retry_left;
int query_config_ret = 0;
mbedtls_net_context server_fd;
io_ctx_t io_ctx;
@@ -742,10 +796,6 @@ int main(int argc, char *argv[])
size_t cid_renego_len = 0;
#endif
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- FILE *early_data_fp = NULL;
-#endif /* MBEDTLS_SSL_EARLY_DATA */
-
#if defined(MBEDTLS_SSL_ALPN)
const char *alpn_list[ALPN_LIST_SIZE];
#endif
@@ -1201,7 +1251,15 @@ usage:
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#if defined(MBEDTLS_SSL_EARLY_DATA)
else if (strcmp(p, "early_data") == 0) {
- opt.early_data = q;
+ switch (atoi(q)) {
+ case 0:
+ opt.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+ break;
+ case 1:
+ opt.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+ break;
+ default: goto usage;
+ }
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -1968,16 +2026,9 @@ usage:
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
- int early_data_enabled = MBEDTLS_SSL_EARLY_DATA_DISABLED;
- if (strlen(opt.early_data) > 0) {
- if ((early_data_fp = fopen(opt.early_data, "rb")) == NULL) {
- mbedtls_printf("failed\n ! Cannot open '%s' for reading.\n",
- opt.early_data);
- goto exit;
- }
- early_data_enabled = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+ if (opt.early_data != DFL_EARLY_DATA) {
+ mbedtls_ssl_conf_early_data(&conf, opt.early_data);
}
- mbedtls_ssl_conf_early_data(&conf, early_data_enabled);
#endif /* MBEDTLS_SSL_EARLY_DATA */
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
@@ -2448,32 +2499,9 @@ send_request:
mbedtls_printf(" > Write to server:");
fflush(stdout);
- len = mbedtls_snprintf((char *) buf, sizeof(buf) - 1, GET_REQUEST,
- opt.request_page);
- tail_len = (int) strlen(GET_REQUEST_END);
-
- /* Add padding to GET request to reach opt.request_size in length */
- if (opt.request_size != DFL_REQUEST_SIZE &&
- len + tail_len < opt.request_size) {
- memset(buf + len, 'A', opt.request_size - len - tail_len);
- len += opt.request_size - len - tail_len;
- }
-
- strncpy((char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1);
- len += tail_len;
-
- /* Truncate if request size is smaller than the "natural" size */
- if (opt.request_size != DFL_REQUEST_SIZE &&
- len > opt.request_size) {
- len = opt.request_size;
-
- /* Still end with \r\n unless that's really not possible */
- if (len >= 2) {
- buf[len - 2] = '\r';
- }
- if (len >= 1) {
- buf[len - 1] = '\n';
- }
+ ret = build_http_request(buf, sizeof(buf) - 1, &len);
+ if (ret != 0) {
+ goto exit;
}
if (opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM) {
@@ -2545,8 +2573,11 @@ send_request:
}
buf[written] = '\0';
- mbedtls_printf(" %d bytes written in %d fragments\n\n%s\n",
- written, frags, (char *) buf);
+ mbedtls_printf(
+ " %" MBEDTLS_PRINTF_SIZET " bytes written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n",
+ written,
+ frags,
+ (char *) buf);
/* Send a non-empty request if request_size == 0 */
if (len == 0) {
@@ -2653,7 +2684,9 @@ send_request:
len = ret;
buf[len] = '\0';
- mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf);
+ mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s",
+ len,
+ (char *) buf);
fflush(stdout);
/* End of message should be detected according to the syntax of the
* application protocol (eg HTTP), just use a dummy test here. */
@@ -2712,7 +2745,9 @@ send_request:
len = ret;
buf[len] = '\0';
- mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf);
+ mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s",
+ len,
+ (char *) buf);
ret = 0;
}
@@ -3002,6 +3037,54 @@ reconnect:
goto exit;
}
+ ret = build_http_request(buf, sizeof(buf) - 1, &len);
+ if (ret != 0) {
+ goto exit;
+ }
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (ssl.conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+ frags = 0;
+ written = 0;
+ do {
+ while ((ret = mbedtls_ssl_write_early_data(&ssl, buf + written,
+ len - written)) < 0) {
+ if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) {
+ goto end_of_early_data;
+ }
+ if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
+ ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
+ ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
+ mbedtls_printf(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n",
+ (unsigned int) -ret);
+ goto exit;
+ }
+
+ /* For event-driven IO, wait for socket to become available */
+ if (opt.event == 1 /* level triggered IO */) {
+#if defined(MBEDTLS_TIMING_C)
+ idle(&server_fd, &timer, ret);
+#else
+ idle(&server_fd, ret);
+#endif
+ }
+ }
+
+ frags++;
+ written += ret;
+ } while (written < len);
+ }
+
+end_of_early_data:
+
+ buf[written] = '\0';
+ mbedtls_printf(
+ " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n",
+ written,
+ frags,
+ (char *) buf);
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
@@ -3035,12 +3118,6 @@ exit:
mbedtls_ssl_config_free(&conf);
mbedtls_ssl_session_free(&saved_session);
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (early_data_fp != NULL) {
- fclose(early_data_fp);
- }
-#endif
-
if (session_data != NULL) {
mbedtls_platform_zeroize(session_data, session_data_len);
}
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
index 9a078f6..5b071f7 100644
--- a/tests/include/test/ssl_helpers.h
+++ b/tests/include/test/ssl_helpers.h
@@ -608,9 +608,7 @@ int mbedtls_test_get_tls13_ticket(
mbedtls_test_handshake_test_options *client_options,
mbedtls_test_handshake_test_options *server_options,
mbedtls_ssl_session *session);
-#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C &&
- MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS &&
- MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+#endif
#define ECJPAKE_TEST_PWD "bla"
diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh
index 4e6bf87..ad062dc 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -263,7 +263,7 @@ requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_
run_test "TLS 1.3 m->G: EarlyData: basic check, good" \
"$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK \
--earlydata --maxearlydata 16384 --disable-client-cert" \
- "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1 reco_delay=900" \
+ "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \
0 \
-c "received max_early_data_size: 16384" \
-c "Reconnecting with saved session" \
@@ -285,9 +285,34 @@ requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
MBEDTLS_SSL_EARLY_DATA
requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test "TLS 1.3 m->G: EarlyData: write early data, good" \
+ "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --earlydata --disable-client-cert" \
+ "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \
+ 0 \
+ -c "Reconnecting with saved session" \
+ -c "NewSessionTicket: early_data(42) extension received." \
+ -c "ClientHello: early_data(42) extension exists." \
+ -c "EncryptedExtensions: early_data(42) extension received." \
+ -c "EncryptedExtensions: early_data(42) extension exists." \
+ -c "<= write early_data" \
+ -c "<= write EndOfEarlyData" \
+ -s "Parsing extension 'Early Data/42' (0 bytes)" \
+ -s "Sending extension Early Data/42 (0 bytes)" \
+ -s "END OF EARLY DATA (5) was received." \
+ -s "early data accepted" \
+ -s "decrypted early data with length"
+
+requires_gnutls_tls1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_EARLY_DATA
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
run_test "TLS 1.3 m->G: EarlyData: no early_data in NewSessionTicket, good" \
"$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --disable-client-cert" \
- "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1" \
+ "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1" \
0 \
-c "Reconnecting with saved session" \
-C "NewSessionTicket: early_data(42) extension received." \
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 69ccf26..385682a 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3274,14 +3274,17 @@ elliptic_curve_get_properties
TLS 1.3 resume session with ticket
tls13_resume_session_with_ticket
-TLS 1.3 early data, early data accepted
-tls13_early_data:TEST_EARLY_DATA_ACCEPTED
+TLS 1.3 read early data, early data accepted
+tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED
-TLS 1.3 early data, server rejects early data
-tls13_early_data:TEST_EARLY_DATA_SERVER_REJECTS
+TLS 1.3 read early data, no early data indication
+tls13_read_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT
-TLS 1.3 early data, discard after HRR
-tls13_early_data:TEST_EARLY_DATA_HRR
+TLS 1.3 read early data, server rejects early data
+tls13_read_early_data:TEST_EARLY_DATA_SERVER_REJECTS
+
+TLS 1.3 read early data, discard after HRR
+tls13_read_early_data:TEST_EARLY_DATA_HRR
TLS 1.3 cli, early data status, early data accepted
tls13_cli_early_data_status:TEST_EARLY_DATA_ACCEPTED
@@ -3294,3 +3297,15 @@ tls13_cli_early_data_status:TEST_EARLY_DATA_SERVER_REJECTS
TLS 1.3 cli, early data status, hello retry request
tls13_cli_early_data_status:TEST_EARLY_DATA_HRR
+
+TLS 1.3 write early data, early data accepted
+tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED
+
+TLS 1.3 write early data, no early data indication
+tls13_write_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT
+
+TLS 1.3 write early data, server rejects early data
+tls13_write_early_data:TEST_EARLY_DATA_SERVER_REJECTS
+
+TLS 1.3 write early data, hello retry request
+tls13_write_early_data:TEST_EARLY_DATA_HRR
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 0e798f4..d327828 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -18,49 +18,6 @@
#define TEST_EARLY_DATA_SERVER_REJECTS 2
#define TEST_EARLY_DATA_HRR 3
-#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
- defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \
- defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \
- defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \
- defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \
- defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) && \
- defined(MBEDTLS_MD_CAN_SHA256) && \
- defined(MBEDTLS_ECP_HAVE_SECP256R1) && defined(MBEDTLS_ECP_HAVE_SECP384R1) && \
- defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-/*
- * The implementation of the function should be based on
- * mbedtls_ssl_write_early_data() eventually. The current version aims at
- * removing the dependency on mbedtls_ssl_write_early_data() for the
- * development and testing of reading early data.
- */
-static int write_early_data(mbedtls_ssl_context *ssl,
- unsigned char *buf, size_t len)
-{
- int ret = mbedtls_ssl_get_max_out_record_payload(ssl);
-
- TEST_ASSERT(ret > 0);
- TEST_ASSERT(len <= (size_t) ret);
-
- ret = mbedtls_ssl_flush_output(ssl);
- TEST_EQUAL(ret, 0);
- TEST_EQUAL(ssl->out_left, 0);
-
- ssl->out_msglen = len;
- ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
- if (len > 0) {
- memcpy(ssl->out_msg, buf, len);
- }
-
- ret = mbedtls_ssl_write_record(ssl, 1);
- TEST_EQUAL(ret, 0);
-
- ret = len;
-
-exit:
- return ret;
-}
-#endif
-
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -3624,12 +3581,12 @@ exit:
/* END_CASE */
/*
- * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_early_data() below is
+ * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_read_early_data() below is
* a temporary workaround to not run the test in Windows-2013 where there is
* an issue with mbedtls_vsnprintf().
*/
/* BEGIN_CASE depends_on:!MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
-void tls13_early_data(int scenario)
+void tls13_read_early_data(int scenario)
{
int ret = -1;
unsigned char buf[64];
@@ -3676,6 +3633,10 @@ void tls13_early_data(int scenario)
case TEST_EARLY_DATA_ACCEPTED:
break;
+ case TEST_EARLY_DATA_NO_INDICATION_SENT:
+ client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+ break;
+
case TEST_EARLY_DATA_SERVER_REJECTS:
mbedtls_debug_set_threshold(3);
server_pattern.pattern =
@@ -3723,12 +3684,16 @@ void tls13_early_data(int scenario)
&(client_ep.ssl), &(server_ep.ssl),
MBEDTLS_SSL_SERVER_HELLO), 0);
- TEST_ASSERT(client_ep.ssl.early_data_status !=
- MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+ ret = mbedtls_ssl_write_early_data(&(client_ep.ssl),
+ (unsigned char *) early_data,
+ early_data_len);
- ret = write_early_data(&(client_ep.ssl), (unsigned char *) early_data,
- early_data_len);
- TEST_EQUAL(ret, early_data_len);
+ if (client_ep.ssl.early_data_status !=
+ MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
+ TEST_EQUAL(ret, early_data_len);
+ } else {
+ TEST_EQUAL(ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ }
ret = mbedtls_test_move_handshake_to_state(
&(server_ep.ssl), &(client_ep.ssl),
@@ -3743,12 +3708,20 @@ void tls13_early_data(int scenario)
TEST_MEMORY_COMPARE(buf, early_data_len, early_data, early_data_len);
break;
+ case TEST_EARLY_DATA_NO_INDICATION_SENT:
+ TEST_EQUAL(ret, 0);
+ TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0);
+ break;
+
case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
case TEST_EARLY_DATA_HRR:
TEST_EQUAL(ret, 0);
TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0);
TEST_EQUAL(server_pattern.counter, 1);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
TEST_EQUAL(mbedtls_test_move_handshake_to_state(
@@ -3869,6 +3842,11 @@ void tls13_cli_early_data_status(int scenario)
(ret == MBEDTLS_ERR_SSL_WANT_WRITE));
}
+ if (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+ TEST_EQUAL(mbedtls_ssl_get_early_data_status(&(client_ep.ssl)),
+ MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
+ }
+
switch (client_ep.ssl.state) {
case MBEDTLS_SSL_CLIENT_HELLO:
switch (scenario) {
@@ -3880,7 +3858,7 @@ void tls13_cli_early_data_status(int scenario)
break;
case TEST_EARLY_DATA_HRR:
- if (client_ep.ssl.handshake->hello_retry_request_count == 0) {
+ if (!client_ep.ssl.handshake->hello_retry_request_flag) {
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN);
} else {
@@ -3888,6 +3866,9 @@ void tls13_cli_early_data_status(int scenario)
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
}
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3905,7 +3886,7 @@ void tls13_cli_early_data_status(int scenario)
break;
case TEST_EARLY_DATA_HRR:
- if (client_ep.ssl.handshake->hello_retry_request_count == 0) {
+ if (!client_ep.ssl.handshake->hello_retry_request_flag) {
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE);
} else {
@@ -3913,6 +3894,9 @@ void tls13_cli_early_data_status(int scenario)
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
}
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3933,6 +3917,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3953,6 +3940,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3979,6 +3969,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3999,12 +3992,14 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
- TEST_ASSERT(scenario != TEST_EARLY_DATA_NO_INDICATION_SENT);
switch (scenario) {
case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
@@ -4012,6 +4007,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_SENT);
break;
+
+ default:
+ TEST_FAIL("Unexpected or unknown scenario.");
}
break;
@@ -4022,7 +4020,6 @@ void tls13_cli_early_data_status(int scenario)
break;
case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
- TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED);
switch (scenario) {
case TEST_EARLY_DATA_NO_INDICATION_SENT:
TEST_EQUAL(client_ep.ssl.early_data_status,
@@ -4034,6 +4031,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unexpected or unknown scenario.");
}
break;
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
@@ -4057,6 +4057,9 @@ void tls13_cli_early_data_status(int scenario)
TEST_EQUAL(client_ep.ssl.early_data_status,
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -4065,8 +4068,30 @@ void tls13_cli_early_data_status(int scenario)
}
} while (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER);
+ ret = mbedtls_ssl_get_early_data_status(&(client_ep.ssl));
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED:
+ TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED);
+ break;
+
+ case TEST_EARLY_DATA_NO_INDICATION_SENT:
+ TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+ break;
+
+ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+
+ ret = mbedtls_ssl_get_early_data_status(&(server_ep.ssl));
+ TEST_EQUAL(ret, MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
+
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
- TEST_EQUAL(client_ep.ssl.handshake->ccs_count, 1);
+ TEST_EQUAL(client_ep.ssl.handshake->ccs_sent, 1);
#endif
exit:
@@ -4078,3 +4103,348 @@ exit:
PSA_DONE();
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
+void tls13_write_early_data(int scenario)
+{
+ int ret = -1;
+ mbedtls_test_ssl_endpoint client_ep, server_ep;
+ mbedtls_test_handshake_test_options client_options;
+ mbedtls_test_handshake_test_options server_options;
+ mbedtls_ssl_session saved_session;
+ uint16_t group_list[3] = {
+ MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
+ MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+ MBEDTLS_SSL_IANA_TLS_GROUP_NONE
+ };
+ int beyond_first_hello = 0;
+
+ mbedtls_platform_zeroize(&client_ep, sizeof(client_ep));
+ mbedtls_platform_zeroize(&server_ep, sizeof(server_ep));
+ mbedtls_test_init_handshake_options(&client_options);
+ mbedtls_test_init_handshake_options(&server_options);
+ mbedtls_ssl_session_init(&saved_session);
+
+ PSA_INIT();
+
+ /*
+ * Run first handshake to get a ticket from the server.
+ */
+ client_options.pk_alg = MBEDTLS_PK_ECDSA;
+ client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+ server_options.pk_alg = MBEDTLS_PK_ECDSA;
+ server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+ if (scenario == TEST_EARLY_DATA_HRR) {
+ client_options.group_list = group_list;
+ server_options.group_list = group_list;
+ }
+
+ ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options,
+ &saved_session);
+ TEST_EQUAL(ret, 0);
+
+ /*
+ * Prepare for handshake with the ticket.
+ */
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED:
+ break;
+
+ case TEST_EARLY_DATA_NO_INDICATION_SENT:
+ client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+ break;
+
+ case TEST_EARLY_DATA_SERVER_REJECTS:
+ server_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+ break;
+
+ case TEST_EARLY_DATA_HRR:
+ server_options.group_list = group_list + 1;
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+
+ ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
+ &client_options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
+ &server_options, NULL, NULL, NULL);
+ TEST_EQUAL(ret, 0);
+
+ mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf,
+ mbedtls_test_ticket_write,
+ mbedtls_test_ticket_parse,
+ NULL);
+
+ ret = mbedtls_test_mock_socket_connect(&(client_ep.socket),
+ &(server_ep.socket), 1024);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session);
+ TEST_EQUAL(ret, 0);
+
+ /*
+ * 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(), make sure we can complete the
+ * handshake successfully and then reset the connection to restart the
+ * handshake from scratch.
+ */
+ do {
+ int client_state = client_ep.ssl.state;
+ int previous_client_state;
+ const char *early_data_string = "This is early data.";
+ const unsigned char *early_data = (const unsigned char *) early_data_string;
+ size_t early_data_len = strlen(early_data_string);
+ int write_early_data_ret, read_early_data_ret;
+ unsigned char read_buf[64];
+
+ write_early_data_ret = mbedtls_ssl_write_early_data(&(client_ep.ssl),
+ early_data,
+ early_data_len);
+
+ if (scenario == TEST_EARLY_DATA_NO_INDICATION_SENT) {
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, client_state);
+ goto complete_handshake;
+ }
+
+ switch (client_state) {
+ case MBEDTLS_SSL_HELLO_REQUEST: /* Intentional fallthrough */
+ case MBEDTLS_SSL_CLIENT_HELLO:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_SERVER_REJECTS:
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ break;
+
+ case TEST_EARLY_DATA_HRR:
+ if (!client_ep.ssl.handshake->hello_retry_request_flag) {
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ } else {
+ beyond_first_hello = 1;
+ TEST_EQUAL(write_early_data_ret,
+ MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO);
+ }
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ case MBEDTLS_SSL_SERVER_HELLO:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_SERVER_REJECTS:
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ break;
+
+ case TEST_EARLY_DATA_HRR:
+ if (!client_ep.ssl.handshake->hello_retry_request_flag) {
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ } else {
+ TEST_EQUAL(write_early_data_ret,
+ MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ }
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_SERVER_REJECTS:
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+ break;
+
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ case MBEDTLS_SSL_SERVER_FINISHED:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED:
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED);
+ break;
+
+ case TEST_EARLY_DATA_SERVER_REJECTS:
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED);
+ break;
+
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED);
+ break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ case MBEDTLS_SSL_END_OF_EARLY_DATA:
+ TEST_EQUAL(scenario, TEST_EARLY_DATA_ACCEPTED);
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_END_OF_EARLY_DATA);
+ break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+ case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(write_early_data_ret, early_data_len);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO);
+ break;
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
+ TEST_EQUAL(scenario, TEST_EARLY_DATA_HRR);
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO);
+ break;
+
+ case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
+ switch (scenario) {
+ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(write_early_data_ret,
+ MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state,
+ MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED);
+ break;
+ default:
+ TEST_FAIL("Unexpected or unknown scenario.");
+ }
+ break;
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+ case MBEDTLS_SSL_CLIENT_CERTIFICATE: /* Intentional fallthrough */
+ case MBEDTLS_SSL_CLIENT_FINISHED: /* Intentional fallthrough */
+ case MBEDTLS_SSL_FLUSH_BUFFERS: /* Intentional fallthrough */
+ case MBEDTLS_SSL_HANDSHAKE_WRAPUP: /* Intentional fallthrough */
+ case MBEDTLS_SSL_HANDSHAKE_OVER:
+ switch (scenario) {
+ case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
+ case TEST_EARLY_DATA_HRR:
+ TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+ TEST_EQUAL(client_ep.ssl.state, client_state);
+ break;
+ default:
+ TEST_FAIL("Unknown scenario.");
+ }
+ break;
+
+ default:
+ TEST_FAIL("Unexpected state.");
+ }
+
+complete_handshake:
+ do {
+ ret = mbedtls_test_move_handshake_to_state(
+ &(server_ep.ssl), &(client_ep.ssl),
+ MBEDTLS_SSL_HANDSHAKE_OVER);
+
+ if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) {
+ read_early_data_ret = mbedtls_ssl_read_early_data(
+ &(server_ep.ssl), read_buf, sizeof(read_buf));
+
+ TEST_EQUAL(read_early_data_ret, early_data_len);
+ }
+ } while (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA);
+
+ TEST_EQUAL(ret, 0);
+ TEST_EQUAL(mbedtls_test_move_handshake_to_state(
+ &(client_ep.ssl), &(server_ep.ssl),
+ MBEDTLS_SSL_HANDSHAKE_OVER), 0);
+
+ mbedtls_test_mock_socket_close(&(client_ep.socket));
+ mbedtls_test_mock_socket_close(&(server_ep.socket));
+
+ ret = mbedtls_ssl_session_reset(&(client_ep.ssl));
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session);
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_ssl_session_reset(&(server_ep.ssl));
+ TEST_EQUAL(ret, 0);
+
+ ret = mbedtls_test_mock_socket_connect(&(client_ep.socket),
+ &(server_ep.socket), 1024);
+ TEST_EQUAL(ret, 0);
+
+ previous_client_state = client_state;
+ if (previous_client_state == MBEDTLS_SSL_HANDSHAKE_OVER) {
+ break;
+ }
+
+ /* In case of HRR scenario, once we have been through it, move over
+ * the first ClientHello and ServerHello otherwise we just keep playing
+ * this first part of the handshake with HRR.
+ */
+ if ((scenario == TEST_EARLY_DATA_HRR) && (beyond_first_hello)) {
+ TEST_ASSERT(mbedtls_test_move_handshake_to_state(
+ &(client_ep.ssl), &(server_ep.ssl),
+ MBEDTLS_SSL_SERVER_HELLO) == 0);
+ TEST_ASSERT(mbedtls_test_move_handshake_to_state(
+ &(client_ep.ssl), &(server_ep.ssl),
+ MBEDTLS_SSL_CLIENT_HELLO) == 0);
+ }
+
+ TEST_EQUAL(mbedtls_test_move_handshake_to_state(
+ &(client_ep.ssl), &(server_ep.ssl),
+ previous_client_state), 0);
+
+ /* Progress the handshake from at least one state */
+ while (client_ep.ssl.state == previous_client_state) {
+ ret = mbedtls_ssl_handshake_step(&(client_ep.ssl));
+ TEST_ASSERT((ret == 0) ||
+ (ret == MBEDTLS_ERR_SSL_WANT_READ) ||
+ (ret == MBEDTLS_ERR_SSL_WANT_WRITE));
+ if (client_ep.ssl.state != previous_client_state) {
+ break;
+ }
+ ret = mbedtls_ssl_handshake_step(&(server_ep.ssl));
+ TEST_ASSERT((ret == 0) ||
+ (ret == MBEDTLS_ERR_SSL_WANT_READ) ||
+ (ret == MBEDTLS_ERR_SSL_WANT_WRITE));
+ }
+ } while (1);
+
+exit:
+ mbedtls_test_ssl_endpoint_free(&client_ep, NULL);
+ mbedtls_test_ssl_endpoint_free(&server_ep, NULL);
+ mbedtls_test_free_handshake_options(&client_options);
+ mbedtls_test_free_handshake_options(&server_options);
+ mbedtls_ssl_session_free(&saved_session);
+ PSA_DONE();
+}
+/* END_CASE */