mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
2859 lines
124 KiB
C
2859 lines
124 KiB
C
/* test_tls_bounds.h
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <tests/unit.h>
|
|
#include <tests/utils.h>
|
|
#include <tests/api/api.h>
|
|
#include <tests/api/test_tls_bounds.h>
|
|
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/internal.h>
|
|
|
|
/* Named guards for the regions below: each covers a file-scope helper or
|
|
* fixture plus the test(s) that use it, so the condition is written once
|
|
* and the region and the in-body guard cannot drift apart. */
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && \
|
|
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(NO_CERTS)
|
|
#define TEST_TLS_BOUNDS_CSR2_REQUESTS
|
|
#endif
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && \
|
|
defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(NO_WOLFSSL_SERVER) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && defined(HAVE_OCSP)
|
|
#define TEST_TLS_BOUNDS_CSR_STATUS_CB
|
|
#endif
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && \
|
|
!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS_OCSP_MULTI) && \
|
|
defined(HAVE_CERTIFICATE_STATUS_REQUEST) && defined(HAVE_OCSP) && \
|
|
!defined(NO_RSA) && !defined(NO_SHA256)
|
|
#define TEST_TLS_BOUNDS_OCSP_CHAIN
|
|
#endif
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SUPPORTED_CURVES) && \
|
|
(defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && !defined(NO_PSK) && \
|
|
defined(HAVE_AESGCM) && !defined(NO_AES) && !defined(NO_SHA256)
|
|
#define TEST_TLS_BOUNDS_POPULATE_EXT
|
|
#endif
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && \
|
|
defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
!defined(NO_WOLFSSL_SERVER) && \
|
|
!defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY)
|
|
#define TEST_TLS_BOUNDS_CSR_PARSE
|
|
#endif
|
|
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \
|
|
!defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT)
|
|
#define TEST_TLS_BOUNDS_SESSION_TICKET_FF
|
|
#endif
|
|
/* test_tls_bounds_load_server_cert() and every test body that calls it. The
|
|
* certificate and key it loads are RSA and come from the filesystem, so a
|
|
* build without either has neither the helper nor its callers. */
|
|
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_CERTS) && !defined(NO_RSA) && \
|
|
!defined(NO_FILESYSTEM)
|
|
#define TEST_TLS_BOUNDS_SERVER_CERT
|
|
#endif
|
|
|
|
/* Each helper below is called only from test bodies whose feature guards differ
|
|
* from one another, so no single condition describes "some caller is compiled
|
|
* in" -- a shared build, for instance, compiles out every WOLFSSL_TEST_STATIC_BUILD
|
|
* body at once. Mark them instead of trying to track the union by hand. */
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define TEST_TLS_BOUNDS_UNUSED __attribute__((unused))
|
|
#else
|
|
#define TEST_TLS_BOUNDS_UNUSED
|
|
#endif
|
|
|
|
/* c32to24() (wolfcrypt/src/misc.c) is only externally linkable when NO_INLINE
|
|
* is defined; this build inlines it into each translation unit that already
|
|
* needs it, so it is not visible here. Same 3-byte big-endian length write,
|
|
* spelled out locally. */
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static void test_tls_bounds_c32to24(word32 in, byte* out)
|
|
{
|
|
out[0] = (byte)(in >> 16);
|
|
out[1] = (byte)(in >> 8);
|
|
out[2] = (byte)in;
|
|
}
|
|
|
|
#ifdef TEST_TLS_BOUNDS_SERVER_CERT
|
|
/* SetSSL_CTX() (InitSSL()'s caller) fails wolfSSL_new() with NO_PRIVATE_KEY
|
|
* for a server-side ssl with no certificate/key and no PSK/anon/cert-setup-cb
|
|
* fallback, so every server-side ssl created only to unit-test a WOLFSSL_LOCAL
|
|
* function directly (never running a real handshake) still needs a loaded
|
|
* cert/key to get past wolfSSL_new() at all. */
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_tls_bounds_load_server_cert(WOLFSSL_CTX* ctx)
|
|
{
|
|
EXPECT_DECLS;
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, "./certs/server-cert.pem",
|
|
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, "./certs/server-key.pem",
|
|
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_UseSNI - the extensions list argument is always &ssl->extensions or
|
|
* &ctx->extensions (wolfSSL_UseSNI / wolfSSL_CTX_UseSNI), or &ech->extensions
|
|
* (the ECH echo path in TLSX_SNI_Parse) - always the address of a struct
|
|
* member, never NULL. The "extensions == NULL" half of the guard has no
|
|
* reachable caller and is excluded (argued in the report, not retested here).
|
|
* The "data == NULL" half, the host-name-length guard, and the duplicate-type
|
|
* removal in the linked list are all reachable through wolfSSL_UseSNI(). */
|
|
int test_TLSX_UseSNI_bounds(void)
|
|
{
|
|
#if defined(HAVE_SNI) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
char longName[WOLFSSL_HOST_NAME_MAX + 1];
|
|
|
|
XMEMSET(longName, 'a', sizeof(longName) - 1);
|
|
longName[sizeof(longName) - 1] = '\0';
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* data == NULL -> BAD_FUNC_ARG (extensions is always non-NULL here). */
|
|
ExpectIntEQ(wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, NULL, 8),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* type == HOST_NAME && size >= MAX -> BAD_LENGTH_E. */
|
|
ExpectIntEQ(wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, longName,
|
|
(word16)XSTRLEN(longName)), WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
|
|
|
/* type != HOST_NAME: the length guard is skipped regardless of size (the
|
|
* BAD_LENGTH_E path is not taken), independence for the first operand of
|
|
* the (type == HOST_NAME) && (size >= MAX) guard. WOLFSSL_SNI_HOST_NAME
|
|
* is the only type TLSX_SNI_New() accepts, so this then fails later,
|
|
* inside TLSX_SNI_New()'s own type switch, with MEMORY_E - a different
|
|
* and later guard than the one under test here. */
|
|
ExpectIntEQ(wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME + 1, longName,
|
|
(word16)XSTRLEN(longName)), WC_NO_ERR_TRACE(MEMORY_E));
|
|
|
|
/* type == HOST_NAME && size < MAX -> accepted; also the first insert,
|
|
* so the duplicate-type list walk has nothing to match yet. */
|
|
ExpectIntEQ(wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "a.example.com",
|
|
13), WOLFSSL_SUCCESS);
|
|
|
|
/* A second insert: the walk finds sni->next->type == type on the first
|
|
* node and removes the duplicate.
|
|
*
|
|
* "sni->next && sni->next->type == type" (the duplicate-removal check)
|
|
* is not driven for independence anywhere in this file: WOLFSSL_SNI_
|
|
* HOST_NAME is the only type TLSX_SNI_New() will ever construct (its
|
|
* switch on sni->type frees and rejects anything else), so every node
|
|
* that ever exists in the list has type == WOLFSSL_SNI_HOST_NAME, and
|
|
* "type" here (the argument of the call reaching this loop) must also
|
|
* be WOLFSSL_SNI_HOST_NAME or TLSX_UseSNI() would already have returned
|
|
* MEMORY_E from TLSX_SNI_New() before the loop is reached. So whenever
|
|
* "sni->next" is true, "sni->next->type == type" is true too - the loop
|
|
* always removes the one prior node on its first check and breaks,
|
|
* which also means a second loop iteration (where sni->next could be
|
|
* NULL) is never reached. Both operands are pinned to true on every
|
|
* real execution; excluded (family 4: contradicted by the callee
|
|
* postcondition of TLSX_SNI_New()). */
|
|
ExpectIntEQ(wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "c.example.com",
|
|
13), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_UseALPN - extensions is always &ssl->extensions (wolfSSL_UseALPN());
|
|
* unreachable-NULL, excluded. data == NULL: wolfSSL_UseALPN() only calls
|
|
* TLSX_UseALPN() with tokens produced by XSTRTOK(), which are never NULL
|
|
* inside the "while (token[idx] != NULL)" loop, so the only way to reach
|
|
* TLSX_UseALPN() with a NULL data pointer at all is to call it directly. */
|
|
int test_TLSX_UseALPN_bounds(void)
|
|
{
|
|
#if defined(HAVE_ALPN) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
ExpectIntEQ(wolfSSL_UseALPN(ssl, (char*)"http/1.1", 8,
|
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS);
|
|
|
|
#ifdef WOLFSSL_TEST_STATIC_BUILD
|
|
/* No wrapper can pass data == NULL; extensions == NULL is likewise
|
|
* unreachable through any caller (always &ssl->extensions), and is
|
|
* exercised here only to document that the guard exists, not to claim
|
|
* it as a caller-reachable pair. */
|
|
ExpectIntEQ(TLSX_UseALPN(&ssl->extensions, NULL, 4,
|
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH, ssl->heap),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_UseMaxFragment - extensions always &ssl->extensions / &ctx->extensions;
|
|
* unreachable-NULL, excluded. mfl < MIN and mfl > MAX are both reachable
|
|
* through the public wrapper with an out-of-range code, alongside a valid
|
|
* in-range call. */
|
|
int test_TLSX_UseMaxFragment_bounds(void)
|
|
{
|
|
#if defined(HAVE_MAX_FRAGMENT) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* mfl < WOLFSSL_MFL_MIN (0 is below WOLFSSL_MFL_2_9 == 1). */
|
|
ExpectIntEQ(wolfSSL_UseMaxFragment(ssl, WOLFSSL_MFL_DISABLED),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* mfl > WOLFSSL_MFL_MAX (WOLFSSL_MFL_2_8 == 6 is the maximum code). */
|
|
ExpectIntEQ(wolfSSL_UseMaxFragment(ssl, (byte)(WOLFSSL_MFL_MAX + 1)),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* In range: accepted. */
|
|
ExpectIntEQ(wolfSSL_UseMaxFragment(ssl, WOLFSSL_MFL_2_11),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_UseCertificateStatusRequest - extensions is always &ssl->extensions /
|
|
* &ctx->extensions (wolfSSL_UseOCSPStapling() / _CTX_); unreachable-NULL,
|
|
* excluded. status_type != WOLFSSL_CSR_OCSP is reachable directly: the
|
|
* wrapper passes the caller's status_type straight through with no
|
|
* validation of its own. */
|
|
int test_TLSX_UseCertificateStatusRequest_bounds(void)
|
|
{
|
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* status_type != WOLFSSL_CSR_OCSP. */
|
|
ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP + 1, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Valid request. */
|
|
ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP,
|
|
WOLFSSL_CSR_OCSP_USE_NONCE), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_UseCertificateStatusRequestV2 - same pattern as V1 above. */
|
|
int test_TLSX_UseCertificateStatusRequestV2_bounds(void)
|
|
{
|
|
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* Neither WOLFSSL_CSR2_OCSP nor WOLFSSL_CSR2_OCSP_MULTI: both operands
|
|
* of "status_type != OCSP && status_type != OCSP_MULTI" true. */
|
|
ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(ssl,
|
|
WOLFSSL_CSR2_OCSP_MULTI + 1, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* status_type == OCSP_MULTI: first operand true (MULTI != OCSP), second
|
|
* operand false (MULTI == MULTI) - independence for the second operand,
|
|
* paired against the invalid-type call above. */
|
|
ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP_MULTI,
|
|
WOLFSSL_CSR2_OCSP_USE_NONCE), WOLFSSL_SUCCESS);
|
|
|
|
/* status_type == OCSP: first operand false, short-circuits past the
|
|
* second - independence for the first operand. */
|
|
ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP,
|
|
WOLFSSL_CSR2_OCSP_USE_NONCE), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_SupportExtensions() - "return ssl && (IsTLS(ssl) ||
|
|
* ssl->version.major == DTLS_MAJOR);" reached through the WOLFSSL_TEST_VIS
|
|
* TLSX_WriteRequest(), which calls it as its leading guard.
|
|
*
|
|
* With WOLFSSL_DTLS defined (as it is in this build), IsTLS() itself already
|
|
* returns true for ssl->version.major == DTLS_MAJOR (it has its own
|
|
* "#ifdef WOLFSSL_DTLS if (ssl->version.major == DTLS_MAJOR) return 1;"
|
|
* check). So the third operand here can only be evaluated (IsTLS() false)
|
|
* when major is neither a valid TLS major/minor pair nor DTLS_MAJOR - and in
|
|
* that same case the third operand's own check of major == DTLS_MAJOR is
|
|
* false too. The third operand's true side is therefore contradicted by
|
|
* IsTLS()'s postcondition in this build and is excluded (family 4); only its
|
|
* (always-false-when-reached) value is exercised below, alongside the first
|
|
* and second operands. */
|
|
int test_TLSX_SupportExtensions_bounds(void)
|
|
{
|
|
#if !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte out[512];
|
|
word32 offset = 0;
|
|
|
|
/* ssl == NULL: the leading operand alone decides the result. */
|
|
ExpectIntEQ(TLSX_WriteRequest(NULL, out, client_hello, &offset), 0);
|
|
|
|
/* A live ssl object: IsTLS(ssl) true (real major/minor), so ssl &&
|
|
* IsTLS(ssl) is already true and the third operand is never reached -
|
|
* independence for the first and second operands. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
|
|
/* Corrupt ssl->version.major to a value IsTLS() does not recognize
|
|
* (neither SSLv3_MAJOR nor DTLS_MAJOR): IsTLS(ssl) is now false, and the
|
|
* third operand - checking that very same field for DTLS_MAJOR - is
|
|
* false too. This is the only way to make IsTLS(ssl) false at all: every
|
|
* ssl created through a real method sets a recognized major/minor. */
|
|
if (ssl != NULL) {
|
|
ssl->version.major = 0;
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
ssl->version.major = SSLv3_MAJOR;
|
|
ssl->version.minor = TLSv1_2_MINOR;
|
|
}
|
|
|
|
/* TLSX_WriteRequest()'s own leading guard is
|
|
* "!TLSX_SupportExtensions(ssl) || output == NULL": a supported ssl with
|
|
* output == NULL exercises the second operand independently of the
|
|
* ssl == NULL call above. */
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, NULL, client_hello, &offset), 0);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_EarlyData_Use() - "extension->val = (WOLFSSL_IS_QUIC(ssl) &&
|
|
* is_response && maxSz > 0) ? WOLFSSL_MAX_32BIT : maxSz;" - this build has no
|
|
* WOLFSSL_QUIC, so WOLFSSL_IS_QUIC() expands to the literal 0: the first
|
|
* operand is a compile-time constant false in every translation unit of this
|
|
* binary. Because of the left-to-right && short circuit, is_response and
|
|
* maxSz > 0 can never be evaluated either - all three operands of this
|
|
* decision are unreachable in this configuration. Excluded (family 3: fixed
|
|
* by the branch/config that reaches it).
|
|
* No test body: nothing to drive. */
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_CSR2_InitRequests(), TLSX_CSR2_ForceRequest(), TLSX_CSR_GetRequest_ex()
|
|
* are WOLFSSL_LOCAL with no public wrapper; each is unit-tested directly by
|
|
* building the minimal extension/context state each one dereferences. */
|
|
int test_TLSX_CSR2_InitRequests_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_CSR2_REQUESTS) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
DecodedCert cert;
|
|
TLSX* ext = NULL;
|
|
CertificateStatusRequestItemV2* csr2;
|
|
|
|
XMEMSET(&cert, 0, sizeof(cert));
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
|
|
WOLFSSL_CSR2_OCSP, 0, ssl->heap, ssl->devId), WOLFSSL_SUCCESS);
|
|
if (EXPECT_SUCCESS())
|
|
ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
|
|
ExpectNotNull(ext);
|
|
|
|
if (ext != NULL) {
|
|
csr2 = (CertificateStatusRequestItemV2*)ext->data;
|
|
|
|
/* isPeer == 0: "!isPeer" true, short-circuits past requests != 0. */
|
|
ExpectIntEQ(TLSX_CSR2_InitRequests(ssl->extensions, &cert, 0,
|
|
ssl->heap), 0);
|
|
|
|
/* isPeer == 1, requests == 0: both operands false, falls through to
|
|
* build the request from the (empty) DecodedCert. */
|
|
ExpectIntEQ(TLSX_CSR2_InitRequests(ssl->extensions, &cert, 1,
|
|
ssl->heap), 0);
|
|
ExpectIntEQ(csr2->requests, 1);
|
|
|
|
/* isPeer == 1, requests != 0: "!isPeer" false, "requests != 0"
|
|
* true - independence for the second operand. */
|
|
ExpectIntEQ(TLSX_CSR2_InitRequests(ssl->extensions, &cert, 1,
|
|
ssl->heap), 0);
|
|
ExpectIntEQ(csr2->requests, 1);
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
int test_TLSX_CSR2_ForceRequest_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_CSR2_REQUESTS) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
TLSX* ext = NULL;
|
|
CertificateStatusRequestItemV2* csr2;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
|
|
WOLFSSL_CSR2_OCSP, 0, ssl->heap, ssl->devId), WOLFSSL_SUCCESS);
|
|
if (EXPECT_SUCCESS())
|
|
ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
|
|
ExpectNotNull(ext);
|
|
|
|
if (ext != NULL) {
|
|
csr2 = (CertificateStatusRequestItemV2*)ext->data;
|
|
|
|
/* ocspEnabled false: whole AND is false regardless of requests. */
|
|
SSL_CM(ssl)->ocspEnabled = 0;
|
|
csr2->requests = 1;
|
|
ExpectIntEQ(TLSX_CSR2_ForceRequest(ssl), WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL));
|
|
|
|
/* ocspEnabled true, requests == 0: first operand true, second
|
|
* false - independence for the second operand's false side. */
|
|
SSL_CM(ssl)->ocspEnabled = 1;
|
|
csr2->requests = 0;
|
|
ExpectIntEQ(TLSX_CSR2_ForceRequest(ssl), WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL));
|
|
|
|
/* ocspEnabled true, requests >= 1: both operands true, so the
|
|
* lookup runs. No responder is configured on this CertManager, so
|
|
* CheckOcspRequest() reports BAD_FUNC_ARG on its own ocsp == NULL
|
|
* guard rather than reaching the network. */
|
|
csr2->requests = 1;
|
|
ExpectIntEQ(TLSX_CSR2_ForceRequest(ssl), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
int test_TLSX_CSR_GetRequest_ex_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) && !defined(WOLFSSL_NO_TLS12) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
/* A TLS 1.2-only method keeps IsAtLeastTLSv1_3(csr->ssl->version) false,
|
|
* so the idx == 0 branch below is deterministic without negotiating a
|
|
* version first. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* csr == NULL: no TLSX_STATUS_REQUEST extension present at all. */
|
|
ExpectNull(TLSX_CSR_GetRequest_ex(ssl->extensions, 0));
|
|
|
|
/* csr != NULL, csr->ssl == NULL - reachable only by calling the
|
|
* WOLFSSL_LOCAL constructor directly with a NULL ssl; the public
|
|
* wrapper (wolfSSL_UseOCSPStapling -> TLSX_UseCertificateStatusRequest)
|
|
* always forwards a live ssl pointer, so this half needs the direct
|
|
* call too. */
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, NULL, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNull(TLSX_CSR_GetRequest_ex(ssl->extensions, 0));
|
|
|
|
/* csr != NULL, csr->ssl != NULL. */
|
|
if (EXPECT_SUCCESS())
|
|
TLSX_Remove(&ssl->extensions, TLSX_STATUS_REQUEST, ssl->heap);
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
/* Pre-TLS1.3 ssl: idx == 0 returns the sole ocsp[0] slot. */
|
|
ExpectNotNull(TLSX_CSR_GetRequest_ex(ssl->extensions, 0));
|
|
ExpectNull(TLSX_CSR_GetRequest_ex(ssl->extensions, 1));
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* wolfSSL_make_eap_keys() - "ssl == NULL || ssl->arrays == NULL". ssl->arrays
|
|
* is allocated lazily by the handshake and is still NULL on a freshly
|
|
* created object, so both operands are reachable without completing a
|
|
* handshake at all. */
|
|
int test_wolfSSL_make_eap_keys_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_HAVE_PRF) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
!defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TEST_STATIC_BUILD)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte key[32];
|
|
|
|
/* ssl == NULL. */
|
|
ExpectIntEQ(wolfSSL_make_eap_keys(NULL, key, sizeof(key), "label"),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* ssl != NULL, ssl->arrays != NULL: wolfSSL_new() -> ReinitSSL() already
|
|
* allocated it, so this is the default state. */
|
|
ExpectNotNull(ssl->arrays);
|
|
if (EXPECT_SUCCESS())
|
|
ssl->specs.mac_algorithm = sha256_mac;
|
|
ExpectIntEQ(wolfSSL_make_eap_keys(ssl, key, sizeof(key), "label"), 0);
|
|
|
|
/* ssl != NULL, ssl->arrays == NULL: FreeArrays() is what clears it in
|
|
* real use, once the handshake has finished with the randoms/master
|
|
* secret and no longer needs them - called directly here (WOLFSSL_LOCAL)
|
|
* rather than running a full handshake just to reach the same state. */
|
|
if (ssl != NULL)
|
|
FreeArrays(ssl, 0);
|
|
ExpectNull(ssl->arrays);
|
|
ExpectIntEQ(wolfSSL_make_eap_keys(ssl, key, sizeof(key), "label"),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* wolfSSL_SetTlsHmacInner() - "ssl == NULL || inner == NULL", then
|
|
* "content == dtls12_cid || (ssl->options.dtls && DtlsGetCidTxSize(ssl) >
|
|
* 0)". Both are public (WOLFSSL_API) and reachable directly. */
|
|
int test_wolfSSL_SetTlsHmacInner_bounds(void)
|
|
{
|
|
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_AEAD_ONLY) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte inner[WOLFSSL_TLS_HMAC_INNER_SZ];
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* ssl == NULL. */
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(NULL, inner, 10, application_data, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* ssl != NULL, inner == NULL. */
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(ssl, NULL, 10, application_data, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* content == dtls12_cid: true on its own, regardless of ssl->options.
|
|
* dtls, on a plain TLS object. */
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(ssl, inner, 10, dtls12_cid, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* content != dtls12_cid, ssl->options.dtls == 0: both operands of the
|
|
* inner OR are false without evaluating DtlsGetCidTxSize() at all. */
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(ssl, inner, 10, application_data, 0),
|
|
0);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
/* DtlsGetCidTxSize() is WOLFSSL_LOCAL, so this block only builds when the
|
|
* test links against the static library. */
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_DTLS) && \
|
|
defined(WOLFSSL_DTLS_CID) && defined(WOLFSSL_DTLS13)
|
|
/* content != dtls12_cid, ssl->options.dtls == 1, no CID negotiated:
|
|
* independence for the second operand while the third is false. */
|
|
ctx = NULL;
|
|
ssl = NULL;
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(ssl, inner, 10, application_data, 0),
|
|
0);
|
|
|
|
/* content != dtls12_cid, ssl->options.dtls == 1, a tx CID configured:
|
|
* independence for the third operand. */
|
|
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl), WOLFSSL_SUCCESS);
|
|
{
|
|
byte cid[4] = { 1, 2, 3, 4 };
|
|
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl, cid, sizeof(cid)),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
if (DtlsGetCidTxSize(ssl) > 0) {
|
|
ExpectIntEQ(wolfSSL_SetTlsHmacInner(ssl, inner, 10, application_data,
|
|
0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* BuildTlsHandshakeHash() - the leading 4-operand NULL/size guard has no
|
|
* public wrapper, so it is unit-tested directly (WOLFSSL_TEST_STATIC_BUILD).
|
|
* The mac_algorithm <= sha256_mac || mac_algorithm == blake2b_mac branch
|
|
* (choosing the SHA-256 handshake hash) only needs its second operand:
|
|
* mac_algorithm <= sha256_mac already has an independence pair elsewhere in
|
|
* the suite; blake2b_mac (8) is above sha256_mac (4) in enum wc_MACAlgorithm
|
|
* ordering regardless of whether HAVE_BLAKE2B is built, so setting
|
|
* specs.mac_algorithm to it exercises the SHA-256 path through the second
|
|
* operand without requiring BLAKE2b support. */
|
|
int test_BuildTlsHandshakeHash_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && !defined(WOLFSSL_NO_TLS12) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_SHA256)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte hash[WC_MAX_DIGEST_SIZE];
|
|
word32 hashLen;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(InitHandshakeHashes(ssl), 0);
|
|
|
|
/* ssl == NULL. */
|
|
hashLen = sizeof(hash);
|
|
ExpectIntEQ(BuildTlsHandshakeHash(NULL, hash, &hashLen),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* hash == NULL. */
|
|
hashLen = sizeof(hash);
|
|
ExpectIntEQ(BuildTlsHandshakeHash(ssl, NULL, &hashLen),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* hashLen == NULL. */
|
|
ExpectIntEQ(BuildTlsHandshakeHash(ssl, hash, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* *hashLen < HSHASH_SZ. */
|
|
hashLen = 1;
|
|
ExpectIntEQ(BuildTlsHandshakeHash(ssl, hash, &hashLen),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* All valid, mac_algorithm <= sha256_mac (sha256_mac itself): the
|
|
* already-covered independence pair for the first operand. */
|
|
if (EXPECT_SUCCESS())
|
|
ssl->specs.mac_algorithm = sha256_mac;
|
|
hashLen = sizeof(hash);
|
|
ExpectIntEQ(BuildTlsHandshakeHash(ssl, hash, &hashLen), 0);
|
|
ExpectIntEQ(hashLen, WC_SHA256_DIGEST_SIZE);
|
|
|
|
/* mac_algorithm == blake2b_mac: first operand false (8 > sha256_mac's
|
|
* 4), second operand true - still routes to the SHA-256 hash object
|
|
* (populated regardless of the negotiated MAC, for exactly this kind of
|
|
* lookup), not to an unbuilt BLAKE2b one. */
|
|
if (EXPECT_SUCCESS())
|
|
ssl->specs.mac_algorithm = blake2b_mac;
|
|
hashLen = sizeof(hash);
|
|
ExpectIntEQ(BuildTlsHandshakeHash(ssl, hash, &hashLen), 0);
|
|
ExpectIntEQ(hashLen, WC_SHA256_DIGEST_SIZE);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLS_hmac() / Hmac_UpdateFinal_CT() - driven directly through ssl->hmac(),
|
|
* which InitSSL() points at TLS_hmac() by default whenever TLS 1.2 (or
|
|
* older) CBC-MAC support is built, before any handshake runs (see the
|
|
* existing test_tls_hmac_size_overflow() in test_hmac.c for the same
|
|
* pattern). No live connection is needed: the size-overflow guard and the
|
|
* verify/padSz dispatch are pure argument checks over ssl->specs and the
|
|
* caller-supplied lengths. */
|
|
int test_TLS_hmac_bounds(void)
|
|
{
|
|
#if !defined(NO_HMAC) && !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_TLS) && defined(NO_OLD_TLS) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_SHA256) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte digest[WC_MAX_DIGEST_SIZE];
|
|
byte in[256];
|
|
|
|
XMEMSET(in, 0xAA, sizeof(in));
|
|
XMEMSET(digest, 0, sizeof(digest));
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectNotNull(ssl->hmac);
|
|
|
|
if (EXPECT_SUCCESS()) {
|
|
ssl->specs.mac_algorithm = sha256_mac;
|
|
ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE;
|
|
|
|
/* "verify && padSz >= 0" (first occurrence, guards the size-overflow
|
|
* pre-check): verify == 0 - first operand false, independence
|
|
* against the verify == 1 calls below. Neither the pre-check nor
|
|
* the second occurrence at line ~1465 are reached; the plain
|
|
* wc_HmacUpdate/Final path below runs instead. */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in, 50, 10, application_data, 0,
|
|
PEER_ORDER), 0);
|
|
|
|
/* verify == 1, padSz == -1: second operand false - independence for
|
|
* the second operand of the same guard, and for the second
|
|
* occurrence at line ~1465 (both are skipped, same as above). */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in, 50, -1, application_data, 1,
|
|
PEER_ORDER), 0);
|
|
|
|
/* verify == 1, padSz == 10: both operands true. Reaches the
|
|
* overflow pre-check with ordinary values (no overflow) and then
|
|
* the constant-time verify path (Hmac_UpdateFinal_CT(), and within
|
|
* it Hmac_OuterHash() - both only reachable from here). */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in, 50, 10, application_data, 1,
|
|
PEER_ORDER), 0);
|
|
|
|
/* Overflow in the first addition (sz + hashSz): sz alone is already
|
|
* within 32 of the word32 max. */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in,
|
|
(word32)(WOLFSSL_MAX_32BIT - 10), 0, application_data, 1,
|
|
PEER_ORDER), WC_NO_ERR_TRACE(BUFFER_E));
|
|
|
|
/* First addition safe (sz + hashSz == WOLFSSL_MAX_32BIT - 5), but
|
|
* adding padSz overflows - independence for the second addition,
|
|
* with the first false. */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in,
|
|
(word32)(WOLFSSL_MAX_32BIT - 32 - 5), 10,
|
|
application_data, 1, PEER_ORDER),
|
|
WC_NO_ERR_TRACE(BUFFER_E));
|
|
|
|
/* First two additions land exactly on WOLFSSL_MAX_32BIT (sz +
|
|
* hashSz(32) + padSz(0)), so neither overflows, but the final "+ 1"
|
|
* does - independence for the third addition, with the first two
|
|
* false. */
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in,
|
|
(word32)(WOLFSSL_MAX_32BIT - 32), 0, application_data, 1,
|
|
PEER_ORDER), WC_NO_ERR_TRACE(BUFFER_E));
|
|
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && !defined(WOLFSSL_NO_HASH_RAW) && \
|
|
!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
|
|
/* Hmac_UpdateFinal_CT()'s own "macLen <= 0" guard: force hash_size
|
|
* to 0 for this call only. wc_HmacSetKey() accepts a zero-length
|
|
* key (RFC 2104 permits an empty key), so ret stays 0 and this
|
|
* still reaches the constant-time path with macLen == 0. The
|
|
* build conditions match TLS_hmac()'s own: the other path,
|
|
* Hmac_UpdateFinal(), takes no macLen and has no such guard.
|
|
*
|
|
* The guard's other half, "macLen > sizeof(hmac->innerHash)"
|
|
* (innerHash is WC_MAX_DIGEST_SIZE bytes), is excluded: macLen is
|
|
* always ssl->specs.hash_size or TRUNCATED_HMAC_SZ, and hash_size
|
|
* is also the key length wc_HmacSetKey() reads out of
|
|
* ssl->keys.*_write_MAC_secret, a fixed WC_MAX_DIGEST_SIZE-byte
|
|
* array - so any hash_size big enough to take this branch would
|
|
* already have made wc_HmacSetKey() (immediately above, in the same
|
|
* call) read out of bounds. Every real MAC algorithm's digest size
|
|
* fits within WC_MAX_DIGEST_SIZE by construction, so this half is
|
|
* contradicted by that shared field's own bound (family 4). */
|
|
ssl->specs.hash_size = 0;
|
|
ExpectIntEQ(ssl->hmac(ssl, digest, in, 50, 0, application_data, 1,
|
|
PEER_ORDER), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE;
|
|
#endif
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_ALPN_GetSize() (reached through the WOLFSSL_TEST_VIS
|
|
* TLSX_GetRequestSize()) - "alpnSz == 0 && extension->data != NULL" is the
|
|
* 16-bit overflow guard on the accumulated ALPN protocol list size. The only
|
|
* producer of a TLSX_APPLICATION_LAYER_PROTOCOL extension is TLSX_UseALPN(),
|
|
* which always supplies a non-NULL ALPN entry before pushing - so
|
|
* extension->data is never NULL while this extension exists, and the second
|
|
* operand is true on every real execution that reaches it (which only
|
|
* happens when the first operand is already true, i.e. on overflow).
|
|
* Excluded (family 4: contradicted by TLSX_UseALPN()'s own postcondition);
|
|
* only the first operand is driven here. WOLFSSL_MAX_ALPN_NUMBER (257)
|
|
* entries of the maximum WOLFSSL_MAX_ALPN_PROTO_NAME_LEN (255) push the
|
|
* running total past 0xFFFF (257 * 256 + 2 == 65794). */
|
|
int test_TLSX_ALPN_GetSize_overflow(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(HAVE_ALPN) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
char name[WOLFSSL_MAX_ALPN_PROTO_NAME_LEN];
|
|
word32 len;
|
|
int i;
|
|
|
|
XMEMSET(name, 'a', sizeof(name));
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* alpnSz != 0 (no overflow): first operand false, short-circuits past
|
|
* the second - independence for the first operand, paired against the
|
|
* overflow case below. */
|
|
len = 0;
|
|
ExpectIntEQ(wolfSSL_UseALPN(ssl, (char*)"http/1.1", 8,
|
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &len), 0);
|
|
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
for (i = 0; EXPECT_SUCCESS() && i < WOLFSSL_MAX_ALPN_NUMBER; i++) {
|
|
ExpectIntEQ(TLSX_UseALPN(&ssl->extensions, name, sizeof(name),
|
|
WOLFSSL_ALPN_FAILED_ON_MISMATCH, ssl->heap),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &len),
|
|
WC_NO_ERR_TRACE(LENGTH_ERROR));
|
|
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_Cookie_GetSize() / TLSX_Cookie_Write() - "msgType == client_hello ||
|
|
* msgType == hello_retry_request", reached through the WOLFSSL_TEST_VIS
|
|
* TLSX_GetRequestSize()/TLSX_WriteRequest() by passing the message type
|
|
* directly: the dispatch inside TLSX_GetSize()/TLSX_Write() only looks at
|
|
* the msgType argument (and, once the extension already exists,
|
|
* extension->resp for the "is this message type getting a response-only
|
|
* extension" skip), not at which top-level wrapper made the call. */
|
|
int test_TLSX_Cookie_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
TLSX* ext = NULL;
|
|
byte cookieData[4] = { 1, 2, 3, 4 };
|
|
byte out[64];
|
|
word32 offset;
|
|
word32 pLen;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
ExpectIntEQ(TLSX_Cookie_Use(ssl, cookieData, sizeof(cookieData), NULL, 0,
|
|
0, &ssl->extensions), 0);
|
|
|
|
/* msgType == client_hello: first operand true. isRequest is true for
|
|
* client_hello, so the extension is included regardless of resp. Drives
|
|
* both TLSX_Cookie_GetSize() (via TLSX_GetRequestSize()) and
|
|
* TLSX_Cookie_Write() (via TLSX_WriteRequest()) - the two functions have
|
|
* the same guard at the same relative position, reached the same way. */
|
|
pLen = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &pLen), 0);
|
|
ExpectTrue(pLen > OPAQUE16_LEN);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
ExpectTrue(offset > OPAQUE16_LEN);
|
|
|
|
/* msgType == hello_retry_request: second operand true, first false -
|
|
* independence for the second operand. hello_retry_request is not
|
|
* "isRequest" (only client_hello/certificate_request are), so resp must
|
|
* be set for TLSX_GetSize()/TLSX_Write() to not skip the extension. */
|
|
if (EXPECT_SUCCESS())
|
|
ext = TLSX_Find(ssl->extensions, TLSX_COOKIE);
|
|
ExpectNotNull(ext);
|
|
if (ext != NULL)
|
|
ext->resp = 1;
|
|
pLen = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, hello_retry_request, &pLen), 0);
|
|
ExpectTrue(pLen > OPAQUE16_LEN);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, hello_retry_request, &offset), 0);
|
|
ExpectTrue(offset > OPAQUE16_LEN);
|
|
|
|
/* msgType == server_hello: both operands false - independence for the
|
|
* second operand's false side, paired against the hello_retry_request
|
|
* case above (both with resp == 1, so the extension is not skipped
|
|
* before TLSX_Cookie_GetSize()/_Write() run). */
|
|
pLen = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, server_hello, &pLen),
|
|
WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, server_hello, &offset),
|
|
WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_CSR_GetSize_ex() / TLSX_CSR_Write_ex() - both share the same
|
|
* response-side shape:
|
|
* if (!isRequest && csr->ssl != NULL && IsAtLeastTLSv1_3(csr->ssl->version)) {
|
|
* if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
|
|
* SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
|
|
* SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
|
|
* <use the status callback response>
|
|
* }
|
|
* <use csr->responses[idx] directly>
|
|
* }
|
|
*
|
|
* In TLSX_CSR_Write_ex() specifically, the leading "!isRequest" operand of
|
|
* the outer decision is unreachable as false: the function's own
|
|
* "#ifndef NO_WOLFSSL_CLIENT if (isRequest) { ...; return (int)offset; }"
|
|
* block (present in this build) always returns before this line whenever
|
|
* isRequest is true, so control only ever reaches the response-side "if"
|
|
* with isRequest already false. Excluded (family 3: fixed by the branch
|
|
* that reaches it). TLSX_CSR_GetSize_ex()'s twin block has no such
|
|
* unconditional return ahead of it (the request-side "if (isRequest) {...}"
|
|
* just falls through), so its !isRequest/csr->ssl!=NULL operands are
|
|
* independently reachable there - which is exactly why the worklist only
|
|
* carries TLSX_CSR_GetSize_ex's third operand (the version check) and not
|
|
* its first two.
|
|
*
|
|
* The nested decision's leading "csr->ssl != NULL" (in both functions) is
|
|
* likewise fixed true: it re-tests the same csr->ssl pointer the enclosing
|
|
* "if" already required to be non-NULL two lines above, with no assignment
|
|
* to csr->ssl in between. Excluded (family 3) in both functions.
|
|
*/
|
|
#ifdef TEST_TLS_BOUNDS_CSR_STATUS_CB
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_TLSX_CSR_write_getsize_status_cb(WOLFSSL* ssl, void* arg)
|
|
{
|
|
(void)ssl; (void)arg;
|
|
return WOLFSSL_OCSP_STATUS_CB_OK;
|
|
}
|
|
#endif
|
|
|
|
int test_TLSX_CSR_write_getsize_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_CSR_STATUS_CB) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
TLSX* ext = NULL;
|
|
CertificateStatusRequest* csr = NULL;
|
|
WOLFSSL_CERT_MANAGER* origCM = NULL;
|
|
ProtocolVersion origVersion;
|
|
byte out[OPAQUE8_LEN + OPAQUE24_LEN + 8];
|
|
word16 sz;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
csr = (CertificateStatusRequest*)ext->data;
|
|
ExpectNotNull(csr);
|
|
|
|
if (csr != NULL) {
|
|
origVersion = ssl->version;
|
|
|
|
/* Outer decision, operand 1 (csr->ssl != NULL): false side. Short-
|
|
* circuits before the version check (csr->ssl->version) is ever
|
|
* dereferenced, so this is safe even though ssl is TLS 1.3. Only
|
|
* TLSX_CSR_Write_ex() needs this pair (TLSX_CSR_GetSize_ex()'s
|
|
* operand 1 is already covered elsewhere). */
|
|
csr->ssl = NULL;
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0), 0);
|
|
csr->ssl = ssl;
|
|
|
|
/* Outer decision, operand 2 (IsAtLeastTLSv1_3): false side, with
|
|
* operand 1 true (csr->ssl == ssl, unchanged). Paired against the
|
|
* TLS 1.3 calls below (operand 2 true). */
|
|
ssl->version.major = SSLv3_MAJOR;
|
|
ssl->version.minor = TLSv1_2_MINOR;
|
|
ExpectIntEQ(TLSX_CSR_GetSize_ex(csr, 0, 0), 0);
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0), 0);
|
|
ssl->version = origVersion;
|
|
|
|
/* Nested decision, operand 1 (SSL_CM(csr->ssl) != NULL): false
|
|
* side. Outer decision is true throughout (TLS 1.3, csr->ssl set),
|
|
* so this also covers operand 2 of the outer decision (true side). */
|
|
origCM = ssl->ctx->cm;
|
|
ssl->ctx->cm = NULL;
|
|
ExpectIntEQ(TLSX_CSR_GetSize_ex(csr, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
ssl->ctx->cm = origCM;
|
|
|
|
/* Nested decision, operand 2 (ocsp_stapling != NULL): false side,
|
|
* operand 1 now true (cm restored, no stapling object allocated
|
|
* yet). */
|
|
ExpectIntEQ(TLSX_CSR_GetSize_ex(csr, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
|
|
/* Nested decision, operand 3 (statusCb != NULL): false side,
|
|
* operands 1 and 2 now true (stapling object allocated, no
|
|
* callback registered yet). */
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_CSR_GetSize_ex(csr, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN);
|
|
|
|
/* Nested decision, all operands true: routes through
|
|
* TLSX_CSR_WriteWithStatusCB() / the status-callback size path.
|
|
* TLSX_CSR_WriteWithStatusCB()'s own leading NULL guards
|
|
* ("ssl == NULL || SSL_CM(ssl) == NULL" and "ocsp == NULL ||
|
|
* ocsp->statusCb == NULL") are unreachable as true: it has exactly
|
|
* one caller (this line), which has just proven all four of those
|
|
* facts true. Excluded (family 1). Its response==NULL/respSz==0
|
|
* guard is not established by the caller and is driven below. */
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_status_cb(ctx,
|
|
test_TLSX_CSR_write_getsize_status_cb), WOLFSSL_SUCCESS);
|
|
|
|
/* response == NULL (respSz == 0 too, both untouched): operand 0
|
|
* of the response/respSz guard true. */
|
|
ssl->ocspCsrResp[0].buffer = NULL;
|
|
ssl->ocspCsrResp[0].length = 0;
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* response != NULL, respSz == 0: operand 0 false, operand 1 true -
|
|
* independence for operand 1. */
|
|
ssl->ocspCsrResp[0].buffer = out;
|
|
ssl->ocspCsrResp[0].length = 0;
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* response != NULL, respSz > 0: both operands false - the write
|
|
* succeeds. Also exercises TLSX_CSR_GetSize_ex()'s status-callback
|
|
* size path (not itself an open condition, but the same call site). */
|
|
ssl->ocspCsrResp[0].length = 4;
|
|
sz = TLSX_CSR_GetSize_ex(csr, 0, 0);
|
|
ExpectIntEQ(sz, OPAQUE8_LEN + OPAQUE24_LEN + 4);
|
|
ExpectIntEQ(TLSX_CSR_Write_ex(csr, out, 0, 0),
|
|
OPAQUE8_LEN + OPAQUE24_LEN + 4);
|
|
|
|
ssl->ocspCsrResp[0].buffer = NULL;
|
|
ssl->ocspCsrResp[0].length = 0;
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_CSR_SetResponseWithStatusCB() - unlike TLSX_CSR_WriteWithStatusCB(),
|
|
* this one is WOLFSSL_LOCAL (not static-in-file), so it is unit-tested
|
|
* directly rather than only through its one real caller (SetupOcspResp() in
|
|
* tls13.c, which - like TLSX_CSR_Write_ex() above - already guarantees
|
|
* ssl/SSL_CM(ssl)/ocsp_stapling/statusCb are non-NULL before calling it).
|
|
* Called directly, none of those preconditions are established, so all four
|
|
* operands are independently reachable here. */
|
|
int test_TLSX_CSR_SetResponseWithStatusCB_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_CSR_STATUS_CB) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
WOLFSSL_CERT_MANAGER* origCM = NULL;
|
|
|
|
/* ssl == NULL: first operand of "ssl == NULL || SSL_CM(ssl) == NULL". */
|
|
ExpectIntEQ(TLSX_CSR_SetResponseWithStatusCB(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* ssl != NULL, SSL_CM(ssl) == NULL: second operand true, first false -
|
|
* independence for the second operand. */
|
|
if ((ssl != NULL) && (ssl->ctx != NULL)) {
|
|
origCM = ssl->ctx->cm;
|
|
ssl->ctx->cm = NULL;
|
|
}
|
|
ExpectIntEQ(TLSX_CSR_SetResponseWithStatusCB(ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
if (EXPECT_SUCCESS())
|
|
ssl->ctx->cm = origCM;
|
|
|
|
/* ssl != NULL, SSL_CM(ssl) != NULL, ocsp == NULL (no stapling object
|
|
* allocated yet): both operands of the first guard false, first
|
|
* operand of the second guard ("ocsp == NULL") true. */
|
|
ExpectIntEQ(TLSX_CSR_SetResponseWithStatusCB(ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* ocsp != NULL, statusCb == NULL: second operand of the second guard
|
|
* true, first false - independence for that operand. */
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_CSR_SetResponseWithStatusCB(ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Both guards false: reaches the callback itself. No status_request
|
|
* extension is present on ssl, so the callback's WOLFSSL_OCSP_STATUS_CB_OK
|
|
* finds nothing in ssl->ocspCsrResp to ack and returns cleanly. */
|
|
ExpectIntEQ(wolfSSL_CTX_set_tlsext_status_cb(ctx,
|
|
test_TLSX_CSR_write_getsize_status_cb), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_CSR_SetResponseWithStatusCB(ssl), 0);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* ProcessChainOCSPRequest() - walks ssl->buffers.certChain (each entry a
|
|
* 3-byte length followed by a DER certificate) and, for each one, builds
|
|
* and checks an OCSP request against SSL_CM(ssl)->ocsp_stapling. Response
|
|
* bytes below are the same "resp_cert_unknown" fixture used by
|
|
* tests/api/test_ocsp.c (generated by create_ocsp_test_blobs.py for
|
|
* certs/ocsp/intermediate1-ca-cert.pem against certs/ocsp/root-ca-cert.pem),
|
|
* copied here under a local name so this file does not pull in
|
|
* test_ocsp_test_blobs.h's non-static globals into a second translation
|
|
* unit. */
|
|
#ifdef TEST_TLS_BOUNDS_OCSP_CHAIN
|
|
static const unsigned char csrocsp_resp_unknown[] = {
|
|
0x30, 0x82, 0x07, 0x29, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x07, 0x22, 0x30,
|
|
0x82, 0x07, 0x1e, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
|
|
0x01, 0x01, 0x04, 0x82, 0x07, 0x0f, 0x30, 0x82, 0x07, 0x0b, 0x30, 0x82,
|
|
0x01, 0x00, 0xa1, 0x81, 0x9b, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09,
|
|
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30,
|
|
0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68,
|
|
0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
|
|
0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65,
|
|
0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77,
|
|
0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
|
|
0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65,
|
|
0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
|
|
0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x72,
|
|
0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09,
|
|
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11, 0x66,
|
|
0x61, 0x63, 0x74, 0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c,
|
|
0x2e, 0x63, 0x6f, 0x6d, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x36, 0x30, 0x36,
|
|
0x32, 0x34, 0x31, 0x36, 0x33, 0x37, 0x30, 0x35, 0x5a, 0x30, 0x4f, 0x30,
|
|
0x4d, 0x30, 0x38, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
|
0x04, 0x14, 0x7a, 0x34, 0xec, 0xb3, 0x2b, 0x4f, 0x1b, 0xa2, 0x72, 0x22,
|
|
0x92, 0xa8, 0x4c, 0xc0, 0x12, 0xc7, 0x7a, 0x56, 0x9e, 0x20, 0x04, 0x14,
|
|
0x73, 0xb0, 0x1c, 0xa4, 0x2f, 0x82, 0xcb, 0xcf, 0x47, 0xa5, 0x38, 0xd7,
|
|
0xb0, 0x04, 0x82, 0x3a, 0x7e, 0x72, 0x15, 0x21, 0x02, 0x01, 0x01, 0x82,
|
|
0x00, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x36, 0x30, 0x36, 0x32, 0x34, 0x31,
|
|
0x36, 0x33, 0x37, 0x30, 0x35, 0x5a, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86,
|
|
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00,
|
|
0x1c, 0x64, 0xcb, 0x8a, 0x8e, 0x9c, 0x63, 0x4e, 0xd5, 0x6d, 0xbc, 0xac,
|
|
0x92, 0x78, 0x02, 0xf2, 0xb5, 0x40, 0x93, 0x38, 0x5d, 0x28, 0x6c, 0x05,
|
|
0x57, 0x81, 0xf3, 0x8b, 0xd7, 0x0e, 0xbb, 0xfc, 0xee, 0x63, 0x9a, 0x4a,
|
|
0x02, 0x04, 0xd9, 0xa2, 0x61, 0x0f, 0x8e, 0x44, 0xb6, 0x48, 0xf4, 0xfe,
|
|
0x23, 0xab, 0xd6, 0x0c, 0x92, 0xe3, 0x8e, 0xcf, 0x36, 0xf1, 0x7b, 0x6c,
|
|
0xf7, 0x99, 0xb0, 0x83, 0xa0, 0xbd, 0x66, 0x98, 0x02, 0xb0, 0x4b, 0x7a,
|
|
0xf7, 0x77, 0x6e, 0x47, 0xa4, 0xd0, 0x27, 0x2e, 0xa0, 0xbd, 0xb0, 0xa7,
|
|
0xfa, 0xb6, 0x8d, 0x84, 0xef, 0x3a, 0x38, 0xa3, 0x6b, 0x26, 0x73, 0xc0,
|
|
0xd6, 0xef, 0x2f, 0xf9, 0x1b, 0xef, 0x01, 0x2c, 0x4e, 0x36, 0x8d, 0x9b,
|
|
0x45, 0x58, 0xb3, 0x97, 0x46, 0x9f, 0xb5, 0xd2, 0x5a, 0x7d, 0xa6, 0x47,
|
|
0x37, 0xd6, 0xa4, 0x3b, 0x61, 0x97, 0x20, 0xd3, 0x32, 0x0e, 0x7f, 0xac,
|
|
0x76, 0x62, 0x19, 0xab, 0x74, 0x71, 0x7b, 0x89, 0x75, 0xfa, 0x3f, 0x89,
|
|
0xe7, 0xf2, 0x55, 0xeb, 0x32, 0xce, 0xe2, 0x55, 0x98, 0x0b, 0x67, 0x9a,
|
|
0x94, 0x48, 0x95, 0x8e, 0xa3, 0x61, 0x8a, 0x4c, 0x2e, 0xe9, 0xbe, 0x65,
|
|
0xe5, 0x7c, 0x9e, 0x5f, 0xcc, 0xeb, 0x74, 0xee, 0xb2, 0x59, 0x5a, 0x03,
|
|
0xa0, 0xbd, 0xcf, 0x06, 0x95, 0x6b, 0x34, 0x47, 0x19, 0x7e, 0xd0, 0xb4,
|
|
0xcc, 0xf6, 0xb3, 0xdc, 0x46, 0x74, 0x0a, 0x9a, 0x28, 0x57, 0xba, 0x46,
|
|
0x6f, 0xfc, 0x24, 0xcd, 0x82, 0x20, 0x1a, 0x1c, 0x74, 0x0c, 0x37, 0x8e,
|
|
0x22, 0x1f, 0x00, 0x9c, 0x66, 0x4f, 0xf5, 0xbb, 0xeb, 0xe1, 0x7f, 0x0e,
|
|
0xb0, 0x39, 0xde, 0xd8, 0xf2, 0x56, 0xe0, 0xc2, 0xa2, 0x95, 0xbe, 0xad,
|
|
0x9c, 0x10, 0x56, 0x28, 0x8e, 0x50, 0x79, 0x2f, 0xb6, 0xbf, 0x31, 0x6e,
|
|
0x71, 0x53, 0x13, 0x63, 0xa0, 0x82, 0x04, 0xf1, 0x30, 0x82, 0x04, 0xed,
|
|
0x30, 0x82, 0x04, 0xe9, 0x30, 0x82, 0x03, 0xd1, 0xa0, 0x03, 0x02, 0x01,
|
|
0x02, 0x02, 0x01, 0x63, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
|
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x98, 0x31, 0x0b,
|
|
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
|
|
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61,
|
|
0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e,
|
|
0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74,
|
|
0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
|
|
0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12,
|
|
0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e,
|
|
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
|
|
0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c,
|
|
0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x20, 0x30, 0x1e,
|
|
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
|
|
0x11, 0x66, 0x61, 0x63, 0x74, 0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73,
|
|
0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36,
|
|
0x30, 0x36, 0x31, 0x31, 0x32, 0x31, 0x34, 0x34, 0x33, 0x34, 0x5a, 0x17,
|
|
0x0d, 0x32, 0x39, 0x30, 0x33, 0x30, 0x37, 0x32, 0x31, 0x34, 0x34, 0x33,
|
|
0x34, 0x5a, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
|
|
0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
|
|
0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67,
|
|
0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07,
|
|
0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30,
|
|
0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66,
|
|
0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b,
|
|
0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
|
0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f,
|
|
0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x72, 0x6f, 0x6f, 0x74,
|
|
0x20, 0x43, 0x41, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
|
0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x63, 0x74,
|
|
0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f,
|
|
0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
|
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
|
|
0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xab, 0x2c,
|
|
0xb4, 0x2f, 0x1d, 0x06, 0x09, 0xef, 0x4e, 0x29, 0x86, 0x84, 0x7e, 0xcc,
|
|
0xbf, 0xa6, 0x79, 0x7c, 0xf0, 0xc0, 0xc1, 0x64, 0x25, 0x8c, 0x75, 0xb7,
|
|
0x10, 0x05, 0xca, 0x48, 0x27, 0x0c, 0x0e, 0x32, 0x1c, 0xb0, 0xfe, 0x99,
|
|
0x85, 0x39, 0xb6, 0xb9, 0xa2, 0xf7, 0x27, 0xff, 0x6d, 0x3c, 0x8c, 0x16,
|
|
0x73, 0x29, 0x21, 0x7f, 0x8b, 0xa6, 0x54, 0x71, 0x90, 0xad, 0xcc, 0x05,
|
|
0xb9, 0x9f, 0x15, 0xc7, 0x0a, 0x3f, 0x5f, 0x69, 0xf4, 0x0a, 0x5f, 0x8c,
|
|
0x71, 0xb5, 0x2c, 0xbf, 0x66, 0xe2, 0x03, 0x9a, 0x32, 0xf4, 0xd2, 0xec,
|
|
0x2a, 0x89, 0x4b, 0xf9, 0x35, 0x88, 0x14, 0x33, 0x47, 0x4e, 0x2e, 0x05,
|
|
0x79, 0x01, 0xed, 0x64, 0x36, 0x76, 0xb9, 0xf8, 0x85, 0xcd, 0x01, 0x88,
|
|
0xac, 0xc5, 0xb2, 0xb1, 0x59, 0xb8, 0xcd, 0x5a, 0xf4, 0x09, 0x09, 0x38,
|
|
0x9b, 0xda, 0x5a, 0xcf, 0xce, 0x78, 0x99, 0x1f, 0x49, 0x3d, 0x41, 0xd6,
|
|
0x06, 0x7c, 0x52, 0x99, 0xc8, 0x97, 0xd1, 0xb3, 0x80, 0x3a, 0xa2, 0x4f,
|
|
0x36, 0xc4, 0xc5, 0x96, 0x30, 0x77, 0x31, 0x38, 0xc8, 0x70, 0xcc, 0xe1,
|
|
0x67, 0x06, 0xb3, 0x2b, 0x2f, 0x93, 0xb5, 0x69, 0xcf, 0x83, 0x7e, 0x88,
|
|
0x53, 0x9b, 0x0f, 0x46, 0x21, 0x4c, 0xd6, 0x05, 0x36, 0x44, 0x99, 0x60,
|
|
0x68, 0x47, 0xe5, 0x32, 0x01, 0x12, 0xd4, 0x10, 0x73, 0xae, 0x9a, 0x34,
|
|
0x94, 0xfa, 0x6e, 0xb8, 0x58, 0x4f, 0x7b, 0x5b, 0x8a, 0x92, 0x97, 0xad,
|
|
0xfd, 0x97, 0xb9, 0x75, 0xca, 0xc2, 0xd4, 0x45, 0x7d, 0x17, 0x6b, 0xcd,
|
|
0x2f, 0xf3, 0x63, 0x7a, 0x0e, 0x30, 0xb5, 0x0b, 0xa9, 0xd9, 0xa6, 0x7c,
|
|
0x74, 0x60, 0x9d, 0xcc, 0x09, 0x03, 0x43, 0xf1, 0x0f, 0x90, 0xd3, 0xb7,
|
|
0xfe, 0x6c, 0x9f, 0xd9, 0xcd, 0x78, 0x4b, 0x15, 0xae, 0x8c, 0x5b, 0xf9,
|
|
0x99, 0x81, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x3a, 0x30,
|
|
0x82, 0x01, 0x36, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
|
|
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
|
|
0x04, 0x16, 0x04, 0x14, 0x73, 0xb0, 0x1c, 0xa4, 0x2f, 0x82, 0xcb, 0xcf,
|
|
0x47, 0xa5, 0x38, 0xd7, 0xb0, 0x04, 0x82, 0x3a, 0x7e, 0x72, 0x15, 0x21,
|
|
0x30, 0x81, 0xc5, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xbd, 0x30,
|
|
0x81, 0xba, 0x80, 0x14, 0x73, 0xb0, 0x1c, 0xa4, 0x2f, 0x82, 0xcb, 0xcf,
|
|
0x47, 0xa5, 0x38, 0xd7, 0xb0, 0x04, 0x82, 0x3a, 0x7e, 0x72, 0x15, 0x21,
|
|
0xa1, 0x81, 0x9e, 0xa4, 0x81, 0x9b, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30,
|
|
0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
|
|
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73,
|
|
0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06,
|
|
0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c,
|
|
0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07,
|
|
0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06,
|
|
0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65,
|
|
0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
|
|
0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20,
|
|
0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x20, 0x30, 0x1e, 0x06,
|
|
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11,
|
|
0x66, 0x61, 0x63, 0x74, 0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73,
|
|
0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x01, 0x63, 0x30, 0x0b, 0x06, 0x03,
|
|
0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x32, 0x06,
|
|
0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30,
|
|
0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
|
|
0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32,
|
|
0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x3a, 0x32, 0x32, 0x32, 0x32,
|
|
0x30, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
|
0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x36, 0xb1, 0x86,
|
|
0xd6, 0x72, 0xf8, 0xe7, 0x6a, 0xae, 0x43, 0xfb, 0xc0, 0xed, 0xf1, 0x36,
|
|
0x64, 0x8a, 0xda, 0x8e, 0x5f, 0xf7, 0xc4, 0xad, 0x64, 0xc8, 0x29, 0x03,
|
|
0x74, 0x58, 0xb0, 0x9e, 0xee, 0x41, 0x89, 0x5b, 0x2a, 0x12, 0xf4, 0x82,
|
|
0xa4, 0x03, 0xa5, 0xf0, 0xdf, 0xa2, 0x84, 0xcb, 0x2b, 0xb3, 0x16, 0x0f,
|
|
0xdc, 0xcf, 0xcc, 0x56, 0x99, 0x61, 0xa9, 0xf9, 0x3d, 0x3a, 0x7e, 0xe4,
|
|
0x12, 0x43, 0xc3, 0xb1, 0x4f, 0x58, 0x26, 0x79, 0xe7, 0xe4, 0x0d, 0xa5,
|
|
0x88, 0x3d, 0x79, 0x33, 0xa1, 0x09, 0x7d, 0x78, 0xaf, 0xbd, 0x59, 0x71,
|
|
0x11, 0x54, 0x4a, 0xcc, 0xd6, 0xd2, 0x6d, 0x1f, 0x88, 0x27, 0xac, 0xd5,
|
|
0xbf, 0x75, 0xfc, 0xc3, 0x05, 0x0b, 0xcd, 0xc8, 0x0e, 0x72, 0x41, 0x1d,
|
|
0xd8, 0x68, 0x62, 0xbe, 0x94, 0xd7, 0x60, 0xbe, 0x05, 0x4a, 0x42, 0x9c,
|
|
0x50, 0xb7, 0x45, 0x71, 0x6d, 0x83, 0x9a, 0xef, 0x08, 0x5c, 0x41, 0xdb,
|
|
0xc8, 0x62, 0x33, 0x3c, 0x69, 0xa2, 0x8a, 0xb4, 0x0f, 0xdb, 0x65, 0xc4,
|
|
0xb7, 0x92, 0x0a, 0x76, 0xf7, 0x55, 0x06, 0x77, 0x8c, 0xff, 0x8c, 0x84,
|
|
0x84, 0xd9, 0xdd, 0x46, 0x11, 0x2a, 0x2d, 0x27, 0x96, 0xa7, 0xf5, 0x47,
|
|
0xc1, 0x43, 0x4b, 0xfe, 0x53, 0xd8, 0xbe, 0x16, 0x94, 0x36, 0x0a, 0xd4,
|
|
0xbe, 0xc3, 0x6c, 0x9b, 0x0c, 0x52, 0x31, 0x4a, 0xeb, 0x62, 0xb4, 0x81,
|
|
0x4b, 0x2d, 0xf7, 0xf1, 0x65, 0xc1, 0xee, 0x36, 0x79, 0x19, 0xf7, 0xab,
|
|
0x16, 0xf8, 0x38, 0xd2, 0xea, 0x87, 0x8d, 0xf8, 0xf9, 0x14, 0x82, 0xdb,
|
|
0x67, 0xb6, 0x94, 0xa8, 0x55, 0x0b, 0x90, 0x6b, 0xaf, 0xb0, 0xe9, 0x42,
|
|
0x64, 0x42, 0x6d, 0x2c, 0xe3, 0xf1, 0xb6, 0xe0, 0xf9, 0x58, 0xed, 0x69,
|
|
0x66, 0x62, 0x98, 0xdc, 0x5a, 0x7b, 0xfa, 0x35, 0x5a, 0x23, 0x84, 0x91,
|
|
0x0e,
|
|
};
|
|
|
|
enum {
|
|
CSROCSP_MODE_UNKNOWN = 0,
|
|
CSROCSP_MODE_LOOKUP_FAIL,
|
|
CSROCSP_MODE_WANT_READ
|
|
};
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_ProcessChainOCSPRequest_io_cb(void* ctx, const char* url,
|
|
int urlSz, unsigned char* req, int reqSz, unsigned char** respBuf)
|
|
{
|
|
int mode = *(int*)ctx;
|
|
static const unsigned char garbage[] = { 0xFF, 0x00, 0x11, 0x22 };
|
|
(void)url; (void)urlSz; (void)req; (void)reqSz;
|
|
|
|
switch (mode) {
|
|
case CSROCSP_MODE_UNKNOWN:
|
|
*respBuf = (unsigned char*)csrocsp_resp_unknown;
|
|
return (int)sizeof(csrocsp_resp_unknown);
|
|
case CSROCSP_MODE_LOOKUP_FAIL:
|
|
*respBuf = (unsigned char*)garbage;
|
|
return (int)sizeof(garbage);
|
|
case CSROCSP_MODE_WANT_READ:
|
|
default:
|
|
return WOLFSSL_CBIO_ERR_WANT_READ;
|
|
}
|
|
}
|
|
|
|
/* Common setup for the "one real, matching chain entry" vectors: server1
|
|
* (leaf) + intermediate1 (the chain entry ProcessChainOCSPRequest() will
|
|
* process) issued off root-ca, matching the identity the csrocsp_resp_*
|
|
* fixtures above were generated against. */
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_ProcessChainOCSPRequest_setup(WOLFSSL_CTX** pctx,
|
|
WOLFSSL** pssl, CertificateStatusRequest** pcsr, int* mode)
|
|
{
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
TLSX* ext = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx,
|
|
"./certs/ocsp/server1-chain-noroot.pem"), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx,
|
|
"./certs/ocsp/server1-key.pem", WOLFSSL_FILETYPE_PEM),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx,
|
|
"./certs/ocsp/root-ca-cert.pem", NULL), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_URL_OVERRIDE |
|
|
WOLFSSL_OCSP_NO_NONCE), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx, "http://dummy.test"),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(ctx, test_ProcessChainOCSPRequest_io_cb,
|
|
NULL, (void*)mode), WOLFSSL_SUCCESS);
|
|
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
*pcsr = (CertificateStatusRequest*)ext->data;
|
|
}
|
|
|
|
*pctx = ctx;
|
|
*pssl = ssl;
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
int test_ProcessChainOCSPRequest_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_OCSP_CHAIN) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
CertificateStatusRequest* csr = NULL;
|
|
int mode;
|
|
byte garbageThenValid[8 + 3 + 4096];
|
|
byte intermediate1Der[4096];
|
|
word32 interLen = 0;
|
|
XFILE f = XBADFILE;
|
|
DerBuffer fakeChain;
|
|
|
|
/* chain == NULL (both certChain and certificate unset): the leading
|
|
* "chain && chain->buffer" guard is false at its first operand, the
|
|
* whole walk is skipped, and the function returns success with
|
|
* nothing done. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
DerBuffer* savedCert = ssl->buffers.certificate;
|
|
DerBuffer* savedChain = ssl->buffers.certChain;
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
csr = (CertificateStatusRequest*)ext->data;
|
|
/* A certificate had to be loaded for wolfSSL_new() to succeed (see
|
|
* test_tls_bounds_load_server_cert()); clear both buffers back to
|
|
* NULL so ProcessChainOCSPRequest() sees exactly the "chain ==
|
|
* NULL" state under test. The SSL owns these buffers (weOwnCert),
|
|
* so save and restore them - nulling them outright leaked the DER
|
|
* copy that wolfSSL_new() allocated. */
|
|
ssl->buffers.certChain = NULL;
|
|
ssl->buffers.certificate = NULL;
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl), 0);
|
|
ssl->buffers.certificate = savedCert;
|
|
ssl->buffers.certChain = savedChain;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* chain != NULL, chain->buffer == NULL: second operand false,
|
|
* independence from the chain == NULL vector above (first operand). */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
csr = (CertificateStatusRequest*)ext->data;
|
|
XMEMSET(&fakeChain, 0, sizeof(fakeChain));
|
|
ssl->buffers.certChain = &fakeChain;
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl), 0);
|
|
ssl->buffers.certChain = NULL;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* while-loop operand 0 (ret == 0) false side: a two-entry chain whose
|
|
* first entry is not a certificate at all, so CreateOcspRequest() fails
|
|
* with a hard ASN.1 parse error - not one of the soft-fail codes the
|
|
* loop body resets to 0 - while its second (valid) entry is still
|
|
* unconsumed, forcing the while condition's re-check to see ret != 0
|
|
* with more chain data pending. */
|
|
ExpectNotNull(f = XFOPEN("./certs/ocsp/intermediate1-ca-cert.der", "rb"));
|
|
if (f != XBADFILE) {
|
|
interLen = (word32)XFREAD(intermediate1Der, 1, sizeof(intermediate1Der),
|
|
f);
|
|
XFCLOSE(f);
|
|
}
|
|
ExpectIntGT(interLen, 0);
|
|
ExpectIntLT(interLen, sizeof(intermediate1Der));
|
|
{
|
|
word32 idx = 0;
|
|
static const byte notACert[] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
|
|
|
test_tls_bounds_c32to24(sizeof(notACert), garbageThenValid + idx);
|
|
idx += OPAQUE24_LEN;
|
|
XMEMCPY(garbageThenValid + idx, notACert, sizeof(notACert));
|
|
idx += sizeof(notACert);
|
|
|
|
test_tls_bounds_c32to24(interLen, garbageThenValid + idx);
|
|
idx += OPAQUE24_LEN;
|
|
XMEMCPY(garbageThenValid + idx, intermediate1Der, interLen);
|
|
idx += interLen;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions,
|
|
TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
csr = (CertificateStatusRequest*)ext->data;
|
|
|
|
XMEMSET(&fakeChain, 0, sizeof(fakeChain));
|
|
fakeChain.buffer = garbageThenValid;
|
|
fakeChain.length = idx;
|
|
ssl->buffers.certChain = &fakeChain;
|
|
|
|
/* Not zero (ASN parse error) and not one of ProcessChainOCSPRequest's
|
|
* own soft-fail codes, so it propagates as the loop's exit ret. */
|
|
ExpectIntNE(ProcessChainOCSPRequest(ssl), 0);
|
|
ExpectIntNE(ProcessChainOCSPRequest(ssl),
|
|
WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN));
|
|
ExpectIntNE(ProcessChainOCSPRequest(ssl),
|
|
WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL));
|
|
ExpectIntNE(ProcessChainOCSPRequest(ssl),
|
|
WC_NO_ERR_TRACE(OCSP_NO_URL));
|
|
|
|
ssl->buffers.certChain = NULL;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
}
|
|
|
|
/* One real, matching chain entry (intermediate1): the while loop enters
|
|
* (operand 0 and operand 1 both true) and, after processing the single
|
|
* entry, exits normally with pos == chain->length (operand 1 false,
|
|
* operand 0 still true) - independence for operand 1, paired against
|
|
* the forced-error vector above (operand 0 false). Run three times with
|
|
* a different responder outcome each time (a fresh CertManager each
|
|
* time, so no cached status from one run leaks into the next), driving
|
|
* the three-way soft-fail classification. */
|
|
mode = CSROCSP_MODE_UNKNOWN;
|
|
ExpectIntEQ(test_ProcessChainOCSPRequest_setup(&ctx, &ssl, &csr, &mode),
|
|
TEST_SUCCESS);
|
|
if (csr != NULL) {
|
|
/* ret is OCSP_CERT_UNKNOWN: first operand of the three-way OR. */
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
csr = NULL;
|
|
|
|
mode = CSROCSP_MODE_LOOKUP_FAIL;
|
|
ExpectIntEQ(test_ProcessChainOCSPRequest_setup(&ctx, &ssl, &csr, &mode),
|
|
TEST_SUCCESS);
|
|
if (csr != NULL) {
|
|
/* ret is OCSP_LOOKUP_FAIL (garbage response bytes fail to decode):
|
|
* second operand true, first false - independence for the second
|
|
* operand. */
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
csr = NULL;
|
|
|
|
/* ret is OCSP_NO_URL: reached without any responder call at all, by
|
|
* leaving the override URL unset and using a chain (server-cert.pem +
|
|
* ca-cert.pem) whose certificates carry no OCSP responder AIA URL. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx,
|
|
"./certs/server-cert.pem"), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx,
|
|
"./certs/server-key.pem", WOLFSSL_FILETYPE_PEM),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx,
|
|
"./certs/ca-cert.pem", NULL), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST));
|
|
if (ext != NULL)
|
|
csr = (CertificateStatusRequest*)ext->data;
|
|
ExpectNotNull(ssl->buffers.certChain);
|
|
if (csr != NULL) {
|
|
/* ret is OCSP_NO_URL: third operand true, first and second
|
|
* false - independence for the third operand. */
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl), 0);
|
|
}
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
csr = NULL;
|
|
|
|
/* ret is OCSP_WANT_READ (via WOLFSSL_CBIO_ERR_WANT_READ from the I/O
|
|
* callback): none of the three - the baseline all-false vector paired
|
|
* against each of the three above. */
|
|
mode = CSROCSP_MODE_WANT_READ;
|
|
ExpectIntEQ(test_ProcessChainOCSPRequest_setup(&ctx, &ssl, &csr, &mode),
|
|
TEST_SUCCESS);
|
|
if (csr != NULL) {
|
|
ExpectIntEQ(ProcessChainOCSPRequest(ssl),
|
|
WC_NO_ERR_TRACE(OCSP_WANT_READ));
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_PopulateExtensions() - called directly (WOLFSSL_LOCAL), the same way
|
|
* SendClientHello()/SendTls13ClientHello() call it before any handshake
|
|
* bytes are produced, so a bare freshly-created ssl is exactly the state a
|
|
* real caller reaches this function with.
|
|
*
|
|
* "16880:17:16880:60:0" - "if (!isServer && ssl->options.postHandshakeAuth)"
|
|
* - is not covered here and is excluded rather than driven: it sits inside
|
|
* "if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { ... }" (opened many
|
|
* lines above, never re-assigning isServer in between), so reaching this
|
|
* line at all already requires isServer == 0. Its own "!isServer" operand
|
|
* is therefore fixed true on every execution that reaches it - excluded
|
|
* (family 3: fixed by the branch that reaches it). */
|
|
#ifdef TEST_TLS_BOUNDS_POPULATE_EXT
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static unsigned int test_TLSX_PopulateExtensions_psk_cb(WOLFSSL* ssl,
|
|
const char* hint, char* identity, unsigned int id_max_len,
|
|
unsigned char* key, unsigned int key_max_len)
|
|
{
|
|
int mode = *(int*)wolfSSL_get_psk_callback_ctx(ssl);
|
|
(void)hint; (void)key_max_len;
|
|
|
|
XSTRNCPY(identity, "id", id_max_len);
|
|
key[0] = 0x01;
|
|
|
|
/* mode 0: > MAX_PSK_KEY_LEN and not equal to USE_HW_PSK - both operands true.
|
|
* mode 1: > MAX_PSK_KEY_LEN and equal to USE_HW_PSK - operand 0 true, operand
|
|
* 1 false.
|
|
* mode 2: <= MAX_PSK_KEY_LEN - operand 0 false, short-circuits. */
|
|
switch (mode) {
|
|
case 0:
|
|
return MAX_PSK_KEY_LEN + 1;
|
|
case 1:
|
|
return (unsigned int)WC_NO_ERR_TRACE(USE_HW_PSK);
|
|
default:
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static unsigned int test_TLSX_PopulateExtensions_psk_tls13_cb(WOLFSSL* ssl,
|
|
const char* hint, char* identity, unsigned int id_max_len,
|
|
unsigned char* key, unsigned int key_max_len, const char** ciphersuite)
|
|
{
|
|
(void)ssl; (void)hint; (void)key_max_len;
|
|
XSTRNCPY(identity, "id", id_max_len);
|
|
key[0] = 0x01;
|
|
*ciphersuite = "TLS13-AES128-GCM-SHA256";
|
|
return 4;
|
|
}
|
|
#endif
|
|
|
|
int test_TLSX_PopulateExtensions_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_POPULATE_EXT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
int mode;
|
|
|
|
/* Operand 1 of "!ssl->options.userCurves && !ssl->ctx->userCurves":
|
|
* ssl->options.userCurves inherits from ctx->userCurves at wolfSSL_new()
|
|
* (InitSSL()), so a ctx with a user curve list makes both true unless
|
|
* the ssl-level copy is forced back to 0 - no public caller can produce
|
|
* "ctx->userCurves set, ssl->options.userCurves clear" any other way. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectIntEQ(wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
ExpectIntEQ(ssl->options.userCurves, 1);
|
|
ssl->options.userCurves = 0;
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ExpectNull(TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS));
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* The point-format decision's four leaf conditions are
|
|
* "(!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) &&
|
|
* TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL &&
|
|
* TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL"
|
|
* (operand indices 0-3); the worklist's ":2" is the ctx-level Find, not
|
|
* the ssl-level one (index 3, already paired elsewhere). TLS 1.2 keeps
|
|
* operand 0 true throughout; ssl->extensions is left without the
|
|
* extension in both vectors below so operand 3 stays fixed true while
|
|
* only the ctx-level Find (operand 2) is flipped. */
|
|
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* ctx-level Find != NULL: operand 2 false. */
|
|
ExpectIntEQ(TLSX_UsePointFormat(&ssl->ctx->extensions,
|
|
WOLFSSL_EC_PF_UNCOMPRESSED, ssl->ctx->heap),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ExpectNull(TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS));
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* ctx-level Find == NULL (default, fresh ctx): operand 2 true -
|
|
* independence for operand 2, paired against the vector above. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ExpectNotNull(TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS));
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
#endif
|
|
|
|
/* Operand 1 of "ssl->options.resuming && ssl->session->namedGroup != 0":
|
|
* resuming fixed true, namedGroup flipped. A default (non-resuming) call
|
|
* is the false/false pair already exercised in ordinary handshake tests
|
|
* elsewhere; this isolates the second operand specifically. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
ssl->options.resuming = 1;
|
|
ssl->session->namedGroup = 0;
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ssl->session->namedGroup = WOLFSSL_ECC_SECP256R1;
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ssl->options.resuming = 0;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
#ifdef HAVE_SESSION_TICKET
|
|
/* Operand 1 of "ssl->options.resuming && ssl->session->ticketLen > 0":
|
|
* resuming fixed true, ticketLen flipped. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
byte ticket[4] = { 1, 2, 3, 4 };
|
|
|
|
ssl->options.resuming = 1;
|
|
ssl->session->ticketLen = 0;
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
|
|
XMEMCPY(ssl->session->ticket, ticket, sizeof(ticket));
|
|
ssl->session->ticketLen = sizeof(ticket);
|
|
/* SetCipherSpecs(ssl) (reached because ticketLen > 0) needs a
|
|
* suite it recognizes; a fresh session's cipherSuite0/cipherSuite
|
|
* default to 0, which is not one. */
|
|
ssl->session->cipherSuite0 = TLS13_BYTE;
|
|
ssl->session->cipherSuite = TLS_AES_128_GCM_SHA256;
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ssl->options.resuming = 0;
|
|
ssl->session->ticketLen = 0;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
#endif /* HAVE_SESSION_TICKET */
|
|
|
|
/* Operand 1 of "client_psk_cb != NULL || client_psk_tls13_cb != NULL":
|
|
* operand 0 fixed false (no client_psk_cb), operand 1 flipped true by
|
|
* registering a tls13 callback that reports "no key available" (a
|
|
* 0-length key), which OPENSSL_EXTRA would treat specially but this
|
|
* build (no OPENSSL_EXTRA) routes through the same
|
|
* "> MAX_PSK_KEY_LEN" guard as any other size, taking its false side. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
wolfSSL_set_psk_client_tls13_callback(ssl,
|
|
test_TLSX_PopulateExtensions_psk_tls13_cb);
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* Both operands of "psk_keySz > MAX_PSK_KEY_LEN" and "not equal to USE_HW_PSK",
|
|
* reached through the plain client_psk_cb path. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
|
|
#ifndef OPENSSL_EXTRA
|
|
/* An over-long key is rejected with PSK_KEY_ERROR. Under OPENSSL_EXTRA the
|
|
* assignment is compiled out and the handshake carries on with a key size
|
|
* larger than the buffer holding it, so this case is not driven there. */
|
|
mode = 0;
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
wolfSSL_set_psk_client_callback(ssl,
|
|
test_TLSX_PopulateExtensions_psk_cb);
|
|
wolfSSL_set_psk_callback_ctx(ssl, &mode);
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0),
|
|
WC_NO_ERR_TRACE(PSK_KEY_ERROR));
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
#endif
|
|
|
|
mode = 1;
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
wolfSSL_set_psk_client_callback(ssl,
|
|
test_TLSX_PopulateExtensions_psk_cb);
|
|
wolfSSL_set_psk_callback_ctx(ssl, &mode);
|
|
/* Operand 0 true, operand 1 false - independence for operand 1. */
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
mode = 2;
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
wolfSSL_set_psk_client_callback(ssl,
|
|
test_TLSX_PopulateExtensions_psk_cb);
|
|
wolfSSL_set_psk_callback_ctx(ssl, &mode);
|
|
/* Operand 0 false - independence for operand 0. */
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_PopulateSupportedGroups() is static-in-file, reached only through
|
|
* TLSX_PopulateExtensions(). Its ML-KEM blocks all share
|
|
* "IsAtLeastTLSv1_3(ssl->version) && TLSX_IsMlKemGroupSupported(ssl->options.side)";
|
|
* the worklist carries only the second operand (the first already has a
|
|
* pair elsewhere). TLSX_IsMlKemGroupSupported() is:
|
|
* if (side == WOLFSSL_CLIENT_END) return <MLKEM_CLIENT_SUPPORT ? 1 : 0>;
|
|
* else if (side == WOLFSSL_SERVER_END) return <MLKEM_SERVER_SUPPORT ? 1 : 0>;
|
|
* else return <MLKEM_CLIENT_SUPPORT || MLKEM_SERVER_SUPPORT ? 1 : 0>;
|
|
* and this build has both WOLFSSL_HAVE_MLKEM_CLIENT_SUPPORT and
|
|
* WOLFSSL_HAVE_MLKEM_SERVER_SUPPORT defined (neither
|
|
* WOLFSSL_MLKEM_NO_MAKE_KEY/_NO_DECAPSULATE/_NO_ENCAPSULATE is set) - so
|
|
* every one of its three branches returns 1, for every possible byte value
|
|
* of ssl->options.side, not just WOLFSSL_CLIENT_END/_SERVER_END/_NEITHER_END.
|
|
* Confirmed by direct call: TLSX_IsMlKemGroupSupported(WOLFSSL_NEITHER_END)
|
|
* returns 1 here, not 0. There is no side value - real or corrupted - that
|
|
* makes this operand false in this build. Excluded (family 4: contradicted
|
|
* by TLSX_IsMlKemGroupSupported()'s own postcondition under this build's
|
|
* feature set). */
|
|
int test_TLSX_PopulateSupportedGroups_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SUPPORTED_CURVES) && defined(WOLFSSL_HAVE_MLKEM_CLIENT_SUPPORT) && !defined(WOLFSSL_NO_ML_KEM) && !defined(NO_DH) && defined(HAVE_FFDHE_2048) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
/* Default client: side == WOLFSSL_CLIENT_END, so
|
|
* TLSX_IsMlKemGroupSupported() is true for all four ML-KEM blocks
|
|
* (its only reachable value in this build - see above). */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* "2048/8 >= minDhKeySz && 2048/8 <= maxDhKeySz": both operands. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
|
|
/* Default range: both operands true. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* minDhKeySz raised above 2048 bits: first operand false. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
ExpectIntEQ(wolfSSL_SetMinDhKey_Sz(ssl, 4096), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* maxDhKeySz lowered below 2048 bits, minDhKeySz left at its default
|
|
* (below 2048 bits): first operand true, second false - independence
|
|
* for the second operand. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
ExpectIntEQ(wolfSSL_SetMaxDhKey_Sz(ssl, 1024), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_CSR_Parse() (client, TLS 1.3, receiving a CertificateStatus
|
|
* response) and TLSX_CSR2_Parse() / TLSX_CSR_Parse() (server, parsing a
|
|
* status_request(_v2) request from a ClientHello) - reached through the
|
|
* WOLFSSL_TEST_VIS TLSX_Parse(). */
|
|
#ifdef TEST_TLS_BOUNDS_CSR_PARSE
|
|
static int test_TLSX_CSR_Parse_fail_after = -1;
|
|
static int test_TLSX_CSR_Parse_alloc_seen = 0;
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static void* test_TLSX_CSR_Parse_fail_malloc(size_t size)
|
|
{
|
|
if (test_TLSX_CSR_Parse_fail_after >= 0) {
|
|
if (test_TLSX_CSR_Parse_alloc_seen == test_TLSX_CSR_Parse_fail_after) {
|
|
test_TLSX_CSR_Parse_alloc_seen++;
|
|
return NULL;
|
|
}
|
|
test_TLSX_CSR_Parse_alloc_seen++;
|
|
}
|
|
return malloc(size);
|
|
}
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static void test_TLSX_CSR_Parse_fail_free(void* ptr)
|
|
{
|
|
free(ptr);
|
|
}
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static void* test_TLSX_CSR_Parse_fail_realloc(void* ptr, size_t size)
|
|
{
|
|
return realloc(ptr, size);
|
|
}
|
|
#endif
|
|
|
|
int test_TLSX_CSR_Parse_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_CSR_PARSE) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte ext[16];
|
|
word16 extLen;
|
|
wolfSSL_Malloc_cb prevM = NULL;
|
|
wolfSSL_Free_cb prevF = NULL;
|
|
wolfSSL_Realloc_cb prevR = NULL;
|
|
|
|
/* Server side, isRequest == true: "SSL_CM(ssl) == NULL ||
|
|
* !SSL_CM(ssl)->ocspStaplingEnabled". A single status_request entry
|
|
* (status_type == OCSP, empty responder_id_list and request_extensions)
|
|
* with SSL_CM(ssl) forced NULL - first operand true. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
Suites* suites = (Suites*)WOLFSSL_SUITES(ssl);
|
|
WOLFSSL_CERT_MANAGER* origCM = ssl->ctx->cm;
|
|
|
|
/* type(2) + len(2) + status_type(1) + responder_id_list len(2)=0 +
|
|
* request_ext len(2)=0 */
|
|
ext[0] = (byte)(TLSXT_STATUS_REQUEST >> 8);
|
|
ext[1] = (byte)(TLSXT_STATUS_REQUEST & 0xFF);
|
|
ext[2] = 0; ext[3] = 5; /* extension body length */
|
|
ext[4] = WOLFSSL_CSR_OCSP;
|
|
ext[5] = 0; ext[6] = 0;
|
|
ext[7] = 0; ext[8] = 0;
|
|
extLen = 4 + 5;
|
|
|
|
ssl->ctx->cm = NULL;
|
|
ExpectIntEQ(TLSX_Parse(ssl, ext, extLen, client_hello, suites), 0);
|
|
ssl->ctx->cm = origCM;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* Client side, isRequest == false, TLS 1.3: the internal ticket-style
|
|
* malloc for csr->responses[idx].buffer.
|
|
* Operand 0 (ret == 0) of "if (ret == 0 &&
|
|
* csr->responses[ssl->response_idx].buffer == NULL)": forced to true
|
|
* by failing that allocation (operand 1 held true), then to false by
|
|
* pushing ssl->response_idx out of range so an earlier guard already
|
|
* set ret != 0 before this line is reached - independence for operand
|
|
* 0, with operand 1's own pair already covered elsewhere. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* type(2) + length(2) + status_type(1) + resp_length(3) + 4 bytes
|
|
* of (fake) response data. */
|
|
byte body[HELLO_EXT_TYPE_SZ + OPAQUE16_LEN + OPAQUE8_LEN +
|
|
OPAQUE24_LEN + 4];
|
|
word16 bodyLen;
|
|
|
|
ExpectIntEQ(TLSX_UseCertificateStatusRequest(&ssl->extensions,
|
|
WOLFSSL_CSR_OCSP, 0, ssl, ssl->heap, ssl->devId),
|
|
WOLFSSL_SUCCESS);
|
|
ssl->options.tls1_3 = 1;
|
|
|
|
body[0] = (byte)(TLSXT_STATUS_REQUEST >> 8);
|
|
body[1] = (byte)(TLSXT_STATUS_REQUEST & 0xFF);
|
|
body[2] = 0;
|
|
body[3] = OPAQUE8_LEN + OPAQUE24_LEN + 4;
|
|
body[4] = WOLFSSL_CSR_OCSP;
|
|
test_tls_bounds_c32to24(4, body + 4 + OPAQUE8_LEN);
|
|
XMEMSET(body + 4 + OPAQUE8_LEN + OPAQUE24_LEN, 0xAB, 4);
|
|
bodyLen = 4 + OPAQUE8_LEN + OPAQUE24_LEN + 4;
|
|
|
|
/* ret == 0, forced allocation failure: operand 0 true, operand 1
|
|
* (buffer == NULL) true - overall true, ret becomes MEMORY_ERROR. */
|
|
ssl->response_idx = 0;
|
|
ExpectIntEQ(wolfSSL_GetAllocators(&prevM, &prevF, &prevR), 0);
|
|
ExpectIntEQ(wolfSSL_SetAllocators(test_TLSX_CSR_Parse_fail_malloc,
|
|
test_TLSX_CSR_Parse_fail_free,
|
|
test_TLSX_CSR_Parse_fail_realloc), 0);
|
|
test_TLSX_CSR_Parse_alloc_seen = 0;
|
|
test_TLSX_CSR_Parse_fail_after = 0;
|
|
ExpectIntEQ(TLSX_Parse(ssl, body, bodyLen, certificate, NULL),
|
|
WC_NO_ERR_TRACE(MEMORY_ERROR));
|
|
test_TLSX_CSR_Parse_fail_after = -1;
|
|
(void)wolfSSL_SetAllocators(prevM, prevF, prevR);
|
|
|
|
/* response_idx out of range: an earlier guard sets ret ==
|
|
* BAD_FUNC_ARG before this decision is reached at all - operand 0
|
|
* false, independence from the vector above. */
|
|
ssl->response_idx = 1 + MAX_CHAIN_DEPTH;
|
|
ExpectIntEQ(TLSX_Parse(ssl, body, bodyLen, certificate, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ssl->response_idx = 0;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
int test_TLSX_CSR2_Parse_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(NO_WOLFSSL_SERVER) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte ext[9];
|
|
WOLFSSL_CERT_MANAGER* origCM = NULL;
|
|
|
|
/* Server side: "SSL_CM(ssl) == NULL || !SSL_CM(ssl)->ocspStaplingEnabled",
|
|
* SSL_CM(ssl) forced NULL - first operand true. One status_request_v2
|
|
* entry (status_type == OCSP, empty responder_id_list/request_extensions). */
|
|
ext[0] = 0; ext[1] = 7; /* overall list size */
|
|
ext[2] = WOLFSSL_CSR2_OCSP; /* status_type */
|
|
ext[3] = 0; ext[4] = 4; /* inner request length */
|
|
ext[5] = 0; ext[6] = 0; /* responder_id_list length */
|
|
ext[7] = 0; ext[8] = 0; /* request_extensions length */
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
Suites* suites = (Suites*)WOLFSSL_SUITES(ssl);
|
|
byte full[9 + 4];
|
|
word16 fullLen;
|
|
|
|
full[0] = (byte)(TLSXT_STATUS_REQUEST_V2 >> 8);
|
|
full[1] = (byte)(TLSXT_STATUS_REQUEST_V2 & 0xFF);
|
|
full[2] = 0; full[3] = sizeof(ext);
|
|
XMEMCPY(full + 4, ext, sizeof(ext));
|
|
fullLen = 4 + sizeof(ext);
|
|
|
|
origCM = ssl->ctx->cm;
|
|
ssl->ctx->cm = NULL;
|
|
ExpectIntEQ(TLSX_Parse(ssl, full, fullLen, client_hello, suites), 0);
|
|
ssl->ctx->cm = origCM;
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_WriteRequest() / TLSX_GetRequestSize() - the "ssl->ctx &&
|
|
* ssl->ctx->extensions" merge guard. msgType values other than client_hello
|
|
* and certificate_request skip the whole leading block (including the
|
|
* SSL_CM(ssl) dereference that a NULL ssl->ctx could not survive), landing
|
|
* directly on this guard, so ssl->ctx can safely be forced NULL only for
|
|
* such a msgType. */
|
|
int test_TLSX_ext_dispatch_ctx_extensions_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
WOLFSSL_CTX* savedCtx = NULL;
|
|
byte out[64];
|
|
word32 offset;
|
|
word32 len;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* ssl->ctx == NULL: first operand false. server_hello is neither
|
|
* client_hello nor certificate_request, so the leading blocks that
|
|
* dereference ssl->ctx are skipped entirely before this line. */
|
|
savedCtx = ssl->ctx;
|
|
ssl->ctx = NULL;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, server_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, server_hello, &offset), 0);
|
|
ssl->ctx = savedCtx;
|
|
|
|
/* ssl->ctx != NULL, ssl->ctx->extensions == NULL (default): second
|
|
* operand false, first true. Still server_hello: with HAVE_ECH
|
|
* defined (as it is in this build), msgType == client_hello takes
|
|
* a wholly different "if (!ssl->options.disableECH && msgType ==
|
|
* client_hello) { ... } else { <this line> }" branch that never
|
|
* reaches this guard at all - server_hello is what actually lands
|
|
* on it, for every vector here. */
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, server_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, server_hello, &offset), 0);
|
|
|
|
/* ssl->ctx != NULL, ssl->ctx->extensions != NULL: both true. A
|
|
* renegotiation-info extension with NULL data writes just its
|
|
* length byte. server_hello has isRequest == false, so it also
|
|
* needs resp marked or TLSX_GetSize()/TLSX_Write()'s own
|
|
* "!isRequest && !extension->resp" guard skips it before ever
|
|
* reaching the ssl->ctx merge under test. */
|
|
{
|
|
/* ExpectNotNull() does not assign once an earlier expectation in
|
|
* the same test has failed, so this must start defined. */
|
|
TLSX* ext = NULL;
|
|
ExpectIntEQ(TLSX_Push(&ssl->ctx->extensions,
|
|
TLSX_RENEGOTIATION_INFO, NULL, ssl->ctx->heap), 0);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->ctx->extensions,
|
|
TLSX_RENEGOTIATION_INFO));
|
|
if (ext != NULL)
|
|
ext->resp = 1;
|
|
}
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, server_hello, &len), 0);
|
|
ExpectTrue(len > 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, server_hello, &offset), 0);
|
|
ExpectTrue(offset > 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_WriteRequest()'s and TLSX_GetRequestSize()'s extended-master-secret
|
|
* tails - both "msgType == client_hello && ssl->options.haveEMS &&
|
|
* (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)" - only the
|
|
* second operand (haveEMS) is open on each; the worklist's ":1" suffix. The
|
|
* first (msgType) and third (version/downgrade) already have pairs
|
|
* elsewhere. Both tails sit after the HAVE_ECH branch merges back together,
|
|
* so client_hello reaches them the same way in either function. */
|
|
int test_TLSX_WriteRequest_ems_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte out[64];
|
|
word32 offset;
|
|
word32 len;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* haveEMS == 0 (HAVE_EXTENDED_MASTER defaults it to 1; forced off
|
|
* here): second operand false. */
|
|
ssl->options.haveEMS = 0;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
|
|
/* haveEMS == 1: second operand true - independence for the second
|
|
* operand, first and third held at the same values as above. */
|
|
ssl->options.haveEMS = 1;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &len), 0);
|
|
ExpectTrue(len >= HELLO_EXT_SZ);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
ExpectTrue(offset > 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_WriteRequest()'s trailing length-prefix guard -
|
|
* "offset > OPAQUE16_LEN || msgType != client_hello". */
|
|
int test_TLSX_WriteRequest_length_prefix_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte out[64];
|
|
word32 offset;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* offset == OPAQUE16_LEN (nothing written), msgType == client_hello:
|
|
* both operands false - the length prefix is left unwritten. A
|
|
* fixed TLS 1.2 method with EMS explicitly off, and the
|
|
* empty renegotiation_info InitSSL() advertises by default for
|
|
* every client (SetupClientSecureRenegotiation()) removed, keeps
|
|
* this ssl from writing anything else of its own accord. */
|
|
ssl->options.haveEMS = 0;
|
|
TLSX_Remove(&ssl->extensions, TLSX_RENEGOTIATION_INFO, ssl->heap);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset),
|
|
0);
|
|
ExpectIntEQ(offset, OPAQUE16_LEN);
|
|
|
|
/* offset == OPAQUE16_LEN, msgType == certificate_request: second
|
|
* operand true, first false - independence for the second
|
|
* operand. */
|
|
offset = 0;
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS)
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, certificate_request, &offset),
|
|
0);
|
|
#endif
|
|
|
|
/* offset > OPAQUE16_LEN, msgType == client_hello: first operand
|
|
* true - independence for the first operand. A pushed
|
|
* renegotiation-info extension guarantees at least one byte gets
|
|
* written. */
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_RENEGOTIATION_INFO,
|
|
NULL, ssl->heap), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
ExpectTrue(offset > OPAQUE16_LEN);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_WriteResponse() - "TLSX_SupportExtensions(ssl) && output" (its own
|
|
* independence pair, separate from TLSX_WriteRequest()'s call to the same
|
|
* predicate) and the extended-master-secret tail
|
|
* "ssl->options.haveEMS && msgType == server_hello &&
|
|
* !IsAtLeastTLSv1_3(ssl->version)" (operands 1 and 2; operand 0 already
|
|
* has a pair elsewhere). TLSX_GetResponseSize() has the identical EMS tail
|
|
* one call earlier and is driven by the same three vectors. Both are
|
|
* WOLFSSL_LOCAL, reachable directly in this static build. */
|
|
int test_TLSX_WriteResponse_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_SERVER) && !defined(WOLFSSL_NO_TLS12) && \
|
|
defined(TEST_TLS_BOUNDS_SERVER_CERT) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
byte out[64];
|
|
word16 offset;
|
|
word16 len;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()));
|
|
ExpectIntEQ(test_tls_bounds_load_server_cert(ctx), TEST_SUCCESS);
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* TLSX_SupportExtensions(ssl) false (corrupted version.major, the
|
|
* only way to make it false - see test_TLSX_SupportExtensions_bounds
|
|
* above), output != NULL: first operand false. */
|
|
ssl->version.major = 0;
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteResponse(ssl, out, server_hello, &offset), 0);
|
|
ExpectIntEQ(offset, 0);
|
|
ssl->version.major = SSLv3_MAJOR;
|
|
ssl->version.minor = TLSv1_2_MINOR;
|
|
|
|
/* TLSX_SupportExtensions(ssl) true, output == NULL: second operand
|
|
* false, first true - independence for the second operand. */
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteResponse(ssl, NULL, server_hello, &offset), 0);
|
|
ExpectIntEQ(offset, 0);
|
|
|
|
/* Both true, haveEMS && server_hello && !TLS1.3: all three EMS
|
|
* operands true. */
|
|
ssl->options.haveEMS = 1;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetResponseSize(ssl, server_hello, &len), 0);
|
|
ExpectTrue(len >= HELLO_EXT_SZ);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteResponse(ssl, out, server_hello, &offset), 0);
|
|
ExpectTrue(offset > 0);
|
|
|
|
/* haveEMS true, msgType != server_hello: EMS operand 1 false -
|
|
* independence for operand 1 (operand 0 held true). */
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetResponseSize(ssl, encrypted_extensions, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteResponse(ssl, out, encrypted_extensions,
|
|
&offset), 0);
|
|
|
|
/* haveEMS true, msgType == server_hello, TLS 1.3: EMS operand 2
|
|
* false - independence for operand 2 (operands 0 and 1 held true). */
|
|
ssl->version.major = SSLv3_MAJOR;
|
|
ssl->version.minor = TLSv1_3_MINOR;
|
|
ssl->options.tls1_3 = 1;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetResponseSize(ssl, server_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteResponse(ssl, out, server_hello, &offset), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* The msgType splits shared by TLSX_SupportedVersions_GetSize()/_Write(),
|
|
* TLSX_EncryptThenMac_GetSize()/_Write(), TLSX_ClientCertificateType_GetSize()/
|
|
* _Write() and TLSX_ServerCertificateType_GetSize()/_Write() - all static-
|
|
* in-file, reached only through the generic TLSX_GetSize()/TLSX_Write()
|
|
* dispatch inside the WOLFSSL_TEST_VIS TLSX_GetRequestSize()/
|
|
* TLSX_WriteRequest(). Those two only use msgType to decide which top-level
|
|
* semaphore bits to set before the dispatch; the dispatch itself passes
|
|
* msgType straight through to each extension's own handler regardless of
|
|
* which wrapper made the call (see test_TLSX_Cookie_bounds() above for the
|
|
* same pattern). One ssl populated with all four extensions and driven
|
|
* through client_hello/server_hello/hello_retry_request/encrypted_extensions
|
|
* therefore exercises every open condition in this group in one binary. */
|
|
int test_TLSX_ext_msgtype_dispatch_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) && defined(HAVE_RPK) && \
|
|
defined(HAVE_TLS_EXTENSIONS)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
/* TLSX_PopulateExtensions() on a TLS 1.3 client also builds a real
|
|
* KeyShare (possibly a large post-quantum/hybrid group) and signature
|
|
* algorithm list, so this needs to be sized well past a single
|
|
* extension's record, not just the two pushed-by-hand ones under
|
|
* test - undersizing this the way an early pass did with a 16-byte
|
|
* buffer for a 29-byte record corrupts the stack. */
|
|
byte out[8192];
|
|
word32 offset;
|
|
word32 len;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* SupportedVersions and EncryptThenMac come from the normal
|
|
* client-side extension population; ClientCertificateType/
|
|
* ServerCertificateType are pushed directly (their real Use()
|
|
* paths need a loaded RPK certificate, which is not needed to
|
|
* reach the GetSize/Write msgType split under test). */
|
|
ExpectIntEQ(TLSX_PopulateExtensions(ssl, 0), 0);
|
|
ExpectNotNull(TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS));
|
|
ExpectNotNull(TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC));
|
|
|
|
ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
|
|
ssl->options.rpkState.sending_ClientCertTypes[0] = 0;
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE,
|
|
ssl, ssl->heap), 0);
|
|
ssl->options.rpkState.sending_ServerCertTypeCnt = 1;
|
|
ssl->options.rpkState.sending_ServerCertTypes[0] = 0;
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE,
|
|
ssl, ssl->heap), 0);
|
|
|
|
/* TLSX_GetSize()/TLSX_Write() skip any extension with resp == 0
|
|
* outright for every msgType that is not client_hello/
|
|
* certificate_request (their own leading "!isRequest &&
|
|
* !extension->resp" guard) - server_hello, hello_retry_request and
|
|
* encrypted_extensions all fall in that set. Each is marked resp
|
|
* only for the call(s) that actually exercise it: ServerHello
|
|
* needs all four; hello_retry_request only means anything to
|
|
* SupportedVersions/EncryptThenMac (ClientCertificateType/
|
|
* ServerCertificateType's own GetSize() has no case for it at all,
|
|
* and unlike TLSX_CSR_GetSize_ex() it does not clamp a negative
|
|
* SANITY_MSG_E before folding it into the word32 running total,
|
|
* so marking it resp for a msgType it was never meant to answer
|
|
* corrupts TLSX_GetSize()'s own accumulator - not the thing under
|
|
* test here); encrypted_extensions only means anything to
|
|
* ClientCertificateType/ServerCertificateType. */
|
|
{
|
|
TLSX* svExt = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS);
|
|
TLSX* etmExt = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
|
|
TLSX* cctExt = TLSX_Find(ssl->extensions,
|
|
TLSX_CLIENT_CERTIFICATE_TYPE);
|
|
TLSX* sctExt = TLSX_Find(ssl->extensions,
|
|
TLSX_SERVER_CERTIFICATE_TYPE);
|
|
ExpectNotNull(svExt);
|
|
ExpectNotNull(etmExt);
|
|
ExpectNotNull(cctExt);
|
|
ExpectNotNull(sctExt);
|
|
|
|
/* msgType == client_hello: SupportedVersions/ClientCertificateType/
|
|
* ServerCertificateType all take their "if (msgType ==
|
|
* client_hello)" branch (not part of any open condition here);
|
|
* EncryptThenMac's "msgType != client_hello" operand false. */
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, client_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset),
|
|
0);
|
|
|
|
/* msgType == server_hello: SupportedVersions/
|
|
* ClientCertificateType/ServerCertificateType operand 0 true;
|
|
* EncryptThenMac operand 0 true, operand 1 false. */
|
|
if (svExt != NULL) svExt->resp = 1;
|
|
if (etmExt != NULL) etmExt->resp = 1;
|
|
if (cctExt != NULL) cctExt->resp = 1;
|
|
if (sctExt != NULL) sctExt->resp = 1;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, server_hello, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, server_hello, &offset),
|
|
0);
|
|
if (cctExt != NULL) cctExt->resp = 0;
|
|
if (sctExt != NULL) sctExt->resp = 0;
|
|
|
|
/* msgType == hello_retry_request: SupportedVersions operand 0
|
|
* false, operand 1 true; EncryptThenMac both operands true -
|
|
* SANITY_MSG_E, which TLSX_GetSize()/TLSX_Write() propagate up.
|
|
* ClientCertificateType/ServerCertificateType left resp == 0
|
|
* (skipped) for exactly the reason in the comment above. */
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, hello_retry_request, &len),
|
|
WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, hello_retry_request,
|
|
&offset), WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
if (svExt != NULL) svExt->resp = 0;
|
|
if (etmExt != NULL) etmExt->resp = 0;
|
|
}
|
|
|
|
/* msgType == encrypted_extensions: ClientCertificateType/
|
|
* ServerCertificateType operand 0 false, operand 1 true. */
|
|
{
|
|
TLSX* cctExt = TLSX_Find(ssl->extensions,
|
|
TLSX_CLIENT_CERTIFICATE_TYPE);
|
|
TLSX* sctExt = TLSX_Find(ssl->extensions,
|
|
TLSX_SERVER_CERTIFICATE_TYPE);
|
|
if (cctExt != NULL) cctExt->resp = 1;
|
|
if (sctExt != NULL) sctExt->resp = 1;
|
|
}
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, encrypted_extensions, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, encrypted_extensions,
|
|
&offset), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* The "both false" baseline row for each of the three OR-shaped msgType
|
|
* splits above (SupportedVersions/ClientCertificateType/
|
|
* ServerCertificateType) still needs one more vector each: a msgType
|
|
* that is neither of the two the extension recognizes. server_hello/
|
|
* hello_retry_request/encrypted_extensions above only ever showed one
|
|
* extension's operands both false as a side effect of some OTHER
|
|
* extension being absent or skipped from that same call - never this
|
|
* extension, reached with resp honored, on a call of its own. Each
|
|
* pushed alone (fresh ssl, so no cross-extension interaction) with an
|
|
* unused msgType supplies it. ClientCertificateType/
|
|
* ServerCertificateType's TLSX_GetSize() case does not clamp the
|
|
* SANITY_MSG_E their GetSize() returns here (unlike TLSX_Write()'s
|
|
* case, which returns a word16 that is always 0 in this branch) before
|
|
* folding it into the running total, so TLSX_GetRequestSize() itself
|
|
* comes back BUFFER_E rather than SANITY_MSG_E - a preexisting
|
|
* TLSX_GetSize() quirk, not the thing under test, and not asserted on
|
|
* beyond "some error". */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
/* TLSX_SetSupportedVersions() is static-in-file; its whole body is
|
|
* "return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, data,
|
|
* heap);" with data == ssl, called directly here instead. */
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, ssl,
|
|
ssl->heap), 0);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions,
|
|
TLSX_SUPPORTED_VERSIONS));
|
|
if (ext != NULL)
|
|
ext->resp = 1;
|
|
len = 0;
|
|
ExpectIntEQ(TLSX_GetRequestSize(ssl, encrypted_extensions, &len),
|
|
WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, encrypted_extensions,
|
|
&offset), WC_NO_ERR_TRACE(SANITY_MSG_E));
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE,
|
|
ssl, ssl->heap), 0);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions,
|
|
TLSX_CLIENT_CERTIFICATE_TYPE));
|
|
if (ext != NULL)
|
|
ext->resp = 1;
|
|
len = 0;
|
|
ExpectIntNE(TLSX_GetRequestSize(ssl, hello_retry_request, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, hello_retry_request,
|
|
&offset), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
ssl->options.rpkState.sending_ServerCertTypeCnt = 1;
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE,
|
|
ssl, ssl->heap), 0);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions,
|
|
TLSX_SERVER_CERTIFICATE_TYPE));
|
|
if (ext != NULL)
|
|
ext->resp = 1;
|
|
len = 0;
|
|
ExpectIntNE(TLSX_GetRequestSize(ssl, hello_retry_request, &len), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, hello_retry_request,
|
|
&offset), 0);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_SecureRenegotiation_Write() - "data && data->enabled &&
|
|
* data->verifySet". Only the first operand is open; a NULL data pointer is
|
|
* the "HAVE_SERVER_RENEGOTIATION_INFO only" empty-extension shape the
|
|
* function's own comment describes, produced here directly with
|
|
* TLSX_Push() rather than through a real renegotiation handshake. */
|
|
int test_TLSX_SecureRenegotiation_Write_bounds(void)
|
|
{
|
|
#if defined(WOLFSSL_TEST_STATIC_BUILD) && (defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_TLS_EXTENSIONS) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
/* Sized from the vector: prefix(2) + type(2) + len(2) + reneg length
|
|
* byte(1) + client_verify_data(TLS_FINISHED_SZ==12) == 19 bytes for
|
|
* the enabled/verifySet case below. */
|
|
byte out[32];
|
|
word32 offset;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()));
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
/* data == NULL: first operand false. InitSSL() already advertises
|
|
* an empty renegotiation_info by default for every client
|
|
* (SetupClientSecureRenegotiation(), with real, non-NULL data) -
|
|
* remove it first so this vector's own NULL-data push is the only
|
|
* TLSX_RENEGOTIATION_INFO node on the list. */
|
|
ssl->options.haveEMS = 0;
|
|
TLSX_Remove(&ssl->extensions, TLSX_RENEGOTIATION_INFO, ssl->heap);
|
|
ExpectIntEQ(TLSX_Push(&ssl->extensions, TLSX_RENEGOTIATION_INFO,
|
|
NULL, ssl->heap), 0);
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset), 0);
|
|
ExpectIntEQ(offset, OPAQUE16_LEN + HELLO_EXT_TYPE_SZ + OPAQUE16_LEN +
|
|
OPAQUE8_LEN);
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* data != NULL, enabled and verifySet both true: first operand true -
|
|
* independence for the first operand. wolfSSL_UseSecureRenegotiation()
|
|
* allocates data; verifySet/enabled are then set directly (only ever
|
|
* set true together, by a real Finished exchange in the non-test
|
|
* path). */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
if (ssl != NULL) {
|
|
TLSX* ext = NULL;
|
|
SecureRenegotiation* data;
|
|
|
|
ssl->options.haveEMS = 0;
|
|
ExpectIntEQ(wolfSSL_UseSecureRenegotiation(ssl), WOLFSSL_SUCCESS);
|
|
ExpectNotNull(ext = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO));
|
|
if (ext != NULL) {
|
|
data = (SecureRenegotiation*)ext->data;
|
|
data->enabled = 1;
|
|
data->verifySet = 1;
|
|
offset = 0;
|
|
ExpectIntEQ(TLSX_WriteRequest(ssl, out, client_hello, &offset),
|
|
0);
|
|
ExpectIntEQ(offset, OPAQUE16_LEN + HELLO_EXT_TYPE_SZ +
|
|
OPAQUE16_LEN + OPAQUE8_LEN + TLS_FINISHED_SZ);
|
|
}
|
|
}
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* TLSX_SessionTicket_Parse() (server, TLS 1.2), the "ret is REJECT or
|
|
* VERSION_ERROR" branch after "ret = DoClientTicket(...)". The
|
|
* false/false row - ret is neither value - needs a DoClientTicket() return
|
|
* that is none of WOLFSSL_TICKET_RET_OK/_CREATE/_REJECT or VERSION_ERROR.
|
|
* DoDecryptTicket() has exactly one such path: when the registered
|
|
* SessionTicketEncCb reports success but writes an out-of-range outLen,
|
|
* DoDecryptTicket() returns BAD_TICKET_KEY_CB_SZ directly - none of the
|
|
* four TicketEncRet values and unrelated to VERSION_ERROR - and
|
|
* DoClientTicket() passes that straight back up unchanged (it does not
|
|
* reach WOLFSSL_TICKET_RET_REJECT; every REJECT return in DoDecryptTicket()
|
|
* is a distinct, earlier guard). TLSX_SessionTicket_Parse() then falls to
|
|
* its own "else if (ret < 0)" tail, leaving ret untouched, so the negative
|
|
* value propagates out of TLSX_Parse() and fails the handshake - a real,
|
|
* protocol-level row, not a callee postcondition that collapses it into
|
|
* REJECT. So: covered, not excluded. */
|
|
#ifdef TEST_TLS_BOUNDS_SESSION_TICKET_FF
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_TLSX_SessionTicket_ff_enc_cb(WOLFSSL* ssl,
|
|
byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ],
|
|
byte mac[WOLFSSL_TICKET_MAC_SZ], int enc, byte* ticket, int inLen,
|
|
int* outLen, void* userCtx)
|
|
{
|
|
int i;
|
|
(void)ssl; (void)userCtx;
|
|
|
|
if (enc) {
|
|
XMEMSET(key_name, 0x11, WOLFSSL_TICKET_NAME_SZ);
|
|
XMEMSET(iv, 0x22, WOLFSSL_TICKET_IV_SZ);
|
|
XMEMSET(mac, 0x33, WOLFSSL_TICKET_MAC_SZ);
|
|
/* DoCreateTicket()'s own sanity check rejects an encrypt callback
|
|
* that leaves the internal ticket bytes unchanged, so this has to
|
|
* actually transform them, not just report success. */
|
|
for (i = 0; i < inLen; i++)
|
|
ticket[i] = (byte)(ticket[i] ^ 0xA5);
|
|
*outLen = inLen;
|
|
}
|
|
else {
|
|
/* Report success with an out-of-range outLen: DoDecryptTicket()'s
|
|
* own "outLen > inLen || outLen < WOLFSSL_INTERNAL_TICKET_LEN"
|
|
* guard turns this into BAD_TICKET_KEY_CB_SZ. */
|
|
*outLen = 0;
|
|
}
|
|
return WOLFSSL_TICKET_RET_OK;
|
|
}
|
|
|
|
TEST_TLS_BOUNDS_UNUSED
|
|
static int test_TLSX_SessionTicket_ff_ctx_ready(WOLFSSL_CTX* ctx)
|
|
{
|
|
EXPECT_DECLS;
|
|
ExpectIntEQ(wolfSSL_CTX_set_TicketEncCb(ctx,
|
|
test_TLSX_SessionTicket_ff_enc_cb), WOLFSSL_SUCCESS);
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
int test_TLSX_SessionTicket_Parse_falsefalse_bounds(void)
|
|
{
|
|
#if defined(TEST_TLS_BOUNDS_SESSION_TICKET_FF) && \
|
|
!defined(WOLFSSL_NO_TLS12)
|
|
EXPECT_DECLS;
|
|
test_ssl_memio_ctx test_ctx;
|
|
WOLFSSL_SESSION* sess = NULL;
|
|
|
|
/* First connection: issue a ticket (enc == 1 path only). */
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
test_ctx.c_cb.method = wolfTLSv1_2_client_method;
|
|
test_ctx.s_cb.method = wolfTLSv1_2_server_method;
|
|
test_ctx.s_cb.ctx_ready = test_TLSX_SessionTicket_ff_ctx_ready;
|
|
ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_UseSessionTicket(test_ctx.c_ssl), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
|
|
TEST_SUCCESS);
|
|
ExpectNotNull(sess = wolfSSL_get1_session(test_ctx.c_ssl));
|
|
test_ssl_memio_cleanup(&test_ctx);
|
|
|
|
/* Second connection: present that ticket back (enc == 0 path), which
|
|
* the callback now deliberately corrupts. */
|
|
if (sess != NULL) {
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
test_ctx.c_cb.method = wolfTLSv1_2_client_method;
|
|
test_ctx.s_cb.method = wolfTLSv1_2_server_method;
|
|
test_ctx.s_cb.ctx_ready = test_TLSX_SessionTicket_ff_ctx_ready;
|
|
ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_session(test_ctx.c_ssl, sess),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
|
|
TEST_FAIL);
|
|
test_ssl_memio_cleanup(&test_ctx);
|
|
}
|
|
wolfSSL_SESSION_free(sess);
|
|
|
|
return EXPECT_RESULT();
|
|
#else
|
|
return TEST_SKIPPED;
|
|
#endif
|
|
}
|