mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 10:50:53 +02:00
Merge pull request #10166 from JeremiahM37/test-coverage
Add negative tests for TLS handshake verification paths
This commit is contained in:
@@ -899,3 +899,225 @@ int test_tls_set_curves_list_ecc_fallback(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if !defined(WOLFSSL_NO_TLS12) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
static int test_tls12_find_client_finished(const struct test_memio_ctx* test_ctx,
|
||||
int* finishedMsgPos, int* finishedOffInMsg, int* finishedLen)
|
||||
{
|
||||
int i;
|
||||
const char* msg = NULL;
|
||||
int msgSz = 0;
|
||||
int ccsPos = -1;
|
||||
|
||||
*finishedMsgPos = -1;
|
||||
*finishedOffInMsg = -1;
|
||||
*finishedLen = 0;
|
||||
|
||||
for (i = 0; i < test_ctx->s_msg_count; i++) {
|
||||
if (test_memio_get_message(test_ctx, 0, &msg, &msgSz, i) != 0 ||
|
||||
msgSz < RECORD_HEADER_SZ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((byte)msg[0] == change_cipher_spec) {
|
||||
ccsPos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ccsPos >= 0 &&
|
||||
test_memio_get_message(test_ctx, 0, &msg, &msgSz, ccsPos + 1) == 0 &&
|
||||
msgSz >= RECORD_HEADER_SZ && (byte)msg[0] == handshake) {
|
||||
*finishedMsgPos = ccsPos + 1;
|
||||
*finishedOffInMsg = 0;
|
||||
*finishedLen = msgSz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_ctx->s_msg_count == 1) {
|
||||
int off = 0;
|
||||
|
||||
while (off + RECORD_HEADER_SZ <= test_ctx->s_len) {
|
||||
word16 recLen;
|
||||
int totalLen;
|
||||
|
||||
ato16(test_ctx->s_buff + off + 3, &recLen);
|
||||
totalLen = RECORD_HEADER_SZ + recLen;
|
||||
if (off + totalLen > test_ctx->s_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (test_ctx->s_buff[off] == change_cipher_spec) {
|
||||
int nextOff = off + totalLen;
|
||||
|
||||
if (nextOff + RECORD_HEADER_SZ > test_ctx->s_len ||
|
||||
test_ctx->s_buff[nextOff] != handshake) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ato16(test_ctx->s_buff + nextOff + 3, &recLen);
|
||||
totalLen = RECORD_HEADER_SZ + recLen;
|
||||
if (nextOff + totalLen > test_ctx->s_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*finishedMsgPos = 0;
|
||||
*finishedOffInMsg = nextOff;
|
||||
*finishedLen = totalLen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
off += totalLen;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Test that a corrupted TLS 1.2 Finished verify_data is properly rejected
|
||||
* with VERIFY_FINISHED_ERROR. We let the client queue its second flight,
|
||||
* remove the Finished record from the memio queue, allow the server to
|
||||
* process up through CCS, then inject a corrupted Finished record. */
|
||||
int test_tls12_corrupted_finished(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(WOLFSSL_NO_TLS12) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
char finishedMsg[1024];
|
||||
int finishedSz = (int)sizeof(finishedMsg);
|
||||
int finishedMsgPos = -1;
|
||||
int finishedOffInMsg = -1;
|
||||
int finishedLen = 0;
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
|
||||
|
||||
/* Step 1: Client sends ClientHello */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 2: Server sends ServerHello..ServerHelloDone */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 3: Client processes server flight and queues its second flight. */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntEQ(test_tls12_find_client_finished(&test_ctx, &finishedMsgPos,
|
||||
&finishedOffInMsg, &finishedLen), 0);
|
||||
ExpectIntGT(finishedLen, 0);
|
||||
|
||||
if (finishedOffInMsg == 0) {
|
||||
ExpectIntEQ(test_memio_copy_message(&test_ctx, 0, finishedMsg,
|
||||
&finishedSz, finishedMsgPos), 0);
|
||||
ExpectIntEQ(test_memio_drop_message(&test_ctx, 0, finishedMsgPos), 0);
|
||||
}
|
||||
else {
|
||||
ExpectIntGE(finishedSz, finishedLen);
|
||||
XMEMCPY(finishedMsg, test_ctx.s_buff + finishedOffInMsg, finishedLen);
|
||||
finishedSz = finishedLen;
|
||||
ExpectIntEQ(test_memio_modify_message_len(&test_ctx, 0,
|
||||
finishedMsgPos, finishedOffInMsg), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 4: Server processes up through CCS but blocks waiting for Finished. */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntEQ(ssl_s->msgsReceived.got_change_cipher, 1);
|
||||
ExpectNotNull(ssl_s->hsHashes);
|
||||
XMEMSET(&ssl_s->hsHashes->verifyHashes, 0xA5,
|
||||
sizeof(ssl_s->hsHashes->verifyHashes));
|
||||
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, finishedMsg,
|
||||
finishedSz), 0);
|
||||
}
|
||||
|
||||
/* Step 5: Server processes corrupted Finished and must reject it. */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WC_NO_ERR_TRACE(VERIFY_FINISHED_ERROR));
|
||||
|
||||
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.2 peerAuthGood fail-safe checks directly on both sides.
|
||||
* The client branch sets NO_PEER_VERIFY; the server branch returns a generic
|
||||
* fatal error from TICKET_SENT before sending its Finished. */
|
||||
int test_tls12_peerauth_failsafe(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(WOLFSSL_NO_TLS12) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
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 ret;
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_c->options.connectState = FIRST_REPLY_SECOND;
|
||||
ssl_c->options.peerAuthGood = 0;
|
||||
ssl_c->options.sendVerify = 0;
|
||||
ret = wolfSSL_connect(ssl_c);
|
||||
ExpectIntEQ(ret, WOLFSSL_FATAL_ERROR);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, ret),
|
||||
WC_NO_ERR_TRACE(NO_PEER_VERIFY));
|
||||
ExpectIntEQ(ssl_c->options.connectState, FIRST_REPLY_SECOND);
|
||||
}
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ctx_c = NULL;
|
||||
ctx_s = NULL;
|
||||
ssl_c = NULL;
|
||||
ssl_s = NULL;
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ssl_s->options.acceptState = TICKET_SENT;
|
||||
ssl_s->options.peerAuthGood = 0;
|
||||
ret = wolfSSL_accept(ssl_s);
|
||||
ExpectIntEQ(ret, WOLFSSL_FATAL_ERROR);
|
||||
ExpectIntEQ(ssl_s->options.acceptState, TICKET_SENT);
|
||||
}
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ int test_tls12_bad_cv_sig_alg(void);
|
||||
int test_tls12_no_null_compression(void);
|
||||
int test_tls12_etm_failed_resumption(void);
|
||||
int test_tls_set_curves_list_ecc_fallback(void);
|
||||
int test_tls12_corrupted_finished(void);
|
||||
int test_tls12_peerauth_failsafe(void);
|
||||
|
||||
#define TEST_TLS_DECLS \
|
||||
TEST_DECL_GROUP("tls", test_utils_memio_move_message), \
|
||||
@@ -45,6 +47,8 @@ int test_tls_set_curves_list_ecc_fallback(void);
|
||||
TEST_DECL_GROUP("tls", test_tls12_bad_cv_sig_alg), \
|
||||
TEST_DECL_GROUP("tls", test_tls12_no_null_compression), \
|
||||
TEST_DECL_GROUP("tls", test_tls12_etm_failed_resumption), \
|
||||
TEST_DECL_GROUP("tls", test_tls_set_curves_list_ecc_fallback)
|
||||
TEST_DECL_GROUP("tls", test_tls_set_curves_list_ecc_fallback), \
|
||||
TEST_DECL_GROUP("tls", test_tls12_corrupted_finished), \
|
||||
TEST_DECL_GROUP("tls", test_tls12_peerauth_failsafe)
|
||||
|
||||
#endif /* TESTS_API_TEST_TLS_H */
|
||||
|
||||
@@ -3058,6 +3058,7 @@ static int DERecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
||||
/* Amount actually copied. */
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int test_tls13_duplicate_extension(void)
|
||||
@@ -3929,3 +3930,453 @@ int test_tls13_short_session_ticket(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
|
||||
/* Test that a corrupted TLS 1.3 Finished verify_data is properly rejected
|
||||
* with VERIFY_FINISHED_ERROR. We run the handshake step-by-step and corrupt
|
||||
* the server's client_write_MAC_secret before it processes the client's
|
||||
* Finished, causing the HMAC comparison to fail.
|
||||
*/
|
||||
int test_tls13_corrupted_finished(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
|
||||
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);
|
||||
|
||||
/* Step 1: Client sends ClientHello */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 2: Server processes CH, sends SH + EE + Cert + CV + Finished */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 3: Client processes server flight, verifies server Finished,
|
||||
* sends client Finished */
|
||||
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
|
||||
/* Corrupt the server's client_write_MAC_secret so that when it computes
|
||||
* the expected Finished HMAC, the result won't match the client's actual
|
||||
* Finished message. */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
XMEMSET(ssl_s->keys.client_write_MAC_secret, 0xFF,
|
||||
sizeof(ssl_s->keys.client_write_MAC_secret));
|
||||
}
|
||||
|
||||
/* Step 4: Server processes client Finished - should fail */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WC_NO_ERR_TRACE(VERIFY_FINISHED_ERROR));
|
||||
|
||||
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
|
||||
* peerAuthGood just before processing the client's Finished.
|
||||
*/
|
||||
int test_tls13_peerauth_failsafe(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
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 ret;
|
||||
|
||||
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);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
/* Queue ClientHello and server flight. */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
ssl_c->options.peerAuthGood = 0;
|
||||
ssl_c->options.sendVerify = 0;
|
||||
ssl_c->options.connectState = FIRST_REPLY_SECOND;
|
||||
ret = wolfSSL_connect(ssl_c);
|
||||
ExpectIntEQ(ret, WOLFSSL_FATAL_ERROR);
|
||||
ExpectIntEQ(ssl_c->options.connectState, FIRST_REPLY_SECOND);
|
||||
}
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ctx_c = NULL;
|
||||
ctx_s = NULL;
|
||||
ssl_c = NULL;
|
||||
ssl_s = NULL;
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
|
||||
ssl_s->options.peerAuthGood = 0;
|
||||
ret = wolfSSL_accept(ssl_s);
|
||||
ExpectIntEQ(ret, WOLFSSL_FATAL_ERROR);
|
||||
ExpectIntEQ(ssl_s->options.peerAuthGood, 0);
|
||||
}
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
|
||||
/* Test that a corrupted HRR cookie HMAC is rejected with HRR_COOKIE_ERROR. */
|
||||
int test_tls13_hrr_bad_cookie(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
defined(WOLFSSL_SEND_HRR_COOKIE) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
|
||||
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);
|
||||
|
||||
ExpectIntEQ(wolfSSL_send_hrr_cookie(ssl_s, NULL, 0), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_NoKeyShares(ssl_c), WOLFSSL_SUCCESS);
|
||||
|
||||
/* Step 1: Client sends CH1 (no key shares) */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 2: Server sends HRR with cookie */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Step 3: Client processes HRR, sends CH2 with cookie */
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
/* Corrupt the server-side cookie secret after HRR so CH2's cookie no longer
|
||||
* verifies in TlsCheckCookie(). */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectNotNull(ssl_s->buffers.tls13CookieSecret.buffer);
|
||||
ExpectIntGT(ssl_s->buffers.tls13CookieSecret.length, 0);
|
||||
ssl_s->buffers.tls13CookieSecret.buffer[
|
||||
ssl_s->buffers.tls13CookieSecret.length - 1] ^= 0xFF;
|
||||
}
|
||||
|
||||
/* Step 4: Server processes corrupted CH2 - should fail */
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WC_NO_ERR_TRACE(HRR_COOKIE_ERROR));
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Test that a TLS 1.3 encrypted record whose inner content type resolves to
|
||||
* zero is rejected in removeMsgInnerPadding() with PARSE_ERROR and an
|
||||
* unexpected_message alert. */
|
||||
int test_tls13_zero_inner_content_type(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
WOLFSSL_ALERT_HISTORY h;
|
||||
byte record[64];
|
||||
byte dummy = 0;
|
||||
char readBuf[8];
|
||||
int recordSz;
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
XMEMSET(&h, 0, sizeof(h));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(ssl_s), 0);
|
||||
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntEQ(test_ctx.c_len, 0);
|
||||
ExpectIntEQ(test_ctx.s_len, 0);
|
||||
|
||||
recordSz = BuildTls13Message(ssl_c, record, (int)sizeof(record), &dummy,
|
||||
0, no_type, 0, 0, 0);
|
||||
ExpectIntGT(recordSz, 0);
|
||||
ExpectIntEQ(wolfSSL_inject(ssl_s, record, recordSz), WOLFSSL_SUCCESS);
|
||||
}
|
||||
|
||||
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, (int)sizeof(readBuf)), -1);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WC_NO_ERR_TRACE(PARSE_ERROR));
|
||||
ExpectIntEQ(wolfSSL_get_alert_history(ssl_s, &h), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(h.last_tx.code, unexpected_message);
|
||||
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Test that a TLS 1.3-capable client rejects downgrade sentinels in a
|
||||
* downgraded ServerHello random for both TLS 1.2 and TLS 1.1-or-lower. */
|
||||
int test_tls13_downgrade_sentinel(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
WOLFSSL_ALERT_HISTORY h;
|
||||
int randomOff = 11 + 24;
|
||||
static const byte downgradeTls12[8] = {
|
||||
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01
|
||||
};
|
||||
#ifndef NO_OLD_TLS
|
||||
static const byte downgradeTls11[8] = {
|
||||
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
XMEMSET(&h, 0, sizeof(h));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLS_client_method, wolfTLSv1_2_server_method), 0);
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntGT(test_ctx.c_len, randomOff + (int)sizeof(downgradeTls12));
|
||||
XMEMCPY(test_ctx.c_buff + randomOff, downgradeTls12,
|
||||
sizeof(downgradeTls12));
|
||||
}
|
||||
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WC_NO_ERR_TRACE(VERSION_ERROR));
|
||||
ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS);
|
||||
ExpectTrue(h.last_tx.code == illegal_parameter ||
|
||||
h.last_tx.code == wolfssl_alert_protocol_version);
|
||||
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
|
||||
#ifndef NO_OLD_TLS
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
XMEMSET(&h, 0, sizeof(h));
|
||||
ctx_c = NULL;
|
||||
ctx_s = NULL;
|
||||
ssl_c = NULL;
|
||||
ssl_s = NULL;
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLS_client_method, wolfTLSv1_1_server_method), 0);
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntGT(test_ctx.c_len, randomOff + (int)sizeof(downgradeTls11));
|
||||
XMEMCPY(test_ctx.c_buff + randomOff, downgradeTls11,
|
||||
sizeof(downgradeTls11));
|
||||
}
|
||||
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WC_NO_ERR_TRACE(VERSION_ERROR));
|
||||
ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS);
|
||||
ExpectTrue(h.last_tx.code == illegal_parameter ||
|
||||
h.last_tx.code == wolfssl_alert_protocol_version);
|
||||
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Test that a TLS 1.3 client rejects ServerHello cipher suites that are not
|
||||
* TLS 1.3 suites or were not offered by the client. */
|
||||
int test_tls13_serverhello_bad_cipher_suites(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
|
||||
!defined(WOLFSSL_NO_TLS12) && \
|
||||
defined(BUILD_TLS_AES_128_GCM_SHA256) && \
|
||||
defined(BUILD_TLS_AES_256_GCM_SHA384)
|
||||
WOLFSSL_CTX *ctx_c = NULL;
|
||||
WOLFSSL_CTX *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL;
|
||||
WOLFSSL *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
WOLFSSL_CTX *ctx12_c = NULL;
|
||||
WOLFSSL_CTX *ctx12_s = NULL;
|
||||
WOLFSSL *ssl12_c = NULL;
|
||||
WOLFSSL *ssl12_s = NULL;
|
||||
struct test_memio_ctx test_ctx12;
|
||||
int suiteOff;
|
||||
byte tls12Suite0 = 0;
|
||||
byte tls12Suite = 0;
|
||||
|
||||
XMEMSET(&test_ctx12, 0, sizeof(test_ctx12));
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx12, &ctx12_c, &ctx12_s, &ssl12_c,
|
||||
&ssl12_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl12_c, ssl12_s, 10, NULL), 0);
|
||||
if (EXPECT_SUCCESS()) {
|
||||
tls12Suite0 = ssl12_c->options.cipherSuite0;
|
||||
tls12Suite = ssl12_c->options.cipherSuite;
|
||||
ExpectIntNE(tls12Suite0, TLS13_BYTE);
|
||||
}
|
||||
wolfSSL_free(ssl12_c);
|
||||
wolfSSL_CTX_free(ctx12_c);
|
||||
wolfSSL_free(ssl12_s);
|
||||
wolfSSL_CTX_free(ctx12_s);
|
||||
|
||||
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);
|
||||
|
||||
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, "TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
suiteOff = 44 + (byte)test_ctx.c_buff[43];
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntGT(test_ctx.c_len, suiteOff + 1);
|
||||
ExpectNotNull(ssl_c->suites);
|
||||
ssl_c->suites->suiteSz = 2;
|
||||
ssl_c->suites->suites[0] = tls12Suite0;
|
||||
ssl_c->suites->suites[1] = tls12Suite;
|
||||
test_ctx.c_buff[suiteOff + 0] = tls12Suite0;
|
||||
test_ctx.c_buff[suiteOff + 1] = tls12Suite;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
||||
ctx_c = NULL;
|
||||
ctx_s = NULL;
|
||||
ssl_c = NULL;
|
||||
ssl_s = NULL;
|
||||
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
||||
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
||||
|
||||
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, "TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
|
||||
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
|
||||
WOLFSSL_ERROR_WANT_READ);
|
||||
|
||||
suiteOff = 44 + (byte)test_ctx.c_buff[43];
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectIntGT(test_ctx.c_len, suiteOff + 1);
|
||||
test_ctx.c_buff[suiteOff + 0] = TLS13_BYTE;
|
||||
test_ctx.c_buff[suiteOff + 1] = TLS_AES_256_GCM_SHA384;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
+13
-1
@@ -46,6 +46,12 @@ int test_tls13_derive_keys_no_key(void);
|
||||
int test_tls13_pqc_hybrid_truncated_keyshare(void);
|
||||
int test_tls13_short_session_ticket(void);
|
||||
int test_tls13_early_data_0rtt_replay(void);
|
||||
int test_tls13_corrupted_finished(void);
|
||||
int test_tls13_peerauth_failsafe(void);
|
||||
int test_tls13_hrr_bad_cookie(void);
|
||||
int test_tls13_zero_inner_content_type(void);
|
||||
int test_tls13_downgrade_sentinel(void);
|
||||
int test_tls13_serverhello_bad_cipher_suites(void);
|
||||
|
||||
#define TEST_TLS13_DECLS \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_apis), \
|
||||
@@ -69,6 +75,12 @@ int test_tls13_early_data_0rtt_replay(void);
|
||||
TEST_DECL_GROUP("tls13", test_tls13_pqc_hybrid_truncated_keyshare), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_short_session_ticket), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_early_data_0rtt_replay), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected)
|
||||
TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_corrupted_finished), \
|
||||
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), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_downgrade_sentinel), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_serverhello_bad_cipher_suites)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_TLS13_H */
|
||||
|
||||
Reference in New Issue
Block a user