Skip to content
Open
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
86 changes: 86 additions & 0 deletions tests/api/test_tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -5851,6 +5851,92 @@ int test_tls13_corrupted_finished(void)
}


/* Test that DoTls13CertificateVerify rejects a CertificateVerify whose
* signature algorithm is not one the receiver advertised.
*
* This drives the validSigAlgo == 0 path in src/tls13.c: the loop that scans
* the receiver's hashSigAlgo list for the algorithm carried in the
* CertificateVerify message. When no entry matches, validSigAlgo stays 0 and
* the message is rejected with INVALID_PARAMETER.
*
* The client sends its ClientHello (advertising its real signature
* algorithms), the server picks one of them to sign its CertificateVerify, and
* then - before the client processes the server flight - the client's accepted
* signature algorithm list is overwritten with a bogus entry. The server's
* (legitimately chosen) algorithm is therefore absent from the client's list
* at verification time, so the lookup fails.
*/
int test_tls13_certificate_verify_bad_sigalgo(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
!defined(NO_CERTS)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
int group = WOLFSSL_ECC_SECP256R1;
Suites* suites = NULL;

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

/* Constrain both peers to a single, mutually-supported key share group so
* the server never sends a HelloRetryRequest. That keeps the message
* stepping below deterministic: one ClientHello, then the full server
* flight (which contains the CertificateVerify we want to corrupt). */
ExpectIntEQ(wolfSSL_set_groups(ssl_c, &group, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, group), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_groups(ssl_s, &group, 1), WOLFSSL_SUCCESS);

/* Step 1: Client sends ClientHello, advertising its real signature
* algorithms. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);

/* Step 2: Server processes the ClientHello and emits SH + EE + Cert +
* CertVerify + Finished, signing the CertVerify with an algorithm taken
* from the list the client just advertised. */
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);

/* The ClientHello has now been sent, so changing the client's accepted
* signature algorithms no longer affects what it advertised. Replace the
* list with a single bogus pair (not a valid SignatureScheme) that the
* server cannot have used. When the client verifies the server's
* CertificateVerify, the lookup loop finds no match -> validSigAlgo == 0. */
if (EXPECT_SUCCESS()) {
suites = (Suites*)WOLFSSL_SUITES(ssl_c);
ExpectNotNull(suites);
}
if (suites != NULL) {
suites->hashSigAlgo[0] = 0xFE;
suites->hashSigAlgo[1] = 0xFE;
suites->hashSigAlgoSz = 2;
}

/* Step 3: Client processes the server flight. DoTls13CertificateVerify
* must reject the CertificateVerify with INVALID_PARAMETER. */
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WC_NO_ERR_TRACE(INVALID_PARAMETER));

wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}


/* Test the TLS 1.3 peerAuthGood fail-safe checks on both sides.
* The client branch queues a real server flight before forcing
* FIRST_REPLY_SECOND on a live handshake object, and the server branch clears
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_tls13.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ int test_tls13_0rtt_stateless_replay(void);
int test_tls13_remove_session_return(void);
int test_tls13_0rtt_ext_cache_eviction(void);
int test_tls13_corrupted_finished(void);
int test_tls13_certificate_verify_bad_sigalgo(void);
int test_tls13_peerauth_failsafe(void);
int test_tls13_hrr_bad_cookie(void);
int test_tls13_zero_inner_content_type(void);
Expand Down Expand Up @@ -120,6 +121,7 @@ int test_tls13_AEAD_limit_KU_aes128_ccm_8_sha256(void);
TEST_DECL_GROUP("tls13", test_tls13_0rtt_ext_cache_eviction), \
TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected), \
TEST_DECL_GROUP("tls13", test_tls13_corrupted_finished), \
TEST_DECL_GROUP("tls13", test_tls13_certificate_verify_bad_sigalgo), \
TEST_DECL_GROUP("tls13", test_tls13_peerauth_failsafe), \
TEST_DECL_GROUP("tls13", test_tls13_hrr_bad_cookie), \
TEST_DECL_GROUP("tls13", test_tls13_zero_inner_content_type), \
Expand Down
Loading