diff --git a/tests/api/test_tls.c b/tests/api/test_tls.c index 565006171b..03459d7f3e 100644 --- a/tests/api/test_tls.c +++ b/tests/api/test_tls.c @@ -768,3 +768,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(); +} diff --git a/tests/api/test_tls.h b/tests/api/test_tls.h index 46d5404344..b4c1d6a2c0 100644 --- a/tests/api/test_tls.h +++ b/tests/api/test_tls.h @@ -31,6 +31,8 @@ int test_tls_certreq_order(void); int test_tls12_bad_cv_sig_alg(void); int test_tls12_no_null_compression(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), \ @@ -41,6 +43,8 @@ int test_tls_set_curves_list_ecc_fallback(void); TEST_DECL_GROUP("tls", test_tls_certreq_order), \ TEST_DECL_GROUP("tls", test_tls12_bad_cv_sig_alg), \ TEST_DECL_GROUP("tls", test_tls12_no_null_compression), \ - 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 */ diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 63ddffb7aa..728122db08 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -2866,6 +2866,7 @@ static int DERecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) /* Amount actually copied. */ return len; } + #endif int test_tls13_duplicate_extension(void) @@ -3645,3 +3646,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(); +} diff --git a/tests/api/test_tls13.h b/tests/api/test_tls13.h index c8eaa3b7fa..b2b17fc003 100644 --- a/tests/api/test_tls13.h +++ b/tests/api/test_tls13.h @@ -44,6 +44,12 @@ int test_tls13_cert_req_sigalgs(void); 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_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), \ @@ -65,6 +71,12 @@ int test_tls13_short_session_ticket(void); TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs), \ TEST_DECL_GROUP("tls13", test_tls13_derive_keys_no_key), \ 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_short_session_ticket), \ + 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 */