mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 05:50:47 +02:00
F-6547 - Reject TLS KeyUpdate on QUIC connections
QUIC performs key updates at the packet-protection layer via the Key Phase bit, so RFC 9001 section 6 requires a QUIC endpoint to reject any received TLS KeyUpdate handshake message as a fatal unexpected_message connection error and to never send one. The TLS 1.3 receive path processed the message normally, rotating traffic secrets and possibly emitting a prohibited KeyUpdate response, and the send path allowed a QUIC connection to originate a KeyUpdate. Guard the key_update case in SanityCheckTls13MsgReceived so a QUIC connection aborts with a fatal unexpected_message alert, and guard Tls13UpdateKeys so a QUIC connection cannot send a KeyUpdate. Add a QUIC unit test that feeds a post-handshake KeyUpdate and confirms the connection is refused.
This commit is contained in:
+19
-1
@@ -13568,6 +13568,16 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
|
||||
|
||||
case key_update:
|
||||
/* Valid on both sides. */
|
||||
#ifdef WOLFSSL_QUIC
|
||||
/* RFC 9001 Section 6: QUIC performs key updates at the QUIC
|
||||
* packet-protection layer, so a TLS KeyUpdate message must be
|
||||
* rejected as a fatal unexpected_message connection error. */
|
||||
if (WOLFSSL_IS_QUIC(ssl)) {
|
||||
WOLFSSL_MSG("KeyUpdate received over QUIC");
|
||||
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||
return SANITY_MSG_E;
|
||||
}
|
||||
#endif
|
||||
/* Check state.
|
||||
* Client and server must have received finished message from other
|
||||
* side.
|
||||
@@ -14974,6 +14984,13 @@ int Tls13UpdateKeys(WOLFSSL* ssl)
|
||||
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_QUIC
|
||||
/* RFC 9001 Section 6: a QUIC connection must not send a TLS KeyUpdate;
|
||||
* key updates are handled at the QUIC packet-protection layer. */
|
||||
if (WOLFSSL_IS_QUIC(ssl))
|
||||
return BAD_FUNC_ARG;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* we are already waiting for the ack of a sent key update message. We can't
|
||||
send another one before receiving its ack. Either wolfSSL_update_keys()
|
||||
@@ -14993,7 +15010,8 @@ int Tls13UpdateKeys(WOLFSSL* ssl)
|
||||
* calling wolfSSL_write() will have the message sent when ready.
|
||||
*
|
||||
* ssl The SSL/TLS object.
|
||||
* returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
|
||||
* returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or running over
|
||||
* QUIC (RFC 9001 handles key updates at the QUIC packet-protection layer),
|
||||
* WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write,
|
||||
* WOLFSSL_SUCCESS on success and otherwise failure.
|
||||
*/
|
||||
|
||||
@@ -1470,6 +1470,56 @@ static int test_quic_server_hello_fail(int verbose) {
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
static int test_quic_key_update_rejected(int verbose) {
|
||||
EXPECT_DECLS;
|
||||
WOLFSSL_CTX * ctx_c = NULL;
|
||||
WOLFSSL_CTX * ctx_s = NULL;
|
||||
QuicTestContext tclient, tserver;
|
||||
QuicConversation conv;
|
||||
uint8_t lbuffer[16];
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
ExpectNotNull(ctx_c = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
||||
ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
||||
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx_s, svrCertFile,
|
||||
WOLFSSL_FILETYPE_PEM));
|
||||
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile,
|
||||
WOLFSSL_FILETYPE_PEM));
|
||||
|
||||
/* complete a normal QUIC handshake */
|
||||
QuicTestContext_init(&tclient, ctx_c, "client", verbose);
|
||||
QuicTestContext_init(&tserver, ctx_s, "server", verbose);
|
||||
QuicConversation_init(&conv, &tclient, &tserver);
|
||||
QuicConversation_do(&conv);
|
||||
|
||||
/* RFC 9001 section 6: a QUIC connection must not send a TLS KeyUpdate;
|
||||
* key updates are handled at the QUIC packet-protection layer. The
|
||||
* public wolfSSL_update_keys() must refuse on a QUIC connection. */
|
||||
ExpectIntEQ(wolfSSL_update_keys(tserver.ssl),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
|
||||
/* RFC 9001 section 6: a TLS KeyUpdate handshake message must be rejected
|
||||
* as a fatal unexpected_message connection error when running over QUIC.
|
||||
* Feed a key_update (update_not_requested) as post-handshake CRYPTO data
|
||||
* and confirm the server refuses to process it. */
|
||||
len = fake_record(key_update, OPAQUE8_LEN, lbuffer);
|
||||
lbuffer[HANDSHAKE_HEADER_SZ] = update_not_requested;
|
||||
ExpectIntEQ(wolfSSL_provide_quic_data(tserver.ssl,
|
||||
wolfssl_encryption_application, lbuffer, len), WOLFSSL_SUCCESS);
|
||||
ret = wolfSSL_process_quic_post_handshake(tserver.ssl);
|
||||
ExpectIntEQ(ret, WC_NO_ERR_TRACE(SANITY_MSG_E));
|
||||
|
||||
QuicTestContext_free(&tclient);
|
||||
QuicTestContext_free(&tserver);
|
||||
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
printf(" test_quic_key_update_rejected: %s\n",
|
||||
EXPECT_RESULT() ? pass : fail);
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* This has gotten a bit out of hand. */
|
||||
#if (defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
|
||||
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
|
||||
@@ -2005,6 +2055,7 @@ int QuicTest(void)
|
||||
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
if ((ret = test_quic_server_hello(verbose)) != TEST_SUCCESS) goto leave;
|
||||
if ((ret = test_quic_server_hello_fail(verbose)) != TEST_SUCCESS) goto leave;
|
||||
if ((ret = test_quic_key_update_rejected(verbose)) != TEST_SUCCESS) goto leave;
|
||||
#ifdef REALLY_HAVE_ALPN_AND_SNI
|
||||
if ((ret = test_quic_alpn(verbose)) != TEST_SUCCESS) goto leave;
|
||||
#endif /* REALLY_HAVE_ALPN_AND_SNI */
|
||||
|
||||
Reference in New Issue
Block a user