diff --git a/library/ssl_misc.h b/library/ssl_misc.h index de8e0dae23..f52f784476 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -16,6 +16,9 @@ #include "mbedtls/error.h" #include "mbedtls/ssl.h" +#include "mbedtls/debug.h" +#include "debug_internal.h" + #include "mbedtls/cipher.h" #include "psa/crypto.h" @@ -1304,12 +1307,30 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_DEBUG_C) +/* Declared in "ssl_debug_helpers.h". We can't include this file from + * "ssl_misc.h" because it includes "ssl_misc.h" because it needs some + * type definitions. TODO: split the type definitions and the helper + * functions into different headers. + */ +const char *mbedtls_ssl_states_str(mbedtls_ssl_states state); +#endif + static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl, mbedtls_ssl_states state) { + MBEDTLS_SSL_DEBUG_MSG(3, ("handshake state: %d (%s) -> %d (%s)", + ssl->state, mbedtls_ssl_states_str(ssl->state), + (int) state, mbedtls_ssl_states_str(state))); ssl->state = (int) state; } +static inline void mbedtls_ssl_handshake_increment_state(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_handshake_set_state(ssl, ssl->state + 1); +} + MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); diff --git a/library/ssl_msg.c b/library/ssl_msg.c index be0dc92720..dba8d74ba1 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -3699,6 +3699,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, rec->buf_len = rec->data_offset + rec->data_len; if (rec->data_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("rejecting empty record")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } @@ -5044,7 +5045,7 @@ int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl) ssl->out_msglen = 1; ssl->out_msg[0] = 1; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -5106,7 +5107,7 @@ int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) mbedtls_ssl_update_in_pointers(ssl); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse change cipher spec")); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5a668a4660..75dde2b8ee 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1409,7 +1409,7 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_REQUEST); ssl->flags &= MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION; ssl->tls_version = ssl->conf->max_tls_version; @@ -4235,7 +4235,7 @@ int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); ret = 0; break; @@ -4386,7 +4386,7 @@ int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl) } #endif - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_REQUEST); ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { @@ -5144,7 +5144,7 @@ static int ssl_context_load(mbedtls_ssl_context *ssl, * Most of them already set to the correct value by mbedtls_ssl_init() and * mbedtls_ssl_reset(), so we only need to set the remaining ones. */ - ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; /* Adjust pointers for header fields of outgoing records to @@ -6726,7 +6726,7 @@ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -6743,7 +6743,7 @@ int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -6766,7 +6766,7 @@ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -6774,7 +6774,7 @@ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (ssl->handshake->client_auth == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } } @@ -6828,7 +6828,7 @@ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -7282,7 +7282,7 @@ crt_verify: exit: if (ret == 0) { - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) @@ -7460,7 +7460,7 @@ void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl) #endif mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); - ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); } @@ -7504,16 +7504,16 @@ int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl) if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC); } #endif } else { - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); } /* @@ -7639,16 +7639,16 @@ int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC); } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); } #endif } else { - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); } #if defined(MBEDTLS_SSL_PROTO_DTLS) diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index e0743e1a6a..df7dfbfa61 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -1118,7 +1118,7 @@ static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) ssl->handshake->cookie_len = cookie_len; /* Start over at ClientHello */ - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); ret = mbedtls_ssl_reset_checksum(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret); @@ -1327,7 +1327,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl->session_negotiate->ciphersuite != i || ssl->session_negotiate->id_len != n || memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) { - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); ssl->handshake->resume = 0; #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); @@ -1336,7 +1336,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) ssl->session_negotiate->id_len = n; memcpy(ssl->session_negotiate->id, buf + 35, n); } else { - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC); } MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed", @@ -1839,7 +1839,7 @@ static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) } MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } ((void) p); @@ -2147,7 +2147,7 @@ start_processing: #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ exit: - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server key exchange")); @@ -2165,7 +2165,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -2192,7 +2192,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -2210,7 +2210,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); ssl->handshake->client_auth = (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); @@ -2381,7 +2381,7 @@ static int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl) return MBEDTLS_ERR_SSL_DECODE_ERROR; } - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { @@ -2683,7 +2683,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -2712,7 +2712,7 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -2754,14 +2754,14 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } if (ssl->handshake->client_auth == 0 || mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -2843,7 +2843,7 @@ sign: ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -2917,7 +2917,7 @@ static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl) /* We're not waiting for a NewSessionTicket message any more */ ssl->handshake->new_session_ticket = 0; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC); /* * Zero-length ticket means the server changed his mind and doesn't want @@ -2978,13 +2978,13 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && ssl->handshake->new_session_ticket != 0) { - ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_NEW_SESSION_TICKET); } #endif switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; /* @@ -3069,7 +3069,7 @@ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index e1785504b6..2b2b49f2b0 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -1597,7 +1597,7 @@ have_ciphersuite: ssl->session_negotiate->ciphersuite = ciphersuites[i]; ssl->handshake->ciphersuite_info = ciphersuite_info; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { @@ -2015,7 +2015,7 @@ static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -2183,7 +2183,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) * New session, create a new session id, * unless we're about to issue a session ticket */ - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); @@ -2207,7 +2207,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl) * Resuming a session */ n = ssl->session_negotiate->id_len; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC); if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); @@ -2333,7 +2333,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -2356,7 +2356,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { @@ -3080,7 +3080,7 @@ static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl) /* Key exchanges not involving ephemeral keys don't use * ServerKeyExchange, so end here. */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write server key exchange")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ @@ -3134,7 +3134,7 @@ static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); @@ -3156,7 +3156,7 @@ static int ssl_write_server_hello_done(mbedtls_ssl_context *ssl) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { @@ -3461,7 +3461,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) return ret; } - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client key exchange")); @@ -3479,7 +3479,7 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } @@ -3505,20 +3505,20 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (ssl->session_negotiate->peer_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert_digest == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); return 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ @@ -3530,7 +3530,7 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) return ret; } - ssl->state++; + mbedtls_ssl_handshake_increment_state(ssl); /* Process the message contents */ if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || @@ -3714,7 +3714,7 @@ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; /* @@ -3803,7 +3803,7 @@ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 3ba314f832..c0c110105d 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -476,6 +476,18 @@ void mbedtls_test_ssl_endpoint_free( * /p second_ssl is used as second endpoint and their sockets have to be * connected before calling this function. * + * For example, to perform a full handshake: + * ``` + * mbedtls_test_move_handshake_to_state( + * &server.ssl, &client.ssl, + * MBEDTLS_SSL_HANDSHAKE_OVER); + * mbedtls_test_move_handshake_to_state( + * &client.ssl, &server.ssl, + * MBEDTLS_SSL_HANDSHAKE_OVER); + * ``` + * Note that you need both calls to reach the handshake-over state on + * both sides. + * * \retval 0 on success, otherwise error code. */ int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl, diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 743b53c007..11648a3341 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -106,6 +106,315 @@ static void resize_buffers(int mfl, int renegotiation, int legacy_renegotiation, #define TEST_GCM_OR_CHACHAPOLY_ENABLED #endif +typedef enum { + RECOMBINE_NOMINAL, /* param: ignored */ + RECOMBINE_SPLIT_FIRST, /* param: offset of split (<=0 means from end) */ + RECOMBINE_TRUNCATE_FIRST, /* param: offset of truncation (<=0 means from end) */ + RECOMBINE_INSERT_EMPTY, /* param: offset (<0 means from end) */ + RECOMBINE_INSERT_RECORD, /* param: record type */ + RECOMBINE_COALESCE, /* param: number of records (INT_MAX=all) */ + RECOMBINE_COALESCE_SPLIT_ONCE, /* param: offset of split (<=0 means from end) */ + RECOMBINE_COALESCE_SPLIT_BOTH_ENDS, /* param: offset, must be >0 */ +} recombine_records_instruction_t; + +/* Keep this in sync with the recombine_server_first_flight() + * See comment there. */ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \ + defined(PSA_WANT_ALG_SHA_256) && \ + defined(PSA_WANT_ECC_SECP_R1_256) && \ + defined(PSA_WANT_ECC_SECP_R1_384) && \ + defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \ + defined(PSA_WANT_ALG_ECDSA_ANY) + +/* Split the first record into two pieces of lengths offset and + * record_length-offset. If offset is zero or negative, count from the end of + * the record. */ +static int recombine_split_first_record(mbedtls_test_ssl_buffer *buf, + int offset) +{ + const size_t header_length = 5; + TEST_LE_U(header_length, buf->content_length); + size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2); + + if (offset > 0) { + TEST_LE_S(offset, record_length); + } else { + TEST_LE_S(-offset, record_length); + offset = record_length + offset; + } + + /* Check that we have room to insert a record header */ + TEST_LE_U(buf->content_length + header_length, buf->capacity); + + /* Make room for a record header */ + size_t new_record_start = header_length + offset; + size_t new_content_start = new_record_start + header_length; + memmove(buf->buffer + new_content_start, + buf->buffer + new_record_start, + buf->content_length - new_record_start); + buf->content_length += header_length; + + /* Construct a header for the new record based on the existing one */ + memcpy(buf->buffer + new_record_start, buf->buffer, header_length); + MBEDTLS_PUT_UINT16_BE(record_length - offset, + buf->buffer, new_content_start - 2); + + /* Adjust the length of the first record */ + MBEDTLS_PUT_UINT16_BE(offset, buf->buffer, header_length - 2); + + return 0; + +exit: + return -1; +} + +/* Truncate the first record, keeping only the first offset bytes. + * If offset is zero or negative, count from the end of the record. + * Remove the subsequent records. + */ +static int recombine_truncate_first_record(mbedtls_test_ssl_buffer *buf, + int offset) +{ + const size_t header_length = 5; + TEST_LE_U(header_length, buf->content_length); + size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2); + + if (offset > 0) { + TEST_LE_S(offset, record_length); + } else { + TEST_LE_S(-offset, record_length); + offset = record_length + offset; + } + + /* Adjust the length of the first record */ + MBEDTLS_PUT_UINT16_BE(offset, buf->buffer, header_length - 2); + + /* Wipe the rest */ + size_t truncated_end = header_length + offset; + memset(buf->buffer + truncated_end, '!', + buf->content_length - truncated_end); + buf->content_length = truncated_end; + + return 0; + +exit: + return -1; +} + +/* Insert a (dummy) record at the given offset. If offset is negative, + * count from the end of the first record. */ +static int recombine_insert_record(mbedtls_test_ssl_buffer *buf, + int offset, + uint8_t inserted_record_type) +{ + const size_t header_length = 5; + TEST_LE_U(header_length, buf->content_length); + size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2); + + if (offset >= 0) { + TEST_LE_S(offset, record_length); + } else { + TEST_LE_S(-offset, record_length); + offset = record_length + offset; + } + + uint8_t inserted_content[42] = { 0 }; + size_t inserted_content_length = 0; + switch (inserted_record_type) { + case MBEDTLS_SSL_MSG_ALERT: + inserted_content[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + inserted_content[1] = MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION; + inserted_content_length = 2; + break; + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + inserted_content[0] = 0x01; + inserted_content_length = 1; + break; + case MBEDTLS_SSL_MSG_APPLICATION_DATA: + inserted_content_length = sizeof(inserted_content); + break; + default: + /* Leave the content empty */ + break; + } + + /* Check that we have room to insert two record headers plus the new + * content. */ + TEST_LE_U(buf->content_length + 2 * header_length + inserted_content_length, + buf->capacity); + + /* Make room for the inserted record and a record header for the fragment */ + size_t inserted_record_start = header_length + offset; + size_t inserted_content_start = inserted_record_start + header_length; + size_t tail_record_start = inserted_content_start + inserted_content_length; + size_t tail_content_start = tail_record_start + header_length; + memmove(buf->buffer + tail_content_start, + buf->buffer + inserted_record_start, + buf->content_length - inserted_record_start); + buf->content_length += 2 * header_length; + + /* Construct the inserted record based on the existing one */ + memcpy(buf->buffer + inserted_record_start, buf->buffer, header_length); + buf->buffer[inserted_record_start] = inserted_record_type; + MBEDTLS_PUT_UINT16_BE(inserted_content_length, + buf->buffer, inserted_content_start - 2); + memcpy(buf->buffer + inserted_content_start, + inserted_content, inserted_content_length); + + /* Construct header for the last fragment based on the existing one */ + memcpy(buf->buffer + tail_record_start, buf->buffer, header_length); + MBEDTLS_PUT_UINT16_BE(record_length - offset, + buf->buffer, tail_content_start - 2); + + /* Adjust the length of the first record */ + MBEDTLS_PUT_UINT16_BE(offset, buf->buffer, header_length - 2); + + return 0; + +exit: + return -1; +} + +/* Coalesce TLS handshake records. + * DTLS is not supported. + * Encrypted or authenticated handshake records are not supported. + * Assume the buffer content is a valid sequence of records. + * + * Coalesce only the first max records, or all the records if there are + * fewer than max. + * Return the number of coalesced records, or -1 on error. + */ +static int recombine_coalesce_handshake_records(mbedtls_test_ssl_buffer *buf, + int max) +{ + const size_t header_length = 5; + TEST_LE_U(header_length, buf->content_length); + if (buf->buffer[0] != MBEDTLS_SSL_MSG_HANDSHAKE) { + return 0; + } + + size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2); + TEST_LE_U(header_length + record_length, buf->content_length); + + int count; + for (count = 1; count < max; count++) { + size_t next_start = header_length + record_length; + if (next_start >= buf->content_length) { + /* We've already reached the last record. */ + break; + } + + TEST_LE_U(next_start + header_length, buf->content_length); + if (buf->buffer[next_start] != MBEDTLS_SSL_MSG_HANDSHAKE) { + /* There's another record, but it isn't a handshake record. */ + break; + } + size_t next_length = + MBEDTLS_GET_UINT16_BE(buf->buffer, next_start + header_length - 2); + TEST_LE_U(next_start + header_length + next_length, buf->content_length); + + /* Erase the next record header */ + memmove(buf->buffer + next_start, + buf->buffer + next_start + header_length, + buf->content_length - next_start); + buf->content_length -= header_length; + /* Update the first record length */ + record_length += next_length; + TEST_LE_U(record_length, 0xffff); + MBEDTLS_PUT_UINT16_BE(record_length, buf->buffer, header_length - 2); + } + + return count; + +exit: + return -1; +} + +static int recombine_records(mbedtls_test_ssl_endpoint *server, + recombine_records_instruction_t instruction, + int param) +{ + mbedtls_test_ssl_buffer *buf = server->socket.output; + int ret; + + /* buf is a circular buffer. For simplicity, this code assumes that + * the data is located at the beginning. This should be ok since + * this function is only meant to be used on the first flight + * emitted by a server. */ + TEST_EQUAL(buf->start, 0); + + switch (instruction) { + case RECOMBINE_NOMINAL: + break; + + case RECOMBINE_SPLIT_FIRST: + ret = recombine_split_first_record(buf, param); + TEST_LE_S(0, ret); + break; + + case RECOMBINE_TRUNCATE_FIRST: + ret = recombine_truncate_first_record(buf, param); + TEST_LE_S(0, ret); + break; + + case RECOMBINE_INSERT_EMPTY: + /* Insert an empty handshake record. */ + ret = recombine_insert_record(buf, param, MBEDTLS_SSL_MSG_HANDSHAKE); + TEST_LE_S(0, ret); + break; + + case RECOMBINE_INSERT_RECORD: + /* Insert an extra record at a position where splitting + * would be ok. */ + ret = recombine_insert_record(buf, 5, param); + TEST_LE_S(0, ret); + break; + + case RECOMBINE_COALESCE: + ret = recombine_coalesce_handshake_records(buf, param); + /* If param != INT_MAX, enforce that there were that many + * records to coalesce. In particular, 1 < param < INT_MAX + * ensures that library will see some coalesced records. */ + if (param == INT_MAX) { + TEST_LE_S(1, ret); + } else { + TEST_EQUAL(ret, param); + } + break; + + case RECOMBINE_COALESCE_SPLIT_ONCE: + ret = recombine_coalesce_handshake_records(buf, INT_MAX); + /* Require at least two coalesced records, otherwise this + * doesn't lead to a meaningful test (use + * RECOMBINE_SPLIT_FIRST instead). */ + TEST_LE_S(2, ret); + ret = recombine_split_first_record(buf, param); + TEST_LE_S(0, ret); + break; + + case RECOMBINE_COALESCE_SPLIT_BOTH_ENDS: + ret = recombine_coalesce_handshake_records(buf, INT_MAX); + /* Accept a single record, which will be split at both ends */ + TEST_LE_S(1, ret); + TEST_LE_S(1, param); + ret = recombine_split_first_record(buf, -param); + TEST_LE_S(0, ret); + ret = recombine_split_first_record(buf, param); + TEST_LE_S(0, ret); + break; + + default: + TEST_FAIL("Instructions not understood"); + } + + return 1; + +exit: + return 0; +} + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED etc */ + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -2840,6 +3149,165 @@ exit: } /* END_CASE */ +/* This test case doesn't actually depend on certificates, + * but our helper code for mbedtls_test_ssl_endpoint does. + * Also, it needs specific hashes, algs and curves for the + * hardcoded test certificates. In principle both RSA and ECDSA + * can be used, but we hardcode ECDSA in order to avoid having + * to express dependencies like "RSA or ECDSA with those curves". */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_ALG_ECDSA_ANY */ +void recombine_server_first_flight(int version, + int instruction, int param, + char *client_log, char *server_log, + int goal_state, int expected_ret) +{ + /* Make sure we have a buffer that's large enough for the longest + * data that the library might ever send, plus a bit extra so that + * we can inject more content. The library won't ever send more than + * 2^14 bytes of handshake messages, so we round that up. In practice + * we could surely get away with a much smaller buffer. The main + * variable part is the server certificate. */ + enum { BUFFSIZE = 17000 }; + mbedtls_test_ssl_endpoint client; + memset(&client, 0, sizeof(client)); + mbedtls_test_ssl_endpoint server; + memset(&server, 0, sizeof(server)); + mbedtls_test_handshake_test_options client_options; + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_handshake_test_options server_options; + mbedtls_test_init_handshake_options(&server_options); +#if defined(MBEDTLS_DEBUG_C) + mbedtls_test_ssl_log_pattern cli_pattern = { .pattern = client_log }; + mbedtls_test_ssl_log_pattern srv_pattern = { .pattern = server_log }; +#else + (void) client_log; + (void) server_log; +#endif + int ret = 0; + + MD_OR_USE_PSA_INIT(); +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(3); +#endif + + // Does't really matter but we want to know to declare dependencies. + client_options.pk_alg = MBEDTLS_PK_ECDSA; + server_options.pk_alg = MBEDTLS_PK_ECDSA; + + client_options.client_min_version = version; + client_options.client_max_version = version; +#if defined(MBEDTLS_DEBUG_C) + client_options.cli_log_obj = &cli_pattern; + client_options.cli_log_fun = mbedtls_test_ssl_log_analyzer; +#endif + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT, + &client_options, NULL, NULL, + NULL), 0); + + server_options.server_min_version = version; + server_options.server_max_version = version; +#if defined(MBEDTLS_DEBUG_C) + server_options.srv_log_obj = &srv_pattern; + server_options.srv_log_fun = mbedtls_test_ssl_log_analyzer; +#endif + TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER, + &server_options, NULL, NULL, + NULL), 0); + + TEST_EQUAL(mbedtls_test_mock_socket_connect(&client.socket, + &server.socket, + BUFFSIZE), 0); + + /* Client: emit the first flight from the client */ + while (ret == 0) { + mbedtls_test_set_step(client.ssl.state); + ret = mbedtls_ssl_handshake_step(&client.ssl); + } + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ); + ret = 0; + TEST_EQUAL(client.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + + /* Server: parse the first flight from the client + * and emit the first flight from the server */ + while (ret == 0) { + mbedtls_test_set_step(1000 + server.ssl.state); + ret = mbedtls_ssl_handshake_step(&server.ssl); + } + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ); + ret = 0; + TEST_EQUAL(server.ssl.state, MBEDTLS_SSL_SERVER_HELLO_DONE + 1); + + /* Recombine the first flight from the server */ + TEST_ASSERT(recombine_records(&server, instruction, param)); + + /* Client: parse the first flight from the server + * and emit the second flight from the client */ + while (ret == 0 && !mbedtls_ssl_is_handshake_over(&client.ssl)) { + mbedtls_test_set_step(client.ssl.state); + ret = mbedtls_ssl_handshake_step(&client.ssl); + if (client.ssl.state == goal_state && ret != 0) { + TEST_EQUAL(ret, expected_ret); + goto goal_reached; + } + } +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* A default TLS 1.3 handshake has only 1 flight from the server, + * while the default (non-resumption) 1.2 handshake has two. */ + if (version >= MBEDTLS_SSL_VERSION_TLS1_3 && + goal_state >= MBEDTLS_SSL_HANDSHAKE_OVER) { + TEST_EQUAL(ret, 0); + } else +#endif + { + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ); + } + ret = 0; + + /* Server: parse the first flight from the client + * and emit the second flight from the server */ + if (instruction == RECOMBINE_TRUNCATE_FIRST) { + /* Close without a notification. The case of closing with a + * notification is tested via RECOMBINE_INSERT_RECORD to insert + * an alert record (which we reject, making the client SSL + * context become invalid). */ + mbedtls_test_mock_socket_close(&server.socket); + goto goal_reached; + } + while (ret == 0 && !mbedtls_ssl_is_handshake_over(&server.ssl)) { + mbedtls_test_set_step(1000 + server.ssl.state); + ret = mbedtls_ssl_handshake_step(&server.ssl); + } + TEST_EQUAL(ret, 0); + + /* Client: parse the second flight from the server */ + while (ret == 0 && !mbedtls_ssl_is_handshake_over(&client.ssl)) { + mbedtls_test_set_step(client.ssl.state); + ret = mbedtls_ssl_handshake_step(&client.ssl); + } + if (client.ssl.state == goal_state) { + TEST_EQUAL(ret, expected_ret); + } else { + TEST_EQUAL(ret, 0); + } + +goal_reached: +#if defined(MBEDTLS_DEBUG_C) + TEST_ASSERT(cli_pattern.counter >= 1); + TEST_ASSERT(srv_pattern.counter >= 1); +#endif + +exit: + mbedtls_test_ssl_endpoint_free(&client, NULL); + mbedtls_test_ssl_endpoint_free(&server, NULL); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + MD_OR_USE_PSA_DONE(); +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(0); +#endif +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:PSA_WANT_ALG_SHA_256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */ void renegotiation(int legacy_renegotiation) { diff --git a/tests/suites/test_suite_ssl.records.data b/tests/suites/test_suite_ssl.records.data new file mode 100644 index 0000000000..8220cb0b92 --- /dev/null +++ b/tests/suites/test_suite_ssl.records.data @@ -0,0 +1,162 @@ +Recombine server flight 1: TLS 1.2, nominal +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_NOMINAL:0:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.3, nominal +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_NOMINAL:0:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, coalesce 2 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE:2:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, coalesce 3 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE:3:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, coalesce all +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE:INT_MAX:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +# TLS 1.3 has a single non-encrypted handshake record, so this doesn't +# actually perform any coalescing. Run the test case anyway, but this does +# very little beyond exercising the test code itself a little. +Recombine server flight 1: TLS 1.3, coalesce all +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_COALESCE:INT_MAX:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, split first at 4 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.3, split first at 4 +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, split first at end-1 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:-1:"subsequent handshake fragment\: 1,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.3, split first at end-1 +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:-1:"subsequent handshake fragment\: 1,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +# The library doesn't support an initial handshake fragment that doesn't +# contain the full 4-byte handshake header. +Recombine server flight 1: TLS 1.2, split first at 3 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:3:"handshake message too short\: 3":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, split first at 3 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:3:"handshake message too short\: 3":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, split first at 2 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:2:"handshake message too short\: 2":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, split first at 2 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:2:"handshake message too short\: 2":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, split first at 1 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:1:"handshake message too short\: 1":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, split first at 1 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:1:"handshake message too short\: 1":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, truncate at 4 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_TRUNCATE_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_WANT_READ + +Recombine server flight 1: TLS 1.3, truncate at 4 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_TRUNCATE_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_WANT_READ + +Recombine server flight 1: TLS 1.2, insert empty record after first (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_CERTIFICATE:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, insert empty record after first (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:0:"rejecting empty record":"":MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, insert empty record at start (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_EMPTY:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, insert empty record at start (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_EMPTY:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, insert empty record at 42 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_EMPTY:42:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, insert empty record at 42 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_EMPTY:42:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, insert ChangeCipherSpec record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.3, insert ChangeCipherSpec record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.2, insert alert record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_ALERT:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.3, insert alert record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_ALERT:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.2, insert data record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_APPLICATION_DATA:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.3, insert data record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_APPLICATION_DATA:"non-handshake message in the middle of a fragmented handshake message":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE + +Recombine server flight 1: TLS 1.2, insert CID record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_CID:"unknown record type":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, insert CID record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_RECORD:MBEDTLS_SSL_MSG_CID:"unknown record type":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.2, insert unknown record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_RECORD:255:"unknown record type 255":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +Recombine server flight 1: TLS 1.3, insert unknown record at 5 (bad) +depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_CHACHA20_POLY1305 +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_RECORD:255:"unknown record type 255":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD + +# Since there is a single unencrypted handshake message in the first flight +# from the server, and the test code that recombines handshake records can only +# handle plaintext records, we can't have TLS 1.3 tests with coalesced +# handshake messages. Hence most coalesce-and-split test cases are 1.2-only. + +Recombine server flight 1: TLS 1.2, coalesce and split at 4 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_ONCE:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +# The last message of the first flight from the server is ServerHelloDone, +# which is an empty handshake message, i.e. of length 4. The library doesn't +# support fragmentation of a handshake header, so the last place where we +# can split the flight is 4+1 = 5 bytes before it ends, with 1 byte in the +# previous handshake message and 4 bytes of ServerHelloDone including header. +Recombine server flight 1: TLS 1.2, coalesce and split at end-5 +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_ONCE:-5:"subsequent handshake fragment\: 5,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0 + +Recombine server flight 1: TLS 1.2, coalesce and split at both ends +depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_BOTH_ENDS:5:"subsequent handshake fragment\: 5,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0