diff --git a/src/dtls13.c b/src/dtls13.c index 265ca7a603..615423df78 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -93,7 +93,7 @@ typedef struct Dtls13RecordPlaintextHeader { #define DTLS13_SEQ_8_LEN 1 /* fixed bits mask to detect unified header */ -#define DTLS13_FIXED_BITS_MASK (0x111 << 5) +#define DTLS13_FIXED_BITS_MASK (0x7 << 5) /* fixed bits value to detect unified header */ #define DTLS13_FIXED_BITS (0x1 << 5) /* ConnectionID present bit in the unified header flags */ diff --git a/src/quic.c b/src/quic.c index 21f64903bb..2d6e4a6c87 100644 --- a/src/quic.c +++ b/src/quic.c @@ -72,7 +72,7 @@ static QuicRecord *quic_record_make(WOLFSSL *ssl, qr = (QuicRecord*)XMALLOC(sizeof(*qr), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (qr) { - memset(qr, 0, sizeof(*qr)); + XMEMSET(qr, 0, sizeof(*qr)); qr->level = level; if (level == wolfssl_encryption_early_data) { qr->capacity = qr->len = (word32)len; diff --git a/src/tls.c b/src/tls.c index 130660425b..d6da604378 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2849,9 +2849,14 @@ static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz) { TCA* tca = list; - while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED && - idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz)) + while (tca) { + if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) + break; + if (tca->type == type && idSz == tca->idSz && + XMEMCMP(id, tca->id, idSz) == 0) + break; tca = tca->next; + } return tca; } diff --git a/tests/api.c b/tests/api.c index a6df4e1450..0015519344 100644 --- a/tests/api.c +++ b/tests/api.c @@ -32829,6 +32829,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret), TEST_DECL(test_certificate_authorities_certificate_request), TEST_DECL(test_certificate_authorities_client_hello), + TEST_DECL(test_TLSX_TCA_Find), TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation), TEST_DECL(test_wolfSSL_SCR_Reconnect), TEST_DECL(test_wolfSSL_SCR_check_enabled), diff --git a/tests/api/test_tls_ext.c b/tests/api/test_tls_ext.c index cf15058507..001a7167ff 100644 --- a/tests/api/test_tls_ext.c +++ b/tests/api/test_tls_ext.c @@ -323,6 +323,138 @@ static int certificate_authorities_server_cb(WOLFSSL *ssl, void *_arg) { } #endif +#if defined(HAVE_TRUSTED_CA) && !defined(NO_SHA) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) +/* Walk the TLSX list to find an extension by type. Avoids calling the + * WOLFSSL_LOCAL TLSX_Find which is not available in shared library builds. */ +static TLSX* test_TLSX_find_ext(TLSX* list, TLSX_Type type) +{ + while (list) { + if (list->type == type) + return list; + list = list->next; + } + return NULL; +} +#endif + +int test_TLSX_TCA_Find(void) +{ + EXPECT_DECLS; +#if defined(HAVE_TRUSTED_CA) && !defined(NO_SHA) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) + /* Two different 20-byte SHA1 ids */ + byte id_A[WC_SHA_DIGEST_SIZE]; + byte id_B[WC_SHA_DIGEST_SIZE]; + TLSX* ext; + + XMEMSET(id_A, 0xAA, sizeof(id_A)); + XMEMSET(id_B, 0xBB, sizeof(id_B)); + + /* Test 1: Exact match - same type and same id should match */ + { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + + 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); + + /* Server has KEY_SHA1 with id_A */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_s, WOLFSSL_TRUSTED_CA_KEY_SHA1, + id_A, sizeof(id_A)), WOLFSSL_SUCCESS); + /* Client sends KEY_SHA1 with id_A (same) */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_c, WOLFSSL_TRUSTED_CA_KEY_SHA1, + id_A, sizeof(id_A)), WOLFSSL_SUCCESS); + + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + /* Server should have found a match and responded */ + ext = test_TLSX_find_ext(ssl_c ? ssl_c->extensions : NULL, + TLSX_TRUSTED_CA_KEYS); + ExpectNotNull(ext); + if (EXPECT_SUCCESS()) + ExpectIntEQ(ext->resp, 1); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } + + /* Test 2: Same type, different id - should NOT match. + * This is the key test that exposes the logic bug in TLSX_TCA_Find + * where matching on type alone (without checking id content) causes + * a false positive. */ + { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + + 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); + + /* Server has KEY_SHA1 with id_A */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_s, WOLFSSL_TRUSTED_CA_KEY_SHA1, + id_A, sizeof(id_A)), WOLFSSL_SUCCESS); + /* Client sends KEY_SHA1 with id_B (different!) */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_c, WOLFSSL_TRUSTED_CA_KEY_SHA1, + id_B, sizeof(id_B)), WOLFSSL_SUCCESS); + + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + /* Server should NOT have found a match - ids differ */ + ext = test_TLSX_find_ext(ssl_c ? ssl_c->extensions : NULL, + TLSX_TRUSTED_CA_KEYS); + ExpectNotNull(ext); + if (EXPECT_SUCCESS()) + ExpectIntEQ(ext->resp, 0); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } + + /* Test 3: PRE_AGREED should match any server entry */ + { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + + 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); + + /* Server has KEY_SHA1 with id_A */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_s, WOLFSSL_TRUSTED_CA_KEY_SHA1, + id_A, sizeof(id_A)), WOLFSSL_SUCCESS); + /* Client sends PRE_AGREED (no id needed) */ + ExpectIntEQ(wolfSSL_UseTrustedCA(ssl_c, WOLFSSL_TRUSTED_CA_PRE_AGREED, + NULL, 0), WOLFSSL_SUCCESS); + + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + /* Server should have matched (PRE_AGREED matches anything) */ + ext = test_TLSX_find_ext(ssl_c ? ssl_c->extensions : NULL, + TLSX_TRUSTED_CA_KEYS); + ExpectNotNull(ext); + if (EXPECT_SUCCESS()) + ExpectIntEQ(ext->resp, 1); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } +#endif + return EXPECT_RESULT(); +} + int test_certificate_authorities_client_hello(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ diff --git a/tests/api/test_tls_ext.h b/tests/api/test_tls_ext.h index 3506d02e96..2ec1da95c8 100644 --- a/tests/api/test_tls_ext.h +++ b/tests/api/test_tls_ext.h @@ -26,5 +26,6 @@ int test_tls_ems_downgrade(void); int test_wolfSSL_DisableExtendedMasterSecret(void); int test_certificate_authorities_certificate_request(void); int test_certificate_authorities_client_hello(void); +int test_TLSX_TCA_Find(void); #endif /* TESTS_API_TEST_TLS_EMS_H */