diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 7c2f03ec28..2c9d197930 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3490,3 +3490,24 @@ inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"160 Inject ClientHello - TLS 1.3 fragmented 4 + invalid type + 72 rejected depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_HAVE_AES:MBEDTLS_MD_CAN_SHA256:MBEDTLS_SSL_HAVE_GCM:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY inject_client_content_on_the_wire:MBEDTLS_PK_ECDSA:MBEDTLS_SSL_CLIENT_HELLO:"1603030004010000481003030002015a160303004803030123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000213010100001d000a000400020017002b0003020304000d000400020403003300020000":"unknown record type":MBEDTLS_ERR_SSL_INVALID_RECORD + +Send large fragmented ClientHello: 4 bytes too large +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: 1 byte too large +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 3:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: would fit without overhead #1 +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:0:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: would fit without overhead #2 +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:1:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: would fit without overhead #3 +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:2:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: would fit without overhead #4 +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:3:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA + +Send large fragmented ClientHello: would fit without overhead #5 +send_large_fragmented_hello:MBEDTLS_SSL_IN_CONTENT_LEN - 4:4:"requesting more data than fits":MBEDTLS_ERR_SSL_BAD_INPUT_DATA diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 9630fe091d..c4d57f79e2 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -5088,3 +5088,115 @@ exit: PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +void send_large_fragmented_hello(int hs_len_int, int first_frag_content_len_int, + char *log_pattern, int expected_ret) +{ + /* This function sends a long message (claiming to be a ClientHello) + * fragmented in 1-byte fragments (except the initial fragment). + * The purpose is to test how the stack reacts when receiving: + * - a message larger than our buffer; + * - a message smaller than our buffer, but where the intermediate size of + * holding all the fragments (including overhead) is larger than our + * buffer. + */ + enum { BUFFSIZE = 16384 }; + mbedtls_test_ssl_endpoint server, client; + mbedtls_platform_zeroize(&server, sizeof(server)); + mbedtls_platform_zeroize(&client, sizeof(client)); + + mbedtls_test_handshake_test_options options; + mbedtls_test_init_handshake_options(&options); + + mbedtls_test_ssl_log_pattern srv_pattern; + memset(&srv_pattern, 0, sizeof(srv_pattern)); + + unsigned char *first_frag = NULL; + int ret = -1; + + size_t hs_len = (size_t) hs_len_int; + size_t first_frag_content_len = (size_t) first_frag_content_len_int; + + PSA_INIT(); + + srv_pattern.pattern = log_pattern; + options.srv_log_obj = &srv_pattern; + options.srv_log_fun = mbedtls_test_ssl_log_analyzer; + mbedtls_debug_set_threshold(5); + + ret = mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER, + &options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT, + &options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&server.socket, &client.socket, + BUFFSIZE); + TEST_EQUAL(ret, 0); + + /* Make the server move past the initial dummy state */ + ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, + MBEDTLS_SSL_CLIENT_HELLO); + TEST_EQUAL(ret, 0); + + /* Prepare initial fragment */ + const size_t first_len = 5 // record header, see below + + 4 // handshake header, see balow + + first_frag_content_len; + TEST_CALLOC(first_frag, first_len); + unsigned char *p = first_frag; + // record header + // record type: handshake + *p++ = 0x16, + // record version (actually common to TLS 1.2 and TLS 1.3) + *p++ = 0x03, + *p++ = 0x03, + // record length: two bytes + *p++ = (unsigned char) (((4 + first_frag_content_len) >> 8) & 0xff); + *p++ = (unsigned char) (((4 + first_frag_content_len) >> 0) & 0xff); + // handshake header + // handshake type: ClientHello + *p++ = 0x01, + // handshake length: three bytes + *p++ = (unsigned char) ((hs_len >> 16) & 0xff); + *p++ = (unsigned char) ((hs_len >> 8) & 0xff); + *p++ = (unsigned char) ((hs_len >> 0) & 0xff); + // handshake content: dummy value + memset(p, 0x2a, first_frag_content_len); + + /* Send initial fragment and have the server process it. */ + ret = mbedtls_test_mock_tcp_send_b(&client.socket, first_frag, first_len); + TEST_ASSERT(ret >= 0 && (size_t) ret == first_len); + + ret = mbedtls_ssl_handshake_step(&server.ssl); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ); + + /* Dummy 1-byte fragment to repeatedly send next */ + const unsigned char next[] = { + 0x16, 0x03, 0x03, 0x00, 0x01, // record header (see above) + 0x2a, // Dummy handshake message content + }; + for (size_t left = hs_len - first_frag_content_len; left != 0; left--) { + ret = mbedtls_test_mock_tcp_send_b(&client.socket, next, sizeof(next)); + TEST_ASSERT(ret >= 0 && (size_t) ret == sizeof(next)); + + ret = mbedtls_ssl_handshake_step(&server.ssl); + if (ret != MBEDTLS_ERR_SSL_WANT_READ) { + break; + } + } + TEST_EQUAL(ret, expected_ret); + TEST_EQUAL(srv_pattern.counter, 1); + +exit: + mbedtls_test_free_handshake_options(&options); + mbedtls_test_ssl_endpoint_free(&server, NULL); + mbedtls_test_ssl_endpoint_free(&client, NULL); + mbedtls_debug_set_threshold(0); + mbedtls_free(first_frag); + PSA_DONE(); +} +/* END_CASE */