Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion library/ssl_tls13_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static void ssl_tls13_select_ciphersuite(
return;
}

MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
MBEDTLS_SSL_DEBUG_MSG(1, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
(unsigned) psk_ciphersuite_id,
(unsigned long) psk_hash_alg));
}
Expand Down Expand Up @@ -1380,6 +1380,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
}

if (ret == 0) {
MBEDTLS_SSL_DEBUG_MSG(2, ("no supported_versions extension"));
return SSL_CLIENT_HELLO_TLS1_2;
}

Expand All @@ -1401,6 +1402,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
* the TLS version to negotiate.
*/
if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) {
MBEDTLS_SSL_DEBUG_MSG(2, ("supported_versions without 1.3"));
return SSL_CLIENT_HELLO_TLS1_2;
}
}
Expand Down Expand Up @@ -1985,6 +1987,7 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)
}
ssl->keep_current_message = 1;
ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
MBEDTLS_SSL_DEBUG_MSG(1, ("non-1.3 ClientHello left for later processing"));
return 0;
}

Expand Down
13 changes: 13 additions & 0 deletions tests/src/test_helpers/ssl_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,22 @@ void mbedtls_test_ssl_log_analyzer(void *ctx, int level,
{
mbedtls_test_ssl_log_pattern *p = (mbedtls_test_ssl_log_pattern *) ctx;

/* Change 0 to 1 for debugging of test cases that use this function. */
#if 0
const char *q, *basename;
/* Extract basename from file */
for (q = basename = file; *q != '\0'; q++) {
if (*q == '/' || *q == '\\') {
basename = q + 1;
}
}
printf("%s:%04d: |%d| %s",
basename, line, level, str);
#else
Comment on lines +31 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that's very helpful!

(void) level;
(void) line;
(void) file;
#endif

if (NULL != p &&
NULL != p->pattern &&
Expand Down
190 changes: 190 additions & 0 deletions tests/suites/test_suite_ssl.function
Original file line number Diff line number Diff line change
Expand Up @@ -5037,3 +5037,193 @@ exit:
PSA_DONE();
}
/* END_CASE */

/* BEGIN_CASE depends_on:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
void inject_client_content_on_the_wire(int pk_alg,
int state, data_t *data,
char *log_pattern, int expected_ret)
{
/* This function allows us to inject content at a specific state
* in the handshake, or when it's completed. The content is injected
* on the mock TCP socket, as if we were an active network attacker.
*
* This function is suitable to inject:
* - crafted records, at any point;
* - valid records that contain crafted handshake messages, but only
* when the traffic is still unprotected (for TLS 1.2 that's most of the
* handshake, for TLS 1.3 that's only the Hello messages);
* - handshake messages that are fragmented in a specific way,
* under the same conditions as above.
*/
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));
int ret = -1;

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(3);

options.pk_alg = pk_alg;

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 to the required state */
ret = mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl, state);
TEST_EQUAL(ret, 0);

/* Send the crafted message */
ret = mbedtls_test_mock_tcp_send_b(&client.socket, data->x, data->len);
TEST_EQUAL(ret, (int) data->len);

/* Have the server process it.
* Need the loop because a server that support 1.3 and 1.2
* will process a 1.2 ClientHello in two steps.
*/
do {
ret = mbedtls_ssl_handshake_step(&server.ssl);
} while (ret == 0 && server.ssl.state == state);
TEST_EQUAL(ret, expected_ret);
TEST_ASSERT(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);
PSA_DONE();
}
/* END_CASE */

/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_DEBUG_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY */
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(1);

// Does't really matter but we want to know to declare dependencies.
options.pk_alg = MBEDTLS_PK_ECDSA;

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: why not

Suggested change
TEST_ASSERT(ret >= 0 && (size_t) ret == first_len);
TEST_EQUAL(ret, (int) first_len);

which prints out the values of ret and first_len if it fails?


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 */
Loading