Skip to content

Commit

Permalink
Fixes an issue where a dtls hello verify message was responded with a…
Browse files Browse the repository at this point in the history
… second dtls 1.3 client hello.
  • Loading branch information
fwh-dc committed May 27, 2024
1 parent 5cbb538 commit dbf90cb
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 29 deletions.
7 changes: 1 addition & 6 deletions fuzz/dtlsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
if (client == NULL)
goto end;
OPENSSL_assert(SSL_set_min_proto_version(client, 0) == 1);
/**
* TODO(DTLSv1.3): Fuzzing fails with
* ssl/statem/extensions_clnt.c:624: OpenSSL internal error:
* Assertion failed: s->hello_retry_request == SSL_HRR_PENDING
*/
OPENSSL_assert(SSL_set_max_proto_version(client, DTLS1_2_VERSION) == 1);
OPENSSL_assert(SSL_set_max_proto_version(client, 0) == 1);
OPENSSL_assert(SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") == 1);
SSL_set_tlsext_host_name(client, "localhost");
in = BIO_new(BIO_s_mem());
Expand Down
17 changes: 17 additions & 0 deletions ssl/statem/statem_clnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,8 @@ MSG_PROCESS_RETURN dtls_process_hello_verify(SSL_CONNECTION *s, PACKET *pkt)
{
size_t cookie_len;
PACKET cookiepkt;
int max_version;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);

if (!PACKET_forward(pkt, 2)
|| !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
Expand All @@ -1362,7 +1364,22 @@ MSG_PROCESS_RETURN dtls_process_hello_verify(SSL_CONNECTION *s, PACKET *pkt)
return MSG_PROCESS_ERROR;
}
s->d1->cookie_len = cookie_len;
if (ssl == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}

max_version = SSL_get_max_proto_version(ssl);

/*
* Server responds with a HelloVerify which means we cannot negotiate a
* higher version than DTLSv1.2.
*/
if ((max_version == DTLS1_3_VERSION || max_version == 0)
&& !SSL_set_max_proto_version(ssl, DTLS1_2_VERSION)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_FINISHED_READING;
}

Expand Down
29 changes: 14 additions & 15 deletions ssl/statem/statem_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2545,6 +2545,7 @@ int ssl_get_min_max_version(const SSL_CONNECTION *s, int *min_version,
int ssl_set_client_hello_version(SSL_CONNECTION *s)
{
int ver_min, ver_max, ret;
const int version1_2 = SSL_CONNECTION_IS_DTLS(s) ? DTLS1_2_VERSION : TLS1_2_VERSION;

/*
* In a renegotiation we always send the same client_version that we sent
Expand All @@ -2560,21 +2561,19 @@ int ssl_set_client_hello_version(SSL_CONNECTION *s)

s->version = ver_max;

if (SSL_CONNECTION_IS_DTLS(s)) {
if (ver_max == DTLS1_BAD_VER) {
/*
* Even though this is technically before version negotiation,
* because we have asked for DTLS1_BAD_VER we will never negotiate
* anything else, and this has impacts on the record layer for when
* we read the ServerHello. So we need to tell the record layer
* about this immediately.
*/
if (!ssl_set_record_protocol_version(s, ver_max))
return 0;
}
} else if (ver_max > TLS1_2_VERSION) {
/* TLS1.3 always uses TLS1.2 in the legacy_version field */
ver_max = TLS1_2_VERSION;
if (SSL_CONNECTION_IS_DTLS(s) && ver_max == DTLS1_BAD_VER) {
/*
* Even though this is technically before version negotiation,
* because we have asked for DTLS1_BAD_VER we will never negotiate
* anything else, and this has impacts on the record layer for when
* we read the ServerHello. So we need to tell the record layer
* about this immediately.
*/
if (!ssl_set_record_protocol_version(s, ver_max))
return 0;
} else if (ssl_version_cmp(s, ver_max, version1_2) > 0) {
/* (D)TLS1.3 always uses (D)TLS1.2 in the legacy_version field */
ver_max = version1_2;
}

s->client_version = ver_max;
Expand Down
12 changes: 4 additions & 8 deletions test/dtlstest.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@ static int test_dtls_drop_records(int idx)

/**
* TODO(DTLSv1.3): Tests fails with
* ssl/statem/extensions_clnt.c:624: OpenSSL internal error:
* Assertion failed: s->hello_retry_request == SSL_HRR_PENDING
* tls_psk_do_binder:binder does not verify:ssl/statem/extensions.c:1690:
*
* Check when https://github.com/openssl/openssl/pull/24426 has been merged
*/
if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(),
DTLS_client_method(),
Expand Down Expand Up @@ -612,14 +613,9 @@ static int test_listen(void)
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;

/**
* TODO(DTLSv1.3): Tests fails with
* ssl/statem/extensions_clnt.c:624: OpenSSL internal error:
* Assertion failed: s->hello_retry_request == SSL_HRR_PENDING
*/
if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(),
DTLS_client_method(),
DTLS1_VERSION, DTLS1_2_VERSION,
DTLS1_VERSION, 0,
&sctx, &cctx, cert, privkey)))
return 0;

Expand Down

0 comments on commit dbf90cb

Please sign in to comment.