mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 17:30:51 +02:00
e5f569ad7c
Per RFC 8446 section 8, a server MUST ensure that any instance of it
would accept 0-RTT for the same 0-RTT handshake at most once. Without
this, the same ClientHello could be replayed to re-accept early data on
a subsequent connection.
After the PSK is authenticated (binder verified) in DoPreSharedKeys,
call wolfSSL_SSL_CTX_remove_session on ssl->session when the client
offered 0-RTT and the session permits it. That evicts the entry from
the internal cache (under the row's write lock) and invokes the
application's ctx->rem_sess_cb so any external cache can drop its copy
too. The session's timeout is also cleared so the live reference held
by the current handshake cannot be resumed again.
The mutation is paid only when the client actually included the
early_data extension on a 0-RTT-capable session, so normal resumptions
are unaffected and the existing remove-callback counts in
test_wolfSSL_CTX_add_session_ext_{tls13,dtls13} stay correct.
wolfSSL_SSL_CTX_remove_session was previously declared and defined only
under the OpenSSL compatibility layer. Because it is now called from
the core TLS 1.3 PSK path, the declaration in wolfssl/ssl.h and the
definition in src/ssl_sess.c are moved out of that block to match the
existing !NO_SESSION_CACHE gate under which the function is meaningful.
wolfSSL_SSL_get0_session stays in the compat block.
test_tls13_early_data_0rtt_replay verifies the behaviour. It does a
full TLS 1.3 handshake with stateful tickets (SSL_OP_NO_TICKET) and
max_early_data > 0, then tries to resume the saved session twice while
offering 0-RTT each time. A minimal single-slot external session cache
is wired up via wolfSSL_CTX_sess_set_{new,get,remove}_cb to confirm
both caches are cleared. Round 0 must resume and deliver the early
data, and rem_calls must hit 1 (the fix's single eviction). Round 1
must fall back to a full handshake (session_reused == 0), deliver no
early data, and leave rem_calls at 1.
Verified against multiple configurations (incl. --enable-all
--enable-earlydata, the no-compat -DHAVE_EXT_CACHE build, and the
os-check.yml combo). Valgrind under -g2 -O0 with OPENSSL_EXTRA +
HAVE_EXT_CACHE + HAVE_EX_DATA reports no errors and no
definitely-lost bytes.
Refs wolfSSL/wolfssl#10197
3932 lines
146 KiB
C
3932 lines
146 KiB
C
/* test_tls13.c
|
|
*
|
|
* 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>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/internal.h>
|
|
#include <tests/api/api.h>
|
|
#include <tests/utils.h>
|
|
#include <tests/api/test_tls13.h>
|
|
|
|
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
|
|
#ifdef WC_SHA384_DIGEST_SIZE
|
|
WC_MAYBE_UNUSED static byte fixedKey[WC_SHA384_DIGEST_SIZE] = { 0, };
|
|
#else
|
|
WC_MAYBE_UNUSED static byte fixedKey[WC_SHA256_DIGEST_SIZE] = { 0, };
|
|
#endif
|
|
#endif
|
|
#ifdef WOLFSSL_EARLY_DATA
|
|
static const char earlyData[] = "Early Data";
|
|
static char earlyDataBuffer[1];
|
|
#endif
|
|
|
|
int test_tls13_apis(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#ifdef WOLFSSL_TLS13
|
|
#if defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC) && \
|
|
(!defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT))
|
|
int ret;
|
|
#endif
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
WOLFSSL_CTX* clientTls12Ctx = NULL;
|
|
WOLFSSL* clientTls12Ssl = NULL;
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
WOLFSSL_CTX* serverTls12Ctx = NULL;
|
|
WOLFSSL* serverTls12Ssl = NULL;
|
|
#endif
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
WOLFSSL_CTX* clientCtx = NULL;
|
|
WOLFSSL* clientSsl = NULL;
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
WOLFSSL_CTX* serverCtx = NULL;
|
|
WOLFSSL* serverSsl = NULL;
|
|
#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM)
|
|
#ifndef NO_RSA
|
|
const char* ourCert = svrCertFile;
|
|
const char* ourKey = svrKeyFile;
|
|
#elif defined(HAVE_ECC)
|
|
const char* ourCert = eccCertFile;
|
|
const char* ourKey = eccKeyFile;
|
|
#elif defined(HAVE_ED25519)
|
|
const char* ourCert = edCertFile;
|
|
const char* ourKey = edKeyFile;
|
|
#elif defined(HAVE_ED448)
|
|
const char* ourCert = ed448CertFile;
|
|
const char* ourKey = ed448KeyFile;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
int required;
|
|
#ifdef WOLFSSL_EARLY_DATA
|
|
int outSz;
|
|
#endif
|
|
#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
|
|
int groups[2] = { WOLFSSL_ECC_SECP256R1,
|
|
#ifdef WOLFSSL_HAVE_MLKEM
|
|
#ifdef WOLFSSL_MLKEM_KYBER
|
|
#ifndef WOLFSSL_NO_KYBER512
|
|
WOLFSSL_KYBER_LEVEL1
|
|
#elif !defined(WOLFSSL_NO_KYBER768)
|
|
WOLFSSL_KYBER_LEVEL3
|
|
#else
|
|
WOLFSSL_KYBER_LEVEL5
|
|
#endif
|
|
#elif !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
#ifndef WOLFSSL_NO_ML_KEM_512
|
|
WOLFSSL_ML_KEM_512
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768)
|
|
WOLFSSL_ML_KEM_768
|
|
#else
|
|
WOLFSSL_ML_KEM_1024
|
|
#endif
|
|
#else
|
|
#ifndef WOLFSSL_NO_ML_KEM_768
|
|
WOLFSSL_SECP256R1MLKEM768
|
|
#else
|
|
WOLFSSL_ECC_SECP256R1
|
|
#endif
|
|
#endif
|
|
#else
|
|
WOLFSSL_ECC_SECP256R1
|
|
#endif
|
|
};
|
|
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
|
|
int bad_groups[2] = { 0xDEAD, 0xBEEF };
|
|
#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
|
|
int numGroups = 2;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_CLIENT)
|
|
int too_many_groups[WOLFSSL_MAX_GROUP_COUNT + 1];
|
|
#endif
|
|
#endif
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
|
|
char groupList[] =
|
|
#ifdef HAVE_CURVE25519
|
|
"X25519:"
|
|
#endif
|
|
#ifdef HAVE_CURVE448
|
|
"X448:"
|
|
#endif
|
|
#ifndef NO_ECC_SECP
|
|
#if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
|
|
"P-521:secp521r1:"
|
|
#endif
|
|
#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
|
|
"P-384:secp384r1:"
|
|
#endif
|
|
#if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
|
|
"P-256:secp256r1"
|
|
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
|
|
#ifdef WOLFSSL_MLKEM_KYBER
|
|
#ifndef WOLFSSL_NO_KYBER512
|
|
":P256_KYBER_LEVEL1"
|
|
#elif !defined(WOLFSSL_NO_KYBER768)
|
|
":P256_KYBER_LEVEL3"
|
|
#elif !defined(WOLFSSL_NO_KYBER1024)
|
|
":P256_KYBER_LEVEL5"
|
|
#endif
|
|
#else
|
|
#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(WOLFSSL_EXTRA_PQC_HYBRIDS)
|
|
":SecP256r1MLKEM512"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_PQC_HYBRIDS)
|
|
":SecP256r1MLKEM768"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_1024) && defined(WOLFSSL_PQC_HYBRIDS)
|
|
":SecP384r1MLKEM1024"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_1024) && \
|
|
!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
":ML_KEM_1024"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768) && \
|
|
!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
":ML_KEM_768"
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif /* !defined(NO_ECC_SECP) */
|
|
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
|
|
#ifdef WOLFSSL_MLKEM_KYBER
|
|
#ifndef WOLFSSL_NO_KYBER512
|
|
":KYBER_LEVEL1"
|
|
#elif !defined(WOLFSSL_NO_KYBER768)
|
|
":KYBER_LEVEL3"
|
|
#elif !defined(WOLFSSL_NO_KYBER1024)
|
|
":KYBER_LEVEL5"
|
|
#endif
|
|
#elif !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
#if !defined(WOLFSSL_NO_ML_KEM_512)
|
|
":ML_KEM_512"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768)
|
|
":ML_KEM_768"
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_1024)
|
|
":ML_KEM_1024"
|
|
#endif
|
|
#endif
|
|
#endif
|
|
"";
|
|
#endif /* defined(OPENSSL_EXTRA) && defined(HAVE_ECC) */
|
|
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
defined(HAVE_SUPPORTED_CURVES) && \
|
|
(!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \
|
|
(defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \
|
|
(defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768)))
|
|
int mlkemLevel;
|
|
#endif
|
|
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
clientTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
|
|
clientTls12Ssl = wolfSSL_new(clientTls12Ctx);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
serverTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
|
|
#if !defined(NO_CERTS)
|
|
#if !defined(NO_FILESYSTEM)
|
|
wolfSSL_CTX_use_certificate_chain_file(serverTls12Ctx, ourCert);
|
|
wolfSSL_CTX_use_PrivateKey_file(serverTls12Ctx, ourKey,
|
|
CERT_FILETYPE);
|
|
#elif defined(USE_CERT_BUFFERS_2048)
|
|
wolfSSL_CTX_use_certificate_chain_buffer_format(serverTls12Ctx,
|
|
server_cert_der_2048, sizeof_server_cert_der_2048,
|
|
WOLFSSL_FILETYPE_ASN1);
|
|
wolfSSL_CTX_use_PrivateKey_buffer(serverTls12Ctx, server_key_der_2048,
|
|
sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1);
|
|
#elif defined(USE_CERT_BUFFERS_256)
|
|
wolfSSL_CTX_use_certificate_chain_buffer_format(serverTls12Ctx,
|
|
serv_ecc_der_256, sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
|
|
wolfSSL_CTX_use_PrivateKey_buffer(serverTls12Ctx, ecc_key_der_256,
|
|
sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
|
|
#endif
|
|
#endif
|
|
serverTls12Ssl = wolfSSL_new(serverTls12Ctx);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
clientCtx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
|
|
clientSsl = wolfSSL_new(clientCtx);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
serverCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
|
|
#if !defined(NO_CERTS)
|
|
/* ignore load failures, since we just need the server to have a cert set */
|
|
#if !defined(NO_FILESYSTEM)
|
|
wolfSSL_CTX_use_certificate_chain_file(serverCtx, ourCert);
|
|
wolfSSL_CTX_use_PrivateKey_file(serverCtx, ourKey, CERT_FILETYPE);
|
|
#elif defined(USE_CERT_BUFFERS_2048)
|
|
wolfSSL_CTX_use_certificate_chain_buffer_format(serverCtx,
|
|
server_cert_der_2048, sizeof_server_cert_der_2048,
|
|
WOLFSSL_FILETYPE_ASN1);
|
|
wolfSSL_CTX_use_PrivateKey_buffer(serverCtx, server_key_der_2048,
|
|
sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1);
|
|
#elif defined(USE_CERT_BUFFERS_256)
|
|
wolfSSL_CTX_use_certificate_chain_buffer_format(serverCtx, serv_ecc_der_256,
|
|
sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
|
|
wolfSSL_CTX_use_PrivateKey_buffer(serverCtx, ecc_key_der_256,
|
|
sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
|
|
#endif
|
|
#endif
|
|
serverSsl = wolfSSL_new(serverCtx);
|
|
ExpectNotNull(serverSsl);
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SEND_HRR_COOKIE
|
|
ExpectIntEQ(wolfSSL_send_hrr_cookie(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_send_hrr_cookie(clientSsl, NULL, 0),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_send_hrr_cookie(serverTls12Ssl, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_send_hrr_cookie(serverSsl, NULL, 0), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_send_hrr_cookie(serverSsl, fixedKey, sizeof(fixedKey)),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef HAVE_SUPPORTED_CURVES
|
|
#ifdef HAVE_ECC
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
do {
|
|
ret = wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_SECP256R1);
|
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
|
|
wolfSSL_AsyncPoll(serverSsl, WOLF_POLL_FLAG_CHECK_HW);
|
|
#endif
|
|
}
|
|
while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
|
|
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
do {
|
|
ret = wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1);
|
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
|
|
wolfSSL_AsyncPoll(clientTls12Ssl, WOLF_POLL_FLAG_CHECK_HW);
|
|
#endif
|
|
}
|
|
while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
|
|
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
|
#endif
|
|
do {
|
|
ret = wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1);
|
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
|
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
|
|
wolfSSL_AsyncPoll(clientSsl, WOLF_POLL_FLAG_CHECK_HW);
|
|
#endif
|
|
}
|
|
while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
|
|
ExpectIntEQ(ret, WOLFSSL_SUCCESS);
|
|
#endif
|
|
#elif defined(HAVE_CURVE25519)
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_X25519),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_X25519),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_X25519),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_X25519),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#elif defined(HAVE_CURVE448)
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_X448),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_ECC_X448),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_X448),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_X448),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#else
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_ECC_SECP256R1),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_ECC_SECP256R1),
|
|
WC_NO_ERR_TRACE(NOT_COMPILED_IN));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1),
|
|
WC_NO_ERR_TRACE(NOT_COMPILED_IN));
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
(!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \
|
|
(defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \
|
|
(defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768)))
|
|
#ifndef WOLFSSL_NO_ML_KEM
|
|
#ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE
|
|
#ifndef WOLFSSL_NO_ML_KEM_768
|
|
mlkemLevel = WOLFSSL_ML_KEM_768;
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_1024)
|
|
mlkemLevel = WOLFSSL_ML_KEM_1024;
|
|
#else
|
|
mlkemLevel = WOLFSSL_ML_KEM_512;
|
|
#endif
|
|
#else
|
|
#if defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)
|
|
mlkemLevel = WOLFSSL_X25519MLKEM768;
|
|
#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768)
|
|
mlkemLevel = WOLFSSL_SECP256R1MLKEM768;
|
|
#endif
|
|
#endif
|
|
#else
|
|
#ifndef WOLFSSL_NO_KYBER768
|
|
mlkemLevel = WOLFSSL_KYBER_LEVEL3;
|
|
#elif !defined(WOLFSSL_NO_KYBER1024)
|
|
mlkemLevel = WOLFSSL_KYBER_LEVEL5;
|
|
#else
|
|
mlkemLevel = WOLFSSL_KYBER_LEVEL1;
|
|
#endif
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(NULL, mlkemLevel),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(serverSsl, mlkemLevel),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, mlkemLevel),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(clientSsl, mlkemLevel),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_NoKeyShares(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_NoKeyShares(serverSsl), WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_NoKeyShares(clientTls12Ssl), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_NoKeyShares(clientSsl), WOLFSSL_SUCCESS);
|
|
#endif
|
|
#endif /* HAVE_SUPPORTED_CURVES */
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_no_ticket_TLSv13(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_CTX_no_ticket_TLSv13(clientCtx),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverTls12Ctx),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_no_ticket_TLSv13(serverCtx), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(clientSsl),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(serverTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(serverSsl), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_no_dhe_psk(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_CTX_no_dhe_psk(clientTls12Ctx),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_no_dhe_psk(clientCtx), 0);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_CTX_no_dhe_psk(serverCtx), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_no_dhe_psk(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_no_dhe_psk(clientTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_no_dhe_psk(clientSsl), 0);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_no_dhe_psk(serverSsl), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_update_keys(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_update_keys(clientTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_update_keys(clientSsl),
|
|
WC_NO_ERR_TRACE(BUILD_MSG_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_update_keys(serverSsl),
|
|
WC_NO_ERR_TRACE(BUILD_MSG_ERROR));
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_key_update_response(NULL, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_key_update_response(NULL, &required),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_key_update_response(clientTls12Ssl, &required),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_key_update_response(clientSsl, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_key_update_response(serverSsl, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
|
|
#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
|
|
ExpectIntEQ(wolfSSL_CTX_allow_post_handshake_auth(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_CTX_allow_post_handshake_auth(serverCtx),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientTls12Ctx),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_allow_post_handshake_auth(clientCtx), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_allow_post_handshake_auth(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_allow_post_handshake_auth(serverSsl),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_allow_post_handshake_auth(clientTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_allow_post_handshake_auth(clientSsl), 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_request_certificate(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_request_certificate(clientSsl),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_request_certificate(serverTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_request_certificate(serverSsl),
|
|
WC_NO_ERR_TRACE(NOT_READY_ERROR));
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef HAVE_ECC
|
|
#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT
|
|
ExpectIntEQ(wolfSSL_preferred_group(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_preferred_group(serverSsl),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_preferred_group(clientTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_preferred_group(clientSsl),
|
|
WC_NO_ERR_TRACE(NOT_READY_ERROR));
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef HAVE_SUPPORTED_CURVES
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(clientCtx, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(NULL, groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(clientTls12Ctx, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups,
|
|
WOLFSSL_MAX_GROUP_COUNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(clientCtx, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(clientCtx, bad_groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(serverCtx, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_set_groups(serverCtx, bad_groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_set_groups(NULL, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_set_groups(clientSsl, NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_set_groups(NULL, groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_set_groups(clientTls12Ssl, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_set_groups(clientSsl, groups,
|
|
WOLFSSL_MAX_GROUP_COUNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_set_groups(clientSsl, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_groups(clientSsl, bad_groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_set_groups(serverSsl, groups, numGroups),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_groups(serverSsl, bad_groups, numGroups),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
|
|
#ifdef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(NULL, NULL),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(clientCtx, NULL),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(NULL, groupList),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_CLIENT)
|
|
{
|
|
int idx;
|
|
for (idx = 0; idx < WOLFSSL_MAX_GROUP_COUNT + 1; idx++)
|
|
too_many_groups[idx] = WOLFSSL_ECC_SECP256R1;
|
|
}
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups(clientCtx, too_many_groups,
|
|
WOLFSSL_MAX_GROUP_COUNT + 1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
ExpectIntEQ(wolfSSL_set1_groups(clientSsl, too_many_groups,
|
|
WOLFSSL_MAX_GROUP_COUNT + 1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(clientTls12Ctx, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(clientCtx, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_CTX_set1_groups_list(serverCtx, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(NULL, NULL),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(clientSsl, NULL),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(NULL, groupList),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(clientTls12Ssl, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(clientSsl, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_set1_groups_list(serverSsl, groupList),
|
|
WOLFSSL_SUCCESS);
|
|
#endif
|
|
#endif /* OPENSSL_EXTRA */
|
|
#endif /* HAVE_SUPPORTED_CURVES */
|
|
#endif /* HAVE_ECC */
|
|
|
|
#ifdef WOLFSSL_EARLY_DATA
|
|
#ifndef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_set_max_early_data(NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_get_max_early_data(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#else
|
|
ExpectIntEQ(SSL_CTX_set_max_early_data(NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(SSL_CTX_get_max_early_data(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_set_max_early_data(clientCtx, 0),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
ExpectIntEQ(wolfSSL_CTX_get_max_early_data(clientCtx),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#else
|
|
ExpectIntEQ(SSL_CTX_set_max_early_data(clientCtx, 0),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
ExpectIntEQ(SSL_CTX_get_max_early_data(clientCtx),
|
|
WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifndef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_CTX_set_max_early_data(serverTls12Ctx, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_get_max_early_data(serverTls12Ctx),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#else
|
|
ExpectIntEQ(SSL_CTX_set_max_early_data(serverTls12Ctx, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(SSL_CTX_get_max_early_data(serverTls12Ctx),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#endif
|
|
#ifndef OPENSSL_EXTRA
|
|
#ifdef WOLFSSL_ERROR_CODE_OPENSSL
|
|
ExpectIntEQ(wolfSSL_CTX_set_max_early_data(serverCtx, 32),
|
|
WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_CTX_set_max_early_data(serverCtx, 32), 0);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_CTX_get_max_early_data(serverCtx), 32);
|
|
#else
|
|
ExpectIntEQ(SSL_CTX_set_max_early_data(serverCtx, 32), 1);
|
|
ExpectIntEQ(SSL_CTX_get_max_early_data(serverCtx), 32);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(NULL, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_get_max_early_data(NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#else
|
|
ExpectIntEQ(SSL_set_max_early_data(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(SSL_get_max_early_data(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef OPENSSL_EXTRA
|
|
#ifdef WOLFSSL_ERROR_CODE_OPENSSL
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(clientSsl, 17), WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(clientSsl, 17), 0);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_get_max_early_data(clientSsl), 17);
|
|
#else
|
|
ExpectIntEQ(SSL_set_max_early_data(clientSsl, 17), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(SSL_get_max_early_data(clientSsl), 17);
|
|
#endif
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifndef OPENSSL_EXTRA
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(serverTls12Ssl, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_get_max_early_data(serverTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#else
|
|
ExpectIntEQ(SSL_set_max_early_data(serverTls12Ssl, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(SSL_get_max_early_data(serverTls12Ssl),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#endif
|
|
#ifndef OPENSSL_EXTRA
|
|
#ifdef WOLFSSL_ERROR_CODE_OPENSSL
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(serverSsl, 16), WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(serverSsl, 16), 0);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_get_max_early_data(serverSsl), 16);
|
|
#else
|
|
ExpectIntEQ(SSL_set_max_early_data(serverSsl, 16), 1);
|
|
ExpectIntEQ(SSL_get_max_early_data(serverSsl), 16);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
ExpectIntEQ(wolfSSL_write_early_data(NULL, earlyData, sizeof(earlyData),
|
|
&outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientSsl, NULL, sizeof(earlyData),
|
|
&outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData, -1, &outSz),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData,
|
|
sizeof(earlyData), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_write_early_data(serverSsl, earlyData,
|
|
sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientTls12Ssl, earlyData,
|
|
sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
/* invoking without session or psk cbs */
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData,
|
|
sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_STATE_E));
|
|
/* verify *outSz is initialized to 0 even on non-success paths */
|
|
outSz = 42;
|
|
ExpectIntEQ(wolfSSL_write_early_data(clientSsl, earlyData,
|
|
sizeof(earlyData), &outSz), WC_NO_ERR_TRACE(BAD_STATE_E));
|
|
ExpectIntEQ(outSz, 0);
|
|
#endif
|
|
|
|
ExpectIntEQ(wolfSSL_read_early_data(NULL, earlyDataBuffer,
|
|
sizeof(earlyDataBuffer), &outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
ExpectIntEQ(wolfSSL_read_early_data(serverSsl, NULL,
|
|
sizeof(earlyDataBuffer), &outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer, -1,
|
|
&outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer,
|
|
sizeof(earlyDataBuffer), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
ExpectIntEQ(wolfSSL_read_early_data(clientSsl, earlyDataBuffer,
|
|
sizeof(earlyDataBuffer), &outSz), WC_NO_ERR_TRACE(SIDE_ERROR));
|
|
#endif
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
ExpectIntEQ(wolfSSL_read_early_data(serverTls12Ssl, earlyDataBuffer,
|
|
sizeof(earlyDataBuffer), &outSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_read_early_data(serverSsl, earlyDataBuffer,
|
|
sizeof(earlyDataBuffer), &outSz), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_EARLY_DATA)
|
|
ExpectIntLT(SSL_get_early_data_status(NULL), 0);
|
|
#endif
|
|
|
|
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
wolfSSL_free(serverSsl);
|
|
wolfSSL_CTX_free(serverCtx);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
wolfSSL_free(clientSsl);
|
|
wolfSSL_CTX_free(clientCtx);
|
|
#endif
|
|
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
#ifndef NO_WOLFSSL_SERVER
|
|
wolfSSL_free(serverTls12Ssl);
|
|
wolfSSL_CTX_free(serverTls12Ctx);
|
|
#endif
|
|
#ifndef NO_WOLFSSL_CLIENT
|
|
wolfSSL_free(clientTls12Ssl);
|
|
wolfSSL_CTX_free(clientTls12Ctx);
|
|
#endif
|
|
#endif
|
|
#endif /* WOLFSSL_TLS13 */
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
|
|
!defined(NO_WOLFSSL_SERVER) && defined(HAVE_ECC) && \
|
|
defined(BUILD_TLS_AES_128_GCM_SHA256) && \
|
|
defined(BUILD_TLS_AES_256_GCM_SHA384)
|
|
/* Called when writing. */
|
|
static int CsSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
(void)ssl;
|
|
(void)buf;
|
|
(void)sz;
|
|
(void)ctx;
|
|
|
|
/* Force error return from wolfSSL_accept_TLSv13(). */
|
|
return WANT_WRITE;
|
|
}
|
|
/* Called when reading. */
|
|
static int CsRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
|
|
int len = (int)msg->length;
|
|
|
|
(void)ssl;
|
|
(void)sz;
|
|
|
|
/* Pass back as much of message as will fit in buffer. */
|
|
if (len > sz)
|
|
len = sz;
|
|
XMEMCPY(buf, msg->buffer, len);
|
|
/* Move over returned data. */
|
|
msg->buffer += len;
|
|
msg->length -= len;
|
|
|
|
/* Amount actually copied. */
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_cipher_suites(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
|
|
!defined(NO_WOLFSSL_SERVER) && defined(HAVE_ECC) && \
|
|
defined(BUILD_TLS_AES_128_GCM_SHA256) && \
|
|
defined(BUILD_TLS_AES_256_GCM_SHA384)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL *ssl = NULL;
|
|
int i;
|
|
byte clientHello[] = {
|
|
0x16, 0x03, 0x03, 0x01, 0x9b, 0x01, 0x00, 0x01,
|
|
0x97, 0x03, 0x03, 0xf4, 0x65, 0xbd, 0x22, 0xfe,
|
|
0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55,
|
|
0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8,
|
|
0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c,
|
|
0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b,
|
|
0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda,
|
|
0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
|
/* Cipher suites: 0x13, 0x01 = TLS13-AES128-GCM-SHA256, twice. */
|
|
0x13, 0x01,
|
|
0x13, 0x01, 0x01, 0x00, 0x01, 0x4a, 0x00, 0x2d,
|
|
0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x33, 0x00,
|
|
0x47, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04,
|
|
0x90, 0xfc, 0xe2, 0x97, 0x05, 0x7c, 0xb5, 0x23,
|
|
0x5d, 0x5f, 0x5b, 0xcd, 0x0c, 0x1e, 0xe0, 0xe9,
|
|
0xab, 0x38, 0x6b, 0x1e, 0x20, 0x5c, 0x1c, 0x90,
|
|
0x2a, 0x9e, 0x68, 0x8e, 0x70, 0x05, 0x10, 0xa8,
|
|
0x02, 0x1b, 0xf9, 0x5c, 0xef, 0xc9, 0xaf, 0xca,
|
|
0x1a, 0x3b, 0x16, 0x8b, 0xe4, 0x1b, 0x3c, 0x15,
|
|
0xb8, 0x0d, 0xbd, 0xaf, 0x62, 0x8d, 0xa7, 0x13,
|
|
0xa0, 0x7c, 0xe0, 0x59, 0x0c, 0x4f, 0x8a, 0x6d,
|
|
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00,
|
|
0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05,
|
|
0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08,
|
|
0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08,
|
|
0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03,
|
|
0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x04, 0x00,
|
|
0x02, 0x00, 0x17, 0x00, 0x16, 0x00, 0x00, 0x00,
|
|
0x23, 0x00, 0x00, 0x00, 0x29, 0x00, 0xb9, 0x00,
|
|
0x94, 0x00, 0x8e, 0x0f, 0x12, 0xfa, 0x84, 0x1f,
|
|
0x76, 0x94, 0xd7, 0x09, 0x5e, 0xad, 0x08, 0x51,
|
|
0xb6, 0x80, 0x28, 0x31, 0x8b, 0xfd, 0xc6, 0xbd,
|
|
0x9e, 0xf5, 0x3b, 0x4d, 0x02, 0xbe, 0x1d, 0x73,
|
|
0xea, 0x13, 0x68, 0x00, 0x4c, 0xfd, 0x3d, 0x48,
|
|
0x51, 0xf9, 0x06, 0xbb, 0x92, 0xed, 0x42, 0x9f,
|
|
0x7f, 0x2c, 0x73, 0x9f, 0xd9, 0xb4, 0xef, 0x05,
|
|
0x26, 0x5b, 0x60, 0x5c, 0x0a, 0xfc, 0xa3, 0xbd,
|
|
0x2d, 0x2d, 0x8b, 0xf9, 0xaa, 0x5c, 0x96, 0x3a,
|
|
0xf2, 0xec, 0xfa, 0xe5, 0x57, 0x2e, 0x87, 0xbe,
|
|
0x27, 0xc5, 0x3d, 0x4f, 0x5d, 0xdd, 0xde, 0x1c,
|
|
0x1b, 0xb3, 0xcc, 0x27, 0x27, 0x57, 0x5a, 0xd9,
|
|
0xea, 0x99, 0x27, 0x23, 0xa6, 0x0e, 0xea, 0x9c,
|
|
0x0d, 0x85, 0xcb, 0x72, 0xeb, 0xd7, 0x93, 0xe3,
|
|
0xfe, 0xf7, 0x5c, 0xc5, 0x5b, 0x75, 0x8c, 0x47,
|
|
0x0a, 0x0e, 0xc4, 0x1a, 0xda, 0xef, 0x75, 0xe5,
|
|
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0xfb, 0x92, 0xce, 0xaa, 0x00, 0x21, 0x20,
|
|
0xcb, 0x73, 0x25, 0x80, 0x46, 0x78, 0x4f, 0xe5,
|
|
0x34, 0xf6, 0x91, 0x13, 0x7f, 0xc8, 0x8d, 0xdc,
|
|
0x81, 0x04, 0xb7, 0x0d, 0x49, 0x85, 0x2e, 0x12,
|
|
0x7a, 0x07, 0x23, 0xe9, 0x13, 0xa4, 0x6d, 0x8c
|
|
};
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
/* Offset into ClientHello message data of first cipher suite. */
|
|
const int csOff = 78;
|
|
/* Server cipher list. */
|
|
const char* serverCs = "TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256";
|
|
/* Suite list with duplicates. */
|
|
const char* dupCs = "TLS13-AES128-GCM-SHA256:"
|
|
"TLS13-AES128-GCM-SHA256:"
|
|
"TLS13-AES256-GCM-SHA384:"
|
|
"TLS13-AES256-GCM-SHA384:"
|
|
"TLS13-AES128-GCM-SHA256";
|
|
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES)
|
|
const byte dupCsBytes[] = { TLS13_BYTE, TLS_AES_256_GCM_SHA384,
|
|
TLS13_BYTE, TLS_AES_256_GCM_SHA384,
|
|
TLS13_BYTE, TLS_AES_128_GCM_SHA256,
|
|
TLS13_BYTE, TLS_AES_128_GCM_SHA256,
|
|
TLS13_BYTE, TLS_AES_256_GCM_SHA384 };
|
|
#endif
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile,
|
|
CERT_FILETYPE));
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, CsRecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, CsSend);
|
|
|
|
/* Test cipher suite list with many copies of a cipher suite. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientHello;
|
|
msg.length = (unsigned int)sizeof(clientHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
/* Force server to have as many occurrences of same cipher suite as
|
|
* possible. */
|
|
if (ssl != NULL) {
|
|
Suites* suites = (Suites*)WOLFSSL_SUITES(ssl);
|
|
suites->suiteSz = WOLFSSL_MAX_SUITE_SZ;
|
|
for (i = 0; i < suites->suiteSz; i += 2) {
|
|
suites->suites[i + 0] = TLS13_BYTE;
|
|
suites->suites[i + 1] = TLS_AES_128_GCM_SHA256;
|
|
}
|
|
}
|
|
/* Test multiple occurrences of same cipher suite. */
|
|
ExpectIntEQ(wolfSSL_accept_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* Set client order opposite to server order:
|
|
* TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384 */
|
|
clientHello[csOff + 0] = TLS13_BYTE;
|
|
clientHello[csOff + 1] = TLS_AES_128_GCM_SHA256;
|
|
clientHello[csOff + 2] = TLS13_BYTE;
|
|
clientHello[csOff + 3] = TLS_AES_256_GCM_SHA384;
|
|
|
|
/* Test server order negotiation. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientHello;
|
|
msg.length = (unsigned int)sizeof(clientHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
/* Server order: TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256 */
|
|
ExpectIntEQ(wolfSSL_set_cipher_list(ssl, serverCs), WOLFSSL_SUCCESS);
|
|
/* Negotiate cipher suites in server order: TLS13-AES256-GCM-SHA384 */
|
|
ExpectIntEQ(wolfSSL_accept_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
/* Check refined order - server order. */
|
|
ExpectIntEQ(ssl->suites->suiteSz, 4);
|
|
ExpectIntEQ(ssl->suites->suites[0], TLS13_BYTE);
|
|
ExpectIntEQ(ssl->suites->suites[1], TLS_AES_256_GCM_SHA384);
|
|
ExpectIntEQ(ssl->suites->suites[2], TLS13_BYTE);
|
|
ExpectIntEQ(ssl->suites->suites[3], TLS_AES_128_GCM_SHA256);
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* Test client order negotiation. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientHello;
|
|
msg.length = (unsigned int)sizeof(clientHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
/* Server order: TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256 */
|
|
ExpectIntEQ(wolfSSL_set_cipher_list(ssl, serverCs), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_UseClientSuites(ssl), 0);
|
|
/* Negotiate cipher suites in client order: TLS13-AES128-GCM-SHA256 */
|
|
ExpectIntEQ(wolfSSL_accept_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
/* Check refined order - client order. */
|
|
ExpectIntEQ(ssl->suites->suiteSz, 4);
|
|
ExpectIntEQ(ssl->suites->suites[0], TLS13_BYTE);
|
|
ExpectIntEQ(ssl->suites->suites[1], TLS_AES_128_GCM_SHA256);
|
|
ExpectIntEQ(ssl->suites->suites[2], TLS13_BYTE);
|
|
ExpectIntEQ(ssl->suites->suites[3], TLS_AES_256_GCM_SHA384);
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
|
|
/* Check duplicate detection is working. */
|
|
ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx, dupCs), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(ctx->suites->suiteSz, 4);
|
|
ExpectIntEQ(ctx->suites->suites[0], TLS13_BYTE);
|
|
ExpectIntEQ(ctx->suites->suites[1], TLS_AES_128_GCM_SHA256);
|
|
ExpectIntEQ(ctx->suites->suites[2], TLS13_BYTE);
|
|
ExpectIntEQ(ctx->suites->suites[3], TLS_AES_256_GCM_SHA384);
|
|
|
|
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES)
|
|
ExpectIntEQ(wolfSSL_CTX_set_cipher_list_bytes(ctx, dupCsBytes,
|
|
sizeof(dupCsBytes)), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(ctx->suites->suiteSz, 4);
|
|
ExpectIntEQ(ctx->suites->suites[0], TLS13_BYTE);
|
|
ExpectIntEQ(ctx->suites->suites[1], TLS_AES_256_GCM_SHA384);
|
|
ExpectIntEQ(ctx->suites->suites[2], TLS13_BYTE);
|
|
ExpectIntEQ(ctx->suites->suites[3], TLS_AES_128_GCM_SHA256);
|
|
#endif
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)\
|
|
&& !defined(NO_PSK)
|
|
static unsigned int test_tls13_bad_psk_binder_client_cb(WOLFSSL* ssl,
|
|
const char* hint, char* identity, unsigned int id_max_len,
|
|
unsigned char* key, unsigned int key_max_len)
|
|
{
|
|
(void)ssl;
|
|
(void)hint;
|
|
(void)key_max_len;
|
|
|
|
/* see internal.h MAX_PSK_ID_LEN for PSK identity limit */
|
|
XSTRNCPY(identity, "Client_identity", id_max_len);
|
|
|
|
key[0] = 0x20;
|
|
return 1;
|
|
}
|
|
|
|
static unsigned int test_tls13_bad_psk_binder_server_cb(WOLFSSL* ssl,
|
|
const char* id, unsigned char* key, unsigned int key_max_len)
|
|
{
|
|
(void)ssl;
|
|
(void)id;
|
|
(void)key_max_len;
|
|
/* zero means error */
|
|
key[0] = 0x10;
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_bad_psk_binder(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)\
|
|
&& !defined(NO_PSK)
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL_CTX *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
WOLFSSL *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_ALERT_HISTORY h;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_bad_psk_binder_client_cb);
|
|
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_bad_psk_binder_server_cb);
|
|
|
|
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
|
|
WOLFSSL_ERROR_WANT_READ);
|
|
|
|
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ( wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
|
|
WC_NO_ERR_TRACE(BAD_BINDER));
|
|
|
|
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)),
|
|
WC_NO_ERR_TRACE(FATAL_ERROR));
|
|
ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(h.last_rx.code, illegal_parameter);
|
|
ExpectIntEQ(h.last_rx.level, alert_fatal);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
#if defined(HAVE_RPK) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
!defined(NO_WOLFSSL_SERVER)
|
|
|
|
#define svrRpkCertFile "./certs/rpk/server-cert-rpk.der"
|
|
#define clntRpkCertFile "./certs/rpk/client-cert-rpk.der"
|
|
|
|
#if defined(WOLFSSL_ALWAYS_VERIFY_CB) && defined(WOLFSSL_TLS13)
|
|
static int MyRpkVerifyCb(int mode, WOLFSSL_X509_STORE_CTX* strctx)
|
|
{
|
|
int ret = WOLFSSL_SUCCESS;
|
|
(void)mode;
|
|
(void)strctx;
|
|
WOLFSSL_ENTER("MyRpkVerifyCb");
|
|
return ret;
|
|
}
|
|
#endif /* WOLFSSL_ALWAYS_VERIFY_CB && WOLFSSL_TLS13 */
|
|
|
|
static WC_INLINE int test_rpk_memio_setup(
|
|
struct test_memio_ctx *ctx,
|
|
WOLFSSL_CTX **ctx_c,
|
|
WOLFSSL_CTX **ctx_s,
|
|
WOLFSSL **ssl_c,
|
|
WOLFSSL **ssl_s,
|
|
method_provider method_c,
|
|
method_provider method_s,
|
|
const char* certfile_c, int fmt_cc, /* client cert file path and format */
|
|
const char* certfile_s, int fmt_cs, /* server cert file path and format */
|
|
const char* pkey_c, int fmt_kc, /* client private key and format */
|
|
const char* pkey_s, int fmt_ks /* server private key and format */
|
|
)
|
|
{
|
|
int ret;
|
|
if (ctx_c != NULL && *ctx_c == NULL) {
|
|
*ctx_c = wolfSSL_CTX_new(method_c());
|
|
if (*ctx_c == NULL) {
|
|
return -1;
|
|
}
|
|
wolfSSL_CTX_set_verify(*ctx_c, WOLFSSL_VERIFY_PEER, NULL);
|
|
|
|
ret = wolfSSL_CTX_load_verify_locations(*ctx_c, caCertFile, 0);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
wolfSSL_SetIORecv(*ctx_c, test_memio_read_cb);
|
|
wolfSSL_SetIOSend(*ctx_c, test_memio_write_cb);
|
|
|
|
ret = wolfSSL_CTX_use_certificate_file(*ctx_c, certfile_c, fmt_cc);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_c, pkey_c, fmt_kc);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (ctx_s != NULL && *ctx_s == NULL) {
|
|
*ctx_s = wolfSSL_CTX_new(method_s());
|
|
if (*ctx_s == NULL) {
|
|
return -1;
|
|
}
|
|
wolfSSL_CTX_set_verify(*ctx_s, WOLFSSL_VERIFY_PEER, NULL);
|
|
|
|
ret = wolfSSL_CTX_load_verify_locations(*ctx_s, cliCertFile, 0);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
|
|
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_s, pkey_s, fmt_ks);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
ret = wolfSSL_CTX_use_certificate_file(*ctx_s, certfile_s, fmt_cs);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
wolfSSL_SetIORecv(*ctx_s, test_memio_read_cb);
|
|
wolfSSL_SetIOSend(*ctx_s, test_memio_write_cb);
|
|
if (ctx->s_ciphers != NULL) {
|
|
ret = wolfSSL_CTX_set_cipher_list(*ctx_s, ctx->s_ciphers);
|
|
if (ret != WOLFSSL_SUCCESS) {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ctx_c != NULL && ssl_c != NULL) {
|
|
*ssl_c = wolfSSL_new(*ctx_c);
|
|
if (*ssl_c == NULL) {
|
|
return -1;
|
|
}
|
|
wolfSSL_SetIOWriteCtx(*ssl_c, ctx);
|
|
wolfSSL_SetIOReadCtx(*ssl_c, ctx);
|
|
}
|
|
if (ctx_s != NULL && ssl_s != NULL) {
|
|
*ssl_s = wolfSSL_new(*ctx_s);
|
|
if (*ssl_s == NULL) {
|
|
return -1;
|
|
}
|
|
wolfSSL_SetIOWriteCtx(*ssl_s, ctx);
|
|
wolfSSL_SetIOReadCtx(*ssl_s, ctx);
|
|
#if !defined(NO_DH)
|
|
SetDH(*ssl_s);
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* HAVE_RPK && !NO_TLS && !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */
|
|
|
|
|
|
int test_tls13_rpk_handshake(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_RPK) && \
|
|
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
|
#ifdef WOLFSSL_TLS13
|
|
int ret = 0;
|
|
#endif
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
int err;
|
|
char certType_c[MAX_CLIENT_CERT_TYPE_CNT];
|
|
char certType_s[MAX_CLIENT_CERT_TYPE_CNT];
|
|
int typeCnt_c;
|
|
int typeCnt_s;
|
|
int tp = 0;
|
|
#if defined(WOLFSSL_ALWAYS_VERIFY_CB) && defined(WOLFSSL_TLS13)
|
|
int isServer;
|
|
#endif
|
|
|
|
(void)err;
|
|
(void)typeCnt_c;
|
|
(void)typeCnt_s;
|
|
(void)certType_c;
|
|
(void)certType_s;
|
|
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
/* TLS1.2
|
|
* Both client and server load x509 cert and start handshaking.
|
|
* Check no negotiation occurred.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method,
|
|
cliCertFile, CERT_FILETYPE,
|
|
svrCertFile, CERT_FILETYPE,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE)
|
|
, 0);
|
|
|
|
|
|
/* set client certificate type in client end */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
/* both client and server do not call client/server_cert_type APIs,
|
|
* expecting default settings works and no negotiation performed.
|
|
*/
|
|
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
/* confirm no negotiation occurred */
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ((int)tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
(void)typeCnt_c;
|
|
(void)typeCnt_s;
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_TLS13
|
|
/* Both client and server load x509 cert and start handshaking.
|
|
* Check no negotiation occurred.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
cliCertFile, CERT_FILETYPE,
|
|
svrCertFile, CERT_FILETYPE,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* set client certificate type in client end */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
/* both client and server do not call client/server_cert_type APIs,
|
|
* expecting default settings works and no negotiation performed.
|
|
*/
|
|
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
/* confirm no negotiation occurred */
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ((int)tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
(void)typeCnt_c;
|
|
(void)typeCnt_s;
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
|
|
|
|
/* Both client and server load RPK cert and start handshaking.
|
|
* Confirm negotiated cert types match as expected.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
clntRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
svrRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* set client certificate type in client end */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in client end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set client certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
#endif
|
|
|
|
|
|
#ifndef WOLFSSL_NO_TLS12
|
|
/* TLS1.2
|
|
* Both client and server load RPK cert and start handshaking.
|
|
* Confirm negotiated cert types match as expected.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method,
|
|
clntRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
svrRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* set client certificate type in client end */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in client end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set client certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
if (test_memio_do_handshake(ssl_c, ssl_s, 10, NULL) != 0)
|
|
return TEST_FAIL;
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
#endif
|
|
|
|
|
|
#ifdef WOLFSSL_TLS13
|
|
/* Both client and server load x509 cert.
|
|
* Have client call set_client_cert_type with both RPK and x509.
|
|
* This doesn't makes client add client cert type extension to ClientHello,
|
|
* since it does not load RPK cert actually.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
cliCertFile, CERT_FILETYPE,
|
|
svrCertFile, CERT_FILETYPE,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* set client certificate type in client end
|
|
*
|
|
* client indicates both RPK and x509 certs are available but loaded RPK
|
|
* cert only. It does not have client add client-cert-type extension in CH.
|
|
*/
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* client indicates both RPK and x509 certs are acceptable */
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* server indicates both RPK and x509 certs are acceptable */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* server should indicate only RPK cert is available */
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = -1;
|
|
typeCnt_s = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
if (test_memio_do_handshake(ssl_c, ssl_s, 10, NULL) != 0)
|
|
return TEST_FAIL;
|
|
|
|
/* Negotiation for client-cert-type should NOT happen. Therefore -1 should
|
|
* be returned as cert type.
|
|
*/
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
|
|
|
|
/* Have client load RPK cert and have server load x509 cert.
|
|
* Check the negotiation result from both ends.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
clntRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
svrCertFile, CERT_FILETYPE,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* have client tell to use RPK cert */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = -1;
|
|
typeCnt_c = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have client tell to accept both RPK and x509 cert */
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have server accept to both RPK and x509 cert */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_c = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* does not call wolfSSL_set_server_cert_type intentionally in sesrver
|
|
* end, expecting the default setting works.
|
|
*/
|
|
|
|
|
|
if (test_memio_do_handshake(ssl_c, ssl_s, 10, NULL) != 0)
|
|
return TEST_FAIL;
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
|
|
|
|
/* Have both client and server load RPK cert, however, have server
|
|
* indicate its cert type x509.
|
|
* Client is expected to detect the cert type mismatch then to send alert
|
|
* with "unsupported_certificate".
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
clntRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
svrRpkCertFile, WOLFSSL_FILETYPE_ASN1, /* server sends RPK cert */
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* have client tell to use RPK cert */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = -1;
|
|
typeCnt_c = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have client tell to accept both RPK and x509 cert */
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have server accept to both RPK and x509 cert */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_c = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have server tell to use x509 cert intentionally. This will bring
|
|
* certificate type mismatch in client side.
|
|
*/
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = -1;
|
|
typeCnt_s = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* expect client detect cert type mismatch then send Alert */
|
|
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
|
|
if (ret != -1)
|
|
return TEST_FAIL;
|
|
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, ret),
|
|
WC_NO_ERR_TRACE(UNSUPPORTED_CERTIFICATE));
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
|
|
|
|
/* Have client load x509 cert and server load RPK cert,
|
|
* however, have client indicate its cert type RPK.
|
|
* Server is expected to detect the cert type mismatch then to send alert
|
|
* with "unsupported_certificate".
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
cliCertFile, CERT_FILETYPE,
|
|
svrRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* have client tell to use RPK cert intentionally */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = -1;
|
|
typeCnt_c = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have client tell to accept both RPK and x509 cert */
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have server accept to both RPK and x509 cert */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_RPK;
|
|
typeCnt_c = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* have server tell to use x509 cert intentionally. This will bring
|
|
* certificate type mismatch in client side.
|
|
*/
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_X509;
|
|
certType_s[1] = -1;
|
|
typeCnt_s = 1;
|
|
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
|
|
|
|
/* expect server detect cert type mismatch then send Alert */
|
|
ExpectIntNE(ret, 0);
|
|
err = wolfSSL_get_error(ssl_c, ret);
|
|
ExpectIntEQ(err, WC_NO_ERR_TRACE(UNSUPPORTED_CERTIFICATE));
|
|
|
|
/* client did not load RPK cert actually, so negotiation did not happen */
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
/* client did not load RPK cert actually, so negotiation did not happen */
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_X509);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
|
|
|
|
#if defined(WOLFSSL_ALWAYS_VERIFY_CB)
|
|
/* Both client and server load RPK cert and set certificate verify
|
|
* callbacks then start handshaking.
|
|
* Confirm both side can refer the peer's cert.
|
|
*/
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
|
|
ExpectIntEQ(
|
|
test_rpk_memio_setup(
|
|
&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
clntRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
svrRpkCertFile, WOLFSSL_FILETYPE_ASN1,
|
|
cliKeyFile, CERT_FILETYPE,
|
|
svrKeyFile, CERT_FILETYPE )
|
|
, 0);
|
|
|
|
/* set client certificate type in client end */
|
|
certType_c[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_c[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_c = 2;
|
|
|
|
certType_s[0] = WOLFSSL_CERT_TYPE_RPK;
|
|
certType_s[1] = WOLFSSL_CERT_TYPE_X509;
|
|
typeCnt_s = 2;
|
|
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_c, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in client end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_c, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set client certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_client_cert_type(ssl_s, certType_c, typeCnt_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set server certificate type in server end */
|
|
ExpectIntEQ(wolfSSL_set_server_cert_type(ssl_s, certType_s, typeCnt_s),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
/* set certificate verify callback to both client and server */
|
|
isServer = 0;
|
|
wolfSSL_SetCertCbCtx(ssl_c, &isServer);
|
|
wolfSSL_set_verify(ssl_c, SSL_VERIFY_PEER, MyRpkVerifyCb);
|
|
|
|
isServer = 1;
|
|
wolfSSL_SetCertCbCtx(ssl_c, &isServer);
|
|
wolfSSL_set_verify(ssl_s, SSL_VERIFY_PEER, MyRpkVerifyCb);
|
|
|
|
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
|
|
if (ret != 0)
|
|
return TEST_FAIL;
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_s, &tp),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_RPK);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
ssl_c = ssl_s = NULL;
|
|
ctx_c = ctx_s = NULL;
|
|
#endif /* WOLFSSL_ALWAYS_VERIFY_CB */
|
|
#endif /* WOLFSSL_TLS13 */
|
|
|
|
#endif /* HAVE_RPK && (!WOLFSSL_NO_TLS12 || WOLFSSL_TLS13) */
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
|
|
defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
(!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \
|
|
(defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \
|
|
(defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768)))
|
|
static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx)
|
|
{
|
|
#ifdef WOLFSSL_MLKEM_KYBER
|
|
#if !defined(WOLFSSL_NO_KYBER1024)
|
|
int group = WOLFSSL_KYBER_LEVEL5;
|
|
#elif !defined(WOLFSSL_NO_KYBER768)
|
|
int group = WOLFSSL_KYBER_LEVEL3;
|
|
#else
|
|
int group = WOLFSSL_KYBER_LEVEL1;
|
|
#endif
|
|
#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
#if !defined(WOLFSSL_NO_ML_KEM_1024)
|
|
int group = WOLFSSL_ML_KEM_1024;
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768)
|
|
int group = WOLFSSL_ML_KEM_768;
|
|
#else
|
|
int group = WOLFSSL_ML_KEM_512;
|
|
#endif
|
|
#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) && \
|
|
defined(WOLFSSL_PQC_HYBRIDS)
|
|
int group = WOLFSSL_SECP256R1MLKEM768;
|
|
#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) && \
|
|
defined(WOLFSSL_PQC_HYBRIDS)
|
|
int group = WOLFSSL_X25519MLKEM768;
|
|
#endif
|
|
|
|
AssertIntEQ(wolfSSL_CTX_set_groups(ctx, &group, 1), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
static void test_tls13_pq_groups_on_result(WOLFSSL* ssl)
|
|
{
|
|
#ifdef WOLFSSL_MLKEM_KYBER
|
|
#if !defined(WOLFSSL_NO_KYBER1024)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL5");
|
|
#elif !defined(WOLFSSL_NO_KYBER768)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL3");
|
|
#else
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL1");
|
|
#endif
|
|
#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
|
|
#if !defined(WOLFSSL_NO_ML_KEM_1024)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_1024");
|
|
#elif !defined(WOLFSSL_NO_ML_KEM_768)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_768");
|
|
#else
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_512");
|
|
#endif
|
|
#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) && \
|
|
defined(WOLFSSL_PQC_HYBRIDS)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "SecP256r1MLKEM768");
|
|
#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) && \
|
|
defined(WOLFSSL_PQC_HYBRIDS)
|
|
AssertStrEQ(wolfSSL_get_curve_name(ssl), "X25519MLKEM768");
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_pq_groups(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
|
|
defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
|
|
(!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \
|
|
(defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \
|
|
(defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768)))
|
|
callback_functions func_cb_client;
|
|
callback_functions func_cb_server;
|
|
|
|
XMEMSET(&func_cb_client, 0, sizeof(callback_functions));
|
|
XMEMSET(&func_cb_server, 0, sizeof(callback_functions));
|
|
|
|
func_cb_client.method = wolfTLSv1_3_client_method;
|
|
func_cb_server.method = wolfTLSv1_3_server_method;
|
|
func_cb_client.ctx_ready = test_tls13_pq_groups_ctx_ready;
|
|
func_cb_client.on_result = test_tls13_pq_groups_on_result;
|
|
func_cb_server.on_result = test_tls13_pq_groups_on_result;
|
|
|
|
test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server);
|
|
|
|
ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS);
|
|
ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET)
|
|
static int test_tls13_read_until_write_ok(WOLFSSL* ssl, void* buf, int bufLen)
|
|
{
|
|
int ret, err;
|
|
int tries = 5;
|
|
|
|
err = 0;
|
|
do {
|
|
ret = wolfSSL_read(ssl, buf, bufLen);
|
|
if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
}
|
|
} while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) &&
|
|
err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE));
|
|
return ret;
|
|
}
|
|
static int test_tls13_connect_until_write_ok(WOLFSSL* ssl)
|
|
{
|
|
int ret, err;
|
|
int tries = 5;
|
|
|
|
err = 0;
|
|
do {
|
|
ret = wolfSSL_connect(ssl);
|
|
if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
}
|
|
} while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) &&
|
|
err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE));
|
|
return ret;
|
|
}
|
|
static int test_tls13_write_until_write_ok(WOLFSSL* ssl, const void* msg,
|
|
int msgLen)
|
|
{
|
|
int ret, err;
|
|
int tries = 5;
|
|
|
|
err = 0;
|
|
do {
|
|
ret = wolfSSL_write(ssl, msg, msgLen);
|
|
if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
}
|
|
} while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) &&
|
|
err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE));
|
|
return ret;
|
|
}
|
|
static int test_tls13_early_data_read_until_write_ok(WOLFSSL* ssl, void* buf,
|
|
int bufLen, int* read)
|
|
{
|
|
int ret, err;
|
|
int tries = 5;
|
|
|
|
err = 0;
|
|
do {
|
|
ret = wolfSSL_read_early_data(ssl, buf, bufLen, read);
|
|
if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
}
|
|
} while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) &&
|
|
err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE));
|
|
return ret;
|
|
}
|
|
static int test_tls13_early_data_write_until_write_ok(WOLFSSL* ssl,
|
|
const void* msg, int msgLen, int* written)
|
|
{
|
|
int ret, err;
|
|
int tries = 5;
|
|
|
|
err = 0;
|
|
do {
|
|
ret = wolfSSL_write_early_data(ssl, msg, msgLen, written);
|
|
if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
|
|
err = wolfSSL_get_error(ssl, ret);
|
|
}
|
|
} while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) &&
|
|
err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE));
|
|
return ret;
|
|
}
|
|
struct test_tls13_wwrite_ctx {
|
|
int want_write;
|
|
struct test_memio_ctx *test_ctx;
|
|
};
|
|
static int test_tls13_mock_wantwrite_cb(WOLFSSL* ssl, char* data, int sz,
|
|
void* ctx)
|
|
{
|
|
struct test_tls13_wwrite_ctx *wwctx = (struct test_tls13_wwrite_ctx *)ctx;
|
|
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
|
|
/* Write ChangeCipherSpec message. */
|
|
if (data[0] != 0x14)
|
|
#endif
|
|
{
|
|
wwctx->want_write = !wwctx->want_write;
|
|
if (wwctx->want_write) {
|
|
return WOLFSSL_CBIO_ERR_WANT_WRITE;
|
|
}
|
|
}
|
|
return test_memio_write_cb(ssl, data, sz, wwctx->test_ctx);
|
|
}
|
|
#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES && WOLFSSL_EARLY_DATA */
|
|
int test_tls13_early_data(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET)
|
|
int written = 0;
|
|
int read = 0;
|
|
size_t i;
|
|
char msg[] = "This is early data";
|
|
char msg2[] = "This is client data";
|
|
char msg3[] = "This is server data";
|
|
char msg4[] = "This is server immediate data";
|
|
char msgBuf[50];
|
|
struct {
|
|
method_provider client_meth;
|
|
method_provider server_meth;
|
|
const char* tls_version;
|
|
int isUdp;
|
|
int splitEarlyData;
|
|
int everyWriteWantWrite;
|
|
} params[] = {
|
|
#ifdef WOLFSSL_TLS13
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
"TLS 1.3", 0, 0, 0 },
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
"TLS 1.3", 0, 1, 0 },
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
"TLS 1.3", 0, 0, 1 },
|
|
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
|
|
"TLS 1.3", 0, 1, 1 },
|
|
#endif
|
|
#ifdef WOLFSSL_DTLS13
|
|
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
|
|
"DTLS 1.3", 1, 0, 0 },
|
|
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
|
|
"DTLS 1.3", 1, 1, 0 },
|
|
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
|
|
"DTLS 1.3", 1, 0, 1 },
|
|
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
|
|
"DTLS 1.3", 1, 1, 1 },
|
|
#endif
|
|
};
|
|
|
|
for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) {
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
WOLFSSL_SESSION *sess = NULL;
|
|
int splitEarlyData = params[i].splitEarlyData;
|
|
int everyWriteWantWrite = params[i].everyWriteWantWrite;
|
|
struct test_tls13_wwrite_ctx wwrite_ctx_s, wwrite_ctx_c;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
XMEMSET(&wwrite_ctx_c, 0, sizeof(wwrite_ctx_c));
|
|
XMEMSET(&wwrite_ctx_s, 0, sizeof(wwrite_ctx_s));
|
|
|
|
fprintf(stderr, "\tEarly data with %s%s%s\n", params[i].tls_version,
|
|
splitEarlyData ? " (split early data)" : "",
|
|
everyWriteWantWrite ? " (every write WANT_WRITE)" : "");
|
|
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c,
|
|
&ssl_s, params[i].client_meth, params[i].server_meth), 0);
|
|
|
|
if (params[i].isUdp) {
|
|
/* Early data is incompatible with HRR usage. Hence, we have to make
|
|
* sure a group is negotiated that does not cause a fragemented CH.
|
|
*/
|
|
int group[1] = {
|
|
#ifdef HAVE_ECC
|
|
WOLFSSL_ECC_SECP256R1,
|
|
#elif defined(HAVE_CURVE25519)
|
|
WOLFSSL_ECC_X25519,
|
|
#elif defined(HAVE_CURVE448)
|
|
WOLFSSL_ECC_X448,
|
|
#elif defined(HAVE_FFDHE_2048)
|
|
WOLFSSL_FFDHE_2048,
|
|
#endif
|
|
};
|
|
ExpectIntEQ(wolfSSL_set_groups(ssl_c, group, 1), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_groups(ssl_s, group, 1), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Get a ticket so that we can do 0-RTT on the next connection */
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
/* Make sure we read the ticket */
|
|
ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
ExpectNotNull(sess = wolfSSL_get1_session(ssl_c));
|
|
|
|
wolfSSL_free(ssl_c);
|
|
ssl_c = NULL;
|
|
wolfSSL_free(ssl_s);
|
|
ssl_s = NULL;
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c,
|
|
&ssl_s, params[i].client_meth, params[i].server_meth), 0);
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
|
|
#ifdef WOLFSSL_DTLS13
|
|
if (params[i].isUdp) {
|
|
wolfSSL_SetLoggingPrefix("server");
|
|
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
|
|
ExpectIntEQ(wolfSSL_dtls13_no_hrr_on_resume(ssl_s, 1),
|
|
WOLFSSL_SUCCESS);
|
|
#else
|
|
/* Let's test this but we generally don't recommend turning off
|
|
* the cookie exchange */
|
|
ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
if (everyWriteWantWrite) {
|
|
wwrite_ctx_c.test_ctx = &test_ctx;
|
|
wwrite_ctx_s.test_ctx = &test_ctx;
|
|
wolfSSL_SetIOWriteCtx(ssl_c, &wwrite_ctx_c);
|
|
wolfSSL_SSLSetIOSend(ssl_c, test_tls13_mock_wantwrite_cb);
|
|
wolfSSL_SetIOWriteCtx(ssl_s, &wwrite_ctx_s);
|
|
wolfSSL_SSLSetIOSend(ssl_s, test_tls13_mock_wantwrite_cb);
|
|
}
|
|
/* Test 0-RTT data */
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
|
|
ExpectIntEQ(test_tls13_early_data_write_until_write_ok(ssl_c, msg,
|
|
sizeof(msg), &written),
|
|
sizeof(msg));
|
|
ExpectIntEQ(written, sizeof(msg));
|
|
|
|
if (splitEarlyData) {
|
|
ExpectIntEQ(test_tls13_early_data_write_until_write_ok(ssl_c, msg,
|
|
sizeof(msg), &written),
|
|
sizeof(msg));
|
|
ExpectIntEQ(written, sizeof(msg));
|
|
}
|
|
|
|
/* Read first 0-RTT data (if split otherwise entire data) */
|
|
wolfSSL_SetLoggingPrefix("server");
|
|
ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf,
|
|
sizeof(msgBuf), &read),
|
|
sizeof(msg));
|
|
ExpectIntEQ(read, sizeof(msg));
|
|
ExpectStrEQ(msg, msgBuf);
|
|
|
|
/* Test 0.5-RTT data */
|
|
ExpectIntEQ(test_tls13_write_until_write_ok(ssl_s, msg4, sizeof(msg4)),
|
|
sizeof(msg4));
|
|
|
|
if (splitEarlyData) {
|
|
/* Read second 0-RTT data */
|
|
ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf,
|
|
sizeof(msgBuf), &read),
|
|
sizeof(msg));
|
|
ExpectIntEQ(read, sizeof(msg));
|
|
ExpectStrEQ(msg, msgBuf);
|
|
}
|
|
|
|
if (params[i].isUdp) {
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
|
|
WC_NO_ERR_TRACE(APP_DATA_READY));
|
|
|
|
/* Read server 0.5-RTT data */
|
|
ExpectIntEQ(
|
|
test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)),
|
|
sizeof(msg4));
|
|
ExpectStrEQ(msg4, msgBuf);
|
|
|
|
/* Complete handshake */
|
|
ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
|
|
WOLFSSL_ERROR_WANT_READ);
|
|
/* Use wolfSSL_is_init_finished to check if handshake is
|
|
* complete. Normally a user would loop until it is true but
|
|
* here we control both sides so we just assert the expected
|
|
* value. wolfSSL_read_early_data does not provide handshake
|
|
* status to us with non-blocking IO and we can't use
|
|
* wolfSSL_accept as TLS layer may return ZERO_RETURN due to
|
|
* early data parsing logic. */
|
|
wolfSSL_SetLoggingPrefix("server");
|
|
ExpectFalse(wolfSSL_is_init_finished(ssl_s));
|
|
ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf,
|
|
sizeof(msgBuf), &read),
|
|
0);
|
|
ExpectIntEQ(read, 0);
|
|
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
|
|
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
else {
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_SetLoggingPrefix("server");
|
|
ExpectFalse(wolfSSL_is_init_finished(ssl_s));
|
|
ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf,
|
|
sizeof(msgBuf), &read),
|
|
0);
|
|
ExpectIntEQ(read, 0);
|
|
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
|
|
|
|
/* Read server 0.5-RTT data */
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(
|
|
test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)),
|
|
sizeof(msg4));
|
|
ExpectStrEQ(msg4, msgBuf);
|
|
}
|
|
|
|
/* Test bi-directional write */
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(test_tls13_write_until_write_ok(ssl_c, msg2, sizeof(msg2)),
|
|
sizeof(msg2));
|
|
wolfSSL_SetLoggingPrefix("server");
|
|
ExpectIntEQ(
|
|
test_tls13_read_until_write_ok(ssl_s, msgBuf, sizeof(msgBuf)),
|
|
sizeof(msg2));
|
|
ExpectStrEQ(msg2, msgBuf);
|
|
ExpectIntEQ(test_tls13_write_until_write_ok(ssl_s, msg3, sizeof(msg3)),
|
|
sizeof(msg3));
|
|
wolfSSL_SetLoggingPrefix("client");
|
|
ExpectIntEQ(
|
|
test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)),
|
|
sizeof(msg3));
|
|
ExpectStrEQ(msg3, msgBuf);
|
|
|
|
wolfSSL_SetLoggingPrefix(NULL);
|
|
ExpectTrue(wolfSSL_session_reused(ssl_c));
|
|
ExpectTrue(wolfSSL_session_reused(ssl_s));
|
|
|
|
wolfSSL_SESSION_free(sess);
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
}
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_TLS13) && defined(WOLFSSL_EARLY_DATA) && \
|
|
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID) && \
|
|
!defined(NO_SESSION_CACHE) && defined(HAVE_EXT_CACHE)
|
|
/* Single-slot external session cache keyed by altSessionID, used by
|
|
* test_tls13_early_data_0rtt_replay to assert the 0-RTT anti-replay
|
|
* fix clears both caches. */
|
|
static struct {
|
|
byte id[ID_LEN];
|
|
byte has_entry;
|
|
WOLFSSL_SESSION* sess;
|
|
int new_calls;
|
|
int get_calls;
|
|
int rem_calls;
|
|
} test_tls13_0rtt_replay_cache;
|
|
|
|
static void test_tls13_0rtt_replay_cache_reset(void)
|
|
{
|
|
/* wolfSSL_SESSION_free is NULL-safe, so unconditionally drop any
|
|
* stored session without touching has_entry first. */
|
|
wolfSSL_SESSION_free(test_tls13_0rtt_replay_cache.sess);
|
|
XMEMSET(&test_tls13_0rtt_replay_cache, 0,
|
|
sizeof(test_tls13_0rtt_replay_cache));
|
|
}
|
|
|
|
/* Stateful-ticket sessions always have haveAltSessionID set, so key the
|
|
* cache on altSessionID directly (wolfSSL_SESSION_get_id is only
|
|
* declared under the OpenSSL compatibility layer). */
|
|
static int test_tls13_0rtt_replay_new_cb(WOLFSSL* ssl, WOLFSSL_SESSION* s)
|
|
{
|
|
(void)ssl;
|
|
test_tls13_0rtt_replay_cache.new_calls++;
|
|
if (s == NULL || !s->haveAltSessionID)
|
|
return 0;
|
|
wolfSSL_SESSION_free(test_tls13_0rtt_replay_cache.sess);
|
|
XMEMCPY(test_tls13_0rtt_replay_cache.id, s->altSessionID, ID_LEN);
|
|
test_tls13_0rtt_replay_cache.sess = s;
|
|
test_tls13_0rtt_replay_cache.has_entry = 1;
|
|
return 1; /* retain the reference; freed in the rem callback */
|
|
}
|
|
|
|
static WOLFSSL_SESSION* test_tls13_0rtt_replay_get_cb(WOLFSSL* ssl,
|
|
const byte* id, int idLen, int* ref)
|
|
{
|
|
(void)ssl;
|
|
test_tls13_0rtt_replay_cache.get_calls++;
|
|
*ref = 1; /* keep ownership; wolfSSL duplicates from us */
|
|
if (!test_tls13_0rtt_replay_cache.has_entry || idLen != ID_LEN)
|
|
return NULL;
|
|
if (XMEMCMP(test_tls13_0rtt_replay_cache.id, id, ID_LEN) != 0)
|
|
return NULL;
|
|
return test_tls13_0rtt_replay_cache.sess;
|
|
}
|
|
|
|
static void test_tls13_0rtt_replay_rem_cb(WOLFSSL_CTX* ctx,
|
|
WOLFSSL_SESSION* s)
|
|
{
|
|
const byte* id;
|
|
(void)ctx;
|
|
if (!test_tls13_0rtt_replay_cache.has_entry || s == NULL)
|
|
return;
|
|
/* Internal-cache-evicted sessions have haveAltSessionID cleared
|
|
* (that field sits before the DupSession copy offset), so fall
|
|
* back to sessionID when altSessionID is not set. Both carry the
|
|
* ID_LEN lookup key. */
|
|
if (s->haveAltSessionID)
|
|
id = s->altSessionID;
|
|
else if (s->sessionIDSz == ID_LEN)
|
|
id = s->sessionID;
|
|
else
|
|
return;
|
|
if (XMEMCMP(test_tls13_0rtt_replay_cache.id, id, ID_LEN) != 0)
|
|
return;
|
|
wolfSSL_SESSION_free(test_tls13_0rtt_replay_cache.sess);
|
|
test_tls13_0rtt_replay_cache.sess = NULL;
|
|
test_tls13_0rtt_replay_cache.has_entry = 0;
|
|
test_tls13_0rtt_replay_cache.rem_calls++;
|
|
}
|
|
|
|
/* RFC 8446 section 8 anti-replay: a 0-RTT-eligible session must be
|
|
* evicted from both the internal and external caches on resumption so
|
|
* the same ClientHello cannot replay early data. */
|
|
int test_tls13_early_data_0rtt_replay(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
WOLFSSL_SESSION *sess = NULL;
|
|
char buf[64];
|
|
int round;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
test_tls13_0rtt_replay_cache_reset();
|
|
|
|
/* Step 1: full handshake populates both caches. */
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method),
|
|
0);
|
|
/* Stateful tickets + 0-RTT enabled. */
|
|
ExpectTrue(wolfSSL_set_options(ssl_s, WOLFSSL_OP_NO_TICKET) != 0);
|
|
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_ERROR_CODE_OPENSSL)
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(ssl_s, 128), WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(ssl_s, 128), 0);
|
|
#endif
|
|
wolfSSL_CTX_sess_set_new_cb(ctx_s, test_tls13_0rtt_replay_new_cb);
|
|
wolfSSL_CTX_sess_set_get_cb(ctx_s, test_tls13_0rtt_replay_get_cb);
|
|
wolfSSL_CTX_sess_set_remove_cb(ctx_s, test_tls13_0rtt_replay_rem_cb);
|
|
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
/* Let the client consume NewSessionTicket. */
|
|
ExpectIntEQ(wolfSSL_read(ssl_c, buf, sizeof(buf)), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
ExpectNotNull(sess = wolfSSL_get1_session(ssl_c));
|
|
ExpectIntEQ(wolfSSL_SessionIsSetup(sess), 1);
|
|
/* Stateful (ID-only) ticket on the client side. */
|
|
ExpectIntEQ(sess->ticketLen, ID_LEN);
|
|
ExpectIntEQ((int)sess->maxEarlyDataSz, 128);
|
|
/* External cache saw the add. */
|
|
ExpectIntGT(test_tls13_0rtt_replay_cache.new_calls, 0);
|
|
ExpectIntEQ(test_tls13_0rtt_replay_cache.has_entry, 1);
|
|
|
|
wolfSSL_free(ssl_c); ssl_c = NULL;
|
|
wolfSSL_free(ssl_s); ssl_s = NULL;
|
|
|
|
/* Resume the same session twice, offering 0-RTT each time. */
|
|
for (round = 0; round < 2 && !EXPECT_FAIL(); round++) {
|
|
const char earlyMsg[] = "early-data-0rtt";
|
|
int written = 0;
|
|
int earlyRead = 0;
|
|
char earlyBuf[sizeof(earlyMsg)];
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
XMEMSET(earlyBuf, 0, sizeof(earlyBuf));
|
|
/* Reuse the CTXs so both caches survive (test_memio_setup
|
|
* leaves *ctx alone when non-NULL). */
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c,
|
|
&ssl_s, wolfTLSv1_3_client_method,
|
|
wolfTLSv1_3_server_method), 0);
|
|
ExpectTrue(wolfSSL_set_options(ssl_s, WOLFSSL_OP_NO_TICKET) != 0);
|
|
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_ERROR_CODE_OPENSSL)
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(ssl_s, 128),
|
|
WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_set_max_early_data(ssl_s, 128), 0);
|
|
#endif
|
|
ExpectIntEQ(wolfSSL_SessionIsSetup(sess), 1);
|
|
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
|
|
|
|
ExpectIntEQ(test_tls13_early_data_write_until_write_ok(ssl_c,
|
|
earlyMsg, (int)sizeof(earlyMsg), &written),
|
|
sizeof(earlyMsg));
|
|
ExpectIntEQ(written, sizeof(earlyMsg));
|
|
|
|
(void)test_tls13_early_data_read_until_write_ok(ssl_s, earlyBuf,
|
|
sizeof(earlyBuf), &earlyRead);
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
if (round == 0) {
|
|
ExpectTrue(wolfSSL_session_reused(ssl_s));
|
|
ExpectIntEQ(earlyRead, sizeof(earlyMsg));
|
|
ExpectStrEQ(earlyMsg, earlyBuf);
|
|
/* Fix fired exactly once to evict the cached entry. */
|
|
ExpectIntEQ(test_tls13_0rtt_replay_cache.rem_calls, 1);
|
|
}
|
|
else {
|
|
ExpectFalse(wolfSSL_session_reused(ssl_s));
|
|
ExpectIntEQ(earlyRead, 0);
|
|
/* No additional eviction in the replay round. */
|
|
ExpectIntEQ(test_tls13_0rtt_replay_cache.rem_calls, 1);
|
|
}
|
|
|
|
wolfSSL_free(ssl_c); ssl_c = NULL;
|
|
wolfSSL_free(ssl_s); ssl_s = NULL;
|
|
}
|
|
|
|
wolfSSL_SESSION_free(sess);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
test_tls13_0rtt_replay_cache_reset();
|
|
return EXPECT_RESULT();
|
|
}
|
|
#else
|
|
int test_tls13_early_data_0rtt_replay(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
return EXPECT_RESULT();
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Check that the client won't send the same CH after a HRR. An HRR without
|
|
* a KeyShare or a Cookie extension will trigger the error. */
|
|
int test_tls13_same_ch(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_TLS13) && defined(WOLFSSL_AES_128) && \
|
|
defined(HAVE_AESGCM) && !defined(NO_SHA256) && \
|
|
/* middlebox compat requires that the session ID is echoed */ \
|
|
!defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
/* Transport Layer Security
|
|
* TLSv1.3 Record Layer: Handshake Protocol: Hello Retry Request
|
|
* Content Type: Handshake (22)
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Length: 50
|
|
* Handshake Protocol: Hello Retry Request
|
|
* Handshake Type: Server Hello (2)
|
|
* Length: 46
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Random: cf21ad74e59a6111be1d8c021e65b891c2a211167abb8c5e079e09e2c8a8339c (HelloRetryRequest magic)
|
|
* Session ID Length: 0
|
|
* Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
|
|
* Compression Method: null (0)
|
|
* Extensions Length: 6
|
|
* Extension: supported_versions (len=2) TLS 1.3 */
|
|
unsigned char hrr[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x32, 0x02, 0x00, 0x00, 0x2e, 0x03, 0x03, 0xcf,
|
|
0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e,
|
|
0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07,
|
|
0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, 0x00, 0x13, 0x01, 0x00, 0x00,
|
|
0x06, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04
|
|
};
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
|
|
wolfTLSv1_3_client_method, NULL), 0);
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (char*)hrr,
|
|
sizeof(hrr)), 0);
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
/* issue 9653: use a more appropriate error than DUPLICATE_MSG_E.
|
|
* Since the cause of this is missing extension, return that. */
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), EXT_MISSING);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_tls13_hrr_different_cs(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_TLS13) && \
|
|
defined(BUILD_TLS_AES_256_GCM_SHA384) && \
|
|
defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) && \
|
|
defined(HAVE_ECC) && defined(HAVE_ECC384) && \
|
|
!defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
|
|
/*
|
|
* TLSv1.3 Record Layer: Handshake Protocol: Hello Retry Request
|
|
* Content Type: Handshake (22)
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Length: 56
|
|
* Handshake Protocol: Hello Retry Request
|
|
* Handshake Type: Server Hello (2)
|
|
* Length: 52
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Random: cf21ad74e59a6111be1d8c021e65b891c2a211167abb8c5e079e09e2c8a8339c (HelloRetryRequest magic)
|
|
* Session ID Length: 0
|
|
* Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
|
|
* Compression Method: null (0)
|
|
* Extensions Length: 12
|
|
* Extension: supported_versions (len=2) TLS 1.3
|
|
* Extension: key_share (len=2) secp384r1
|
|
*
|
|
*/
|
|
unsigned char hrr[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x38, 0x02, 0x00, 0x00, 0x34, 0x03, 0x03, 0xcf,
|
|
0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e,
|
|
0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07,
|
|
0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, 0x00, 0x13, 0x02, 0x00, 0x00,
|
|
0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00,
|
|
0x18
|
|
};
|
|
/*
|
|
* TLSv1.3 Record Layer: Handshake Protocol: Server Hello
|
|
* Content Type: Handshake (22)
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Length: 155
|
|
* Handshake Protocol: Server Hello
|
|
* Handshake Type: Server Hello (2)
|
|
* Length: 151
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Random: 0101010101010101010101010101010101010101010101010101010101010101
|
|
* Session ID Length: 0
|
|
* Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
|
|
* Compression Method: null (0)
|
|
* Extensions Length: 111
|
|
* Extension: key_share (len=101) secp384r1
|
|
* Extension: supported_versions (len=2) TLS 1.3
|
|
*
|
|
*/
|
|
unsigned char sh[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x97, 0x03, 0x03, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x13, 0x03, 0x00, 0x00,
|
|
0x6f, 0x00, 0x33, 0x00, 0x65, 0x00, 0x18, 0x00, 0x61, 0x04, 0x53, 0x3e,
|
|
0xe5, 0xbf, 0x40, 0xec, 0x2d, 0x67, 0x98, 0x8b, 0x77, 0xf3, 0x17, 0x48,
|
|
0x9b, 0xb6, 0xdf, 0x95, 0x29, 0x25, 0xc7, 0x09, 0xfc, 0x03, 0x81, 0x11,
|
|
0x1a, 0x59, 0x56, 0xf2, 0xd7, 0x58, 0x11, 0x0e, 0x59, 0xd3, 0xd7, 0xc1,
|
|
0x72, 0x9e, 0x2c, 0x0d, 0x70, 0xea, 0xf7, 0x73, 0xe6, 0x12, 0x01, 0x16,
|
|
0x42, 0x6d, 0xe2, 0x43, 0x6a, 0x2f, 0x5f, 0xdd, 0x7f, 0xe5, 0x4f, 0xaf,
|
|
0x95, 0x2b, 0x04, 0xfd, 0x13, 0xf5, 0x16, 0xce, 0x62, 0x7f, 0x89, 0xd2,
|
|
0x01, 0x9d, 0x4c, 0x87, 0x96, 0x95, 0x9e, 0x43, 0x33, 0xc7, 0x06, 0x5b,
|
|
0x49, 0x6c, 0xa6, 0x34, 0xd5, 0xdc, 0x63, 0xbd, 0xe9, 0x1f, 0x00, 0x2b,
|
|
0x00, 0x02, 0x03, 0x04
|
|
};
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
|
|
wolfTLSv1_3_client_method, NULL), 0);
|
|
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (char*)hrr,
|
|
sizeof(hrr)), 0);
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (char*)sh,
|
|
sizeof(sh)), 0);
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), INVALID_PARAMETER);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Server-side complement to test_tls13_hrr_different_cs: the client sends a
|
|
* different cipher suite in CH2 than what the server selected in the HRR. */
|
|
int test_tls13_ch2_different_cs(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) && \
|
|
defined(BUILD_TLS_AES_256_GCM_SHA384) && \
|
|
defined(BUILD_TLS_AES_128_GCM_SHA256) && \
|
|
defined(HAVE_ECC) && defined(HAVE_ECC384)
|
|
/*
|
|
* First ClientHello: cipher suite TLS_AES_256_GCM_SHA384 (0x1302),
|
|
* empty key_share, secp384r1 in supported_groups. This triggers the
|
|
* server to send a HelloRetryRequest selecting TLS_AES_256_GCM_SHA384
|
|
* and requesting a secp384r1 key share.
|
|
*/
|
|
/*
|
|
* TLSv1.3 Record Layer: Handshake Protocol: Client Hello
|
|
* Content Type: Handshake (22)
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Length: 110
|
|
* Handshake Protocol: Client Hello
|
|
* Handshake Type: Client Hello (1)
|
|
* Length: 106
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Random: 0101010101010101010101010101010101010101010101010101010101010101
|
|
* Session ID Length: 32
|
|
* Session ID: 0303030303030303030303030303030303030303030303030303030303030303
|
|
* Cipher Suites Length: 2
|
|
* Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
|
|
* Compression Methods Length: 1
|
|
* Compression Method: null (0)
|
|
* Extensions Length: 31
|
|
* Extension: supported_groups (len=4) secp384r1 (0x0018)
|
|
* Extension: signature_algorithms (len=6) rsa_pkcs1_sha256 (0x0401),
|
|
* rsa_pss_rsae_sha256 (0x0804)
|
|
* Extension: key_share (len=2) client_shares length=0 (empty)
|
|
* Extension: supported_versions (len=3) TLS 1.3 (0x0304)
|
|
*/
|
|
unsigned char ch1[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x6e, 0x01, 0x00, 0x00, 0x6a, 0x03, 0x03, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x02, 0x01, 0x00, 0x00, 0x1f,
|
|
0x00, 0x0a, 0x00, 0x04, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0d, 0x00, 0x06,
|
|
0x00, 0x04, 0x04, 0x01, 0x08, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00, 0x00,
|
|
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
|
|
};
|
|
/*
|
|
* TLSv1.3 Record Layer: Handshake Protocol: Client Hello
|
|
* Content Type: Handshake (22)
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Length: 211
|
|
* Handshake Protocol: Client Hello
|
|
* Handshake Type: Client Hello (1)
|
|
* Length: 207
|
|
* Version: TLS 1.2 (0x0303)
|
|
* Random: 0101010101010101010101010101010101010101010101010101010101010101
|
|
* Session ID Length: 32
|
|
* Session ID: 0303030303030303030303030303030303030303030303030303030303030303
|
|
* Cipher Suites Length: 2
|
|
* Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
|
|
* Compression Methods Length: 1
|
|
* Compression Method: null (0)
|
|
* Extensions Length: 132
|
|
* Extension: supported_groups (len=4) secp384r1 (0x0018)
|
|
* Extension: signature_algorithms (len=6) rsa_pkcs1_sha256 (0x0401),
|
|
* rsa_pss_rsae_sha256 (0x0804)
|
|
* Extension: key_share (len=103)
|
|
* client_shares length: 101
|
|
* KeyShareEntry: group secp384r1 (0x0018), key_exchange length: 97
|
|
* key_exchange: 04 || X(48) || Y(48) (uncompressed P-384 point)
|
|
* Extension: supported_versions (len=3) TLS 1.3 (0x0304)
|
|
*/
|
|
unsigned char ch2[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0xd3, 0x01, 0x00, 0x00, 0xcf, 0x03, 0x03, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x01, 0x01, 0x00, 0x00, 0x84,
|
|
0x00, 0x0a, 0x00, 0x04, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0d, 0x00, 0x06,
|
|
0x00, 0x04, 0x04, 0x01, 0x08, 0x04, 0x00, 0x33, 0x00, 0x67, 0x00, 0x65,
|
|
0x00, 0x18, 0x00, 0x61, 0x04, 0x53, 0x3e, 0xe5, 0xbf, 0x40, 0xec, 0x2d,
|
|
0x67, 0x98, 0x8b, 0x77, 0xf3, 0x17, 0x48, 0x9b, 0xb6, 0xdf, 0x95, 0x29,
|
|
0x25, 0xc7, 0x09, 0xfc, 0x03, 0x81, 0x11, 0x1a, 0x59, 0x56, 0xf2, 0xd7,
|
|
0x58, 0x11, 0x0e, 0x59, 0xd3, 0xd7, 0xc1, 0x72, 0x9e, 0x2c, 0x0d, 0x70,
|
|
0xea, 0xf7, 0x73, 0xe6, 0x12, 0x01, 0x16, 0x42, 0x6d, 0xe2, 0x43, 0x6a,
|
|
0x2f, 0x5f, 0xdd, 0x7f, 0xe5, 0x4f, 0xaf, 0x95, 0x2b, 0x04, 0xfd, 0x13,
|
|
0xf5, 0x16, 0xce, 0x62, 0x7f, 0x89, 0xd2, 0x01, 0x9d, 0x4c, 0x87, 0x96,
|
|
0x95, 0x9e, 0x43, 0x33, 0xc7, 0x06, 0x5b, 0x49, 0x6c, 0xa6, 0x34, 0xd5,
|
|
0xdc, 0x63, 0xbd, 0xe9, 0x1f, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
|
|
};
|
|
WOLFSSL_CTX *ctx_s = NULL;
|
|
WOLFSSL *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s,
|
|
NULL, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* Server reads CH1, sends HRR, then waits for CH2 */
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (char*)ch1,
|
|
sizeof(ch1)), 0);
|
|
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
|
|
|
|
/* Server must reject CH2 because the cipher suite changed from the HRR */
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (char*)ch2,
|
|
sizeof(ch2)), 0);
|
|
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), INVALID_PARAMETER);
|
|
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) && \
|
|
defined(HAVE_ECC)
|
|
/* Called when writing. */
|
|
static int MESend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
(void)ssl;
|
|
(void)buf;
|
|
(void)sz;
|
|
(void)ctx;
|
|
|
|
/* Force error return from wolfSSL_accept_TLSv13(). */
|
|
return WANT_WRITE;
|
|
}
|
|
/* Called when reading. */
|
|
static int MERecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
|
|
int len = (int)msg->length;
|
|
|
|
(void)ssl;
|
|
|
|
/* Pass back as much of message as will fit in buffer. */
|
|
if (len > sz)
|
|
len = sz;
|
|
XMEMCPY(buf, msg->buffer, len);
|
|
/* Move over returned data. */
|
|
msg->buffer += len;
|
|
msg->length -= len;
|
|
|
|
/* Amount actually copied. */
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_sg_missing(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) && \
|
|
defined(HAVE_ECC)
|
|
WOLFSSL_CTX *ctx = NULL;
|
|
WOLFSSL *ssl = NULL;
|
|
byte clientHello[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0xcb, 0x01, 0x00, 0x00,
|
|
0xc7, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x01,
|
|
0x01, 0x00, 0x00, 0x7c, 0x00, 0x0d, 0x00, 0x06,
|
|
0x00, 0x04, 0x04, 0x01, 0x08, 0x04,
|
|
/* KeyShare */
|
|
0x00, 0x33,
|
|
0x00, 0x67, 0x00, 0x65, 0x00, 0x18, 0x00, 0x61,
|
|
0x04, 0x53, 0x3e, 0xe5, 0xbf, 0x40, 0xec, 0x2d,
|
|
0x67, 0x98, 0x8b, 0x77, 0xf3, 0x17, 0x48, 0x9b,
|
|
0xb6, 0xdf, 0x95, 0x29, 0x25, 0xc7, 0x09, 0xfc,
|
|
0x03, 0x81, 0x11, 0x1a, 0x59, 0x56, 0xf2, 0xd7,
|
|
0x58, 0x11, 0x0e, 0x59, 0xd3, 0xd7, 0xc1, 0x72,
|
|
0x9e, 0x2c, 0x0d, 0x70, 0xea, 0xf7, 0x73, 0xe6,
|
|
0x12, 0x01, 0x16, 0x42, 0x6d, 0xe2, 0x43, 0x6a,
|
|
0x2f, 0x5f, 0xdd, 0x7f, 0xe5, 0x4f, 0xaf, 0x95,
|
|
0x2b, 0x04, 0xfd, 0x13, 0xf5, 0x16, 0xce, 0x62,
|
|
0x7f, 0x89, 0xd2, 0x01, 0x9d, 0x4c, 0x87, 0x96,
|
|
0x95, 0x9e, 0x43, 0x33, 0xc7, 0x06, 0x5b, 0x49,
|
|
0x6c, 0xa6, 0x34, 0xd5, 0xdc, 0x63, 0xbd, 0xe9,
|
|
0x1f,
|
|
/* SupportedVersions */
|
|
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
|
|
/* Missing SupportedGroups. */
|
|
};
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
WOLFSSL_ALERT_HISTORY h;
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile,
|
|
CERT_FILETYPE));
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, MERecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, MESend);
|
|
|
|
/* Test cipher suite list with many copies of a cipher suite. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientHello;
|
|
msg.length = (unsigned int)sizeof(clientHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
|
|
ExpectIntEQ(wolfSSL_accept_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
ExpectIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(h.last_tx.code, missing_extension);
|
|
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_tls13_ks_missing(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) && \
|
|
defined(HAVE_ECC)
|
|
WOLFSSL_CTX *ctx = NULL;
|
|
WOLFSSL *ssl = NULL;
|
|
byte clientHello[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x66, 0x01, 0x00, 0x00,
|
|
0x62, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x01,
|
|
0x01, 0x00, 0x00, 0x17, 0x00, 0x0d, 0x00, 0x06,
|
|
0x00, 0x04, 0x04, 0x01, 0x08, 0x04,
|
|
/* SupportedGroups */
|
|
0x00, 0x0a,
|
|
0x00, 0x02, 0x00, 0x18,
|
|
/* SupportedVersions */
|
|
0x00, 0x2b, 0x00, 0x03,
|
|
0x02, 0x03, 0x04
|
|
/* Missing KeyShare. */
|
|
};
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
WOLFSSL_ALERT_HISTORY h;
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile,
|
|
CERT_FILETYPE));
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, MERecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, MESend);
|
|
|
|
/* Test cipher suite list with many copies of a cipher suite. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientHello;
|
|
msg.length = (unsigned int)sizeof(clientHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
|
|
ExpectIntEQ(wolfSSL_accept_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
ExpectIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(h.last_tx.code, missing_extension);
|
|
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_ECC)
|
|
/* Called when writing. */
|
|
static int DESend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
(void)ssl;
|
|
(void)buf;
|
|
(void)sz;
|
|
(void)ctx;
|
|
|
|
return sz;
|
|
}
|
|
/* Called when reading. */
|
|
static int DERecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
|
|
int len = (int)msg->length;
|
|
|
|
(void)ssl;
|
|
(void)sz;
|
|
|
|
/* Pass back as much of message as will fit in buffer. */
|
|
if (len > sz)
|
|
len = sz;
|
|
XMEMCPY(buf, msg->buffer, len);
|
|
/* Move over returned data. */
|
|
msg->buffer += len;
|
|
msg->length -= len;
|
|
|
|
/* Amount actually copied. */
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_duplicate_extension(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(HAVE_ECC)
|
|
WOLFSSL_CTX *ctx = NULL;
|
|
WOLFSSL *ssl = NULL;
|
|
byte serverHello[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x81, 0x02, 0x00, 0x00,
|
|
0x7d, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x00, 0x13, 0x01, 0x00, 0x00,
|
|
0x55, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00,
|
|
0x33, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04,
|
|
0x0c, 0x90, 0x1d, 0x42, 0x3c, 0x83, 0x1c, 0xa8,
|
|
0x5e, 0x27, 0xc7, 0x3c, 0x26, 0x3b, 0xa1, 0x32,
|
|
0x72, 0x1b, 0xb9, 0xd7, 0xa8, 0x4c, 0x4f, 0x03,
|
|
0x80, 0xb2, 0xa6, 0x75, 0x6f, 0xd6, 0x01, 0x33,
|
|
0x1c, 0x88, 0x70, 0x23, 0x4d, 0xec, 0x87, 0x85,
|
|
0x04, 0xc1, 0x74, 0x14, 0x4f, 0xa4, 0xb1, 0x4b,
|
|
0x66, 0xa6, 0x51, 0x69, 0x16, 0x06, 0xd8, 0x17,
|
|
0x3e, 0x55, 0xbd, 0x37, 0xe3, 0x81, 0x56, 0x9e,
|
|
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04
|
|
};
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
WOLFSSL_ALERT_HISTORY h;
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, DERecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, DESend);
|
|
|
|
/* Test cipher suite list with many copies of a cipher suite. */
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = serverHello;
|
|
msg.length = (unsigned int)sizeof(serverHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
|
|
ExpectIntEQ(wolfSSL_connect_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
ExpectIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(h.last_tx.code, illegal_parameter);
|
|
ExpectIntEQ(h.last_tx.level, alert_fatal);
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
int test_key_share_mismatch(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
|
|
defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC) && \
|
|
defined(BUILD_TLS_AES_128_GCM_SHA256) && (!defined(WOLFSSL_SP_MATH) || \
|
|
(defined(WOLFSSL_SP_521) && !defined(WOLFSSL_SP_NO_256) && \
|
|
defined(WOLFSSL_SP_384)))
|
|
/* Taken from payload in https://github.com/wolfSSL/wolfssl/issues/9362 */
|
|
const byte ch1_bin[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0x96, 0x01, 0x00, 0x00, 0x92, 0x03, 0x03, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x01, 0x01, 0x00, 0x00, 0x47,
|
|
0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x18, 0x00, 0x17, 0x00, 0x1d,
|
|
0x00, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x08, 0x04, 0x00, 0x33,
|
|
0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x07, 0xaa, 0xff, 0x3e,
|
|
0x9f, 0xc1, 0x67, 0x27, 0x55, 0x44, 0xf4, 0xc3, 0xa6, 0xa1, 0x7c, 0xd8,
|
|
0x37, 0xf2, 0xec, 0x6e, 0x78, 0xcd, 0x8a, 0x57, 0xb1, 0xe3, 0xdf, 0xb3,
|
|
0xcc, 0x03, 0x5a, 0x76, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
|
|
};
|
|
const byte ch2_bin[] = {
|
|
0x16, 0x03, 0x03, 0x00, 0xb7, 0x01, 0x00, 0x00, 0xb3, 0x03, 0x03, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x13, 0x01, 0x01, 0x00, 0x00, 0x68,
|
|
0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x18, 0x00, 0x17, 0x00, 0x1d,
|
|
0x00, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x08, 0x04, 0x00, 0x33,
|
|
0x00, 0x47, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04, 0x0c, 0x90, 0x1d,
|
|
0x42, 0x3c, 0x83, 0x1c, 0xa8, 0x5e, 0x27, 0xc7, 0x3c, 0x26, 0x3b, 0xa1,
|
|
0x32, 0x72, 0x1b, 0xb9, 0xd7, 0xa8, 0x4c, 0x4f, 0x03, 0x80, 0xb2, 0xa6,
|
|
0x75, 0x6f, 0xd6, 0x01, 0x33, 0x1c, 0x88, 0x70, 0x23, 0x4d, 0xec, 0x87,
|
|
0x85, 0x04, 0xc1, 0x74, 0x14, 0x4f, 0xa4, 0xb1, 0x4b, 0x66, 0xa6, 0x51,
|
|
0x69, 0x16, 0x06, 0xd8, 0x17, 0x3e, 0x55, 0xbd, 0x37, 0xe3, 0x81, 0x56,
|
|
0x9e, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04
|
|
};
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
int client_group[] = {WOLFSSL_ECC_SECP521R1};
|
|
int server_group[] = {WOLFSSL_ECC_SECP384R1, WOLFSSL_ECC_SECP256R1};
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
ExpectIntEQ(wolfSSL_set_groups(ssl_c,
|
|
client_group, XELEM_CNT(client_group)), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_set_groups(ssl_s,
|
|
server_group, XELEM_CNT(server_group)), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), BAD_KEY_SHARE_DATA);
|
|
|
|
wolfSSL_free(ssl_s);
|
|
ssl_s = NULL;
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s,
|
|
NULL, wolfTLSv1_3_server_method), 0);
|
|
ExpectIntEQ(wolfSSL_set_groups(ssl_s,
|
|
server_group, XELEM_CNT(server_group)), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char*)ch1_bin,
|
|
sizeof(ch1_bin)), 0);
|
|
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char*)ch2_bin,
|
|
sizeof(ch2_bin)), 0);
|
|
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), BAD_KEY_SHARE_DATA);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_RSA) && defined(HAVE_ECC) && \
|
|
defined(HAVE_AESGCM) && !defined(NO_WOLFSSL_SERVER)
|
|
/* Called when writing. */
|
|
static int Tls13PTASend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
(void)ssl;
|
|
(void)buf;
|
|
(void)ctx;
|
|
|
|
return sz;
|
|
}
|
|
static int Tls13PTARecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
|
|
int len;
|
|
|
|
(void)ssl;
|
|
|
|
if (msg->length == 0) {
|
|
/* Only do as many alerts as required to get to max alert count. */
|
|
msg->buffer[0]--;
|
|
if (msg->buffer[0] > 0) {
|
|
msg->buffer -= 7;
|
|
msg->length += 7;
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
len = (int)msg->length;
|
|
/* Pass back as much of message as will fit in buffer. */
|
|
if (len > sz)
|
|
len = sz;
|
|
XMEMCPY(buf, msg->buffer, len);
|
|
/* Move over returned data. */
|
|
msg->buffer += len;
|
|
msg->length -= len;
|
|
|
|
/* Amount actually copied. */
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
/* Test that when a TLS 1.3 client sends a ClientHello with an empty
|
|
* legacy_session_id (indicating no middlebox compatibility), the server
|
|
* should NOT send a ChangeCipherSpec message. Per RFC 8446 Appendix D.4,
|
|
* the server only sends CCS if the client's ClientHello contains a
|
|
* non-empty session_id.
|
|
*
|
|
* This test reproduces the bug reported in GitHub issue #9156 where
|
|
* wolfSSL server always sends CCS when compiled with
|
|
* WOLFSSL_TLS13_MIDDLEBOX_COMPAT, regardless of the client's session_id.
|
|
*/
|
|
int test_tls13_middlebox_compat_empty_session_id(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) && \
|
|
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL_CTX *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
WOLFSSL *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
int i;
|
|
int found_ccs = 0;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* Disable middlebox compatibility on the client so it sends an empty
|
|
* legacy_session_id in ClientHello. The server should respect this and
|
|
* NOT send a ChangeCipherSpec. */
|
|
if (EXPECT_SUCCESS()) {
|
|
ssl_c->options.tls13MiddleBoxCompat = 0;
|
|
}
|
|
|
|
/* Client sends ClientHello with empty session ID */
|
|
ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c,
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ);
|
|
|
|
/* Server processes ClientHello and sends its flight:
|
|
* ServerHello, EncryptedExtensions, Certificate, CertVerify, Finished
|
|
* (and potentially an unwanted CCS) */
|
|
ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_s,
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ);
|
|
|
|
/* Now examine the server's output (stored in c_buff, since the server
|
|
* writes to the client's read buffer). Scan through TLS records looking
|
|
* for a ChangeCipherSpec record (content type 0x14 = 20). */
|
|
if (EXPECT_SUCCESS()) {
|
|
i = 0;
|
|
while (i + 5 <= test_ctx.c_len) {
|
|
byte content_type = test_ctx.c_buff[i];
|
|
int record_len = (test_ctx.c_buff[i + 3] << 8) |
|
|
test_ctx.c_buff[i + 4];
|
|
|
|
if (content_type == 20) { /* change_cipher_spec */
|
|
found_ccs = 1;
|
|
break;
|
|
}
|
|
|
|
/* Move to next TLS record: 5 byte header + payload */
|
|
i += 5 + record_len;
|
|
}
|
|
}
|
|
|
|
/* The server should NOT have sent CCS since the client's ClientHello
|
|
* had an empty legacy_session_id. If found_ccs is 1, this demonstrates
|
|
* the bug from issue #9156. */
|
|
ExpectIntEQ(found_ccs, 0);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_tls13_plaintext_alert(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_RSA) && defined(HAVE_ECC) && \
|
|
defined(HAVE_AESGCM) && !defined(NO_WOLFSSL_SERVER)
|
|
byte clientMsgs[] = {
|
|
/* Client Hello */
|
|
0x16, 0x03, 0x03, 0x01, 0x9b, 0x01, 0x00, 0x01,
|
|
0x97, 0x03, 0x03, 0xf4, 0x65, 0xbd, 0x22, 0xfe,
|
|
0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55,
|
|
0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8,
|
|
0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c,
|
|
0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b,
|
|
0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda,
|
|
0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x13, 0x01,
|
|
0x13, 0x02, 0x01, 0x00, 0x01, 0x4a, 0x00, 0x2d,
|
|
0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x33, 0x00,
|
|
0x47, 0x00, 0x45, 0x00, 0x17, 0x00, 0x41, 0x04,
|
|
0x90, 0xfc, 0xe2, 0x97, 0x05, 0x7c, 0xb5, 0x23,
|
|
0x5d, 0x5f, 0x5b, 0xcd, 0x0c, 0x1e, 0xe0, 0xe9,
|
|
0xab, 0x38, 0x6b, 0x1e, 0x20, 0x5c, 0x1c, 0x90,
|
|
0x2a, 0x9e, 0x68, 0x8e, 0x70, 0x05, 0x10, 0xa8,
|
|
0x02, 0x1b, 0xf9, 0x5c, 0xef, 0xc9, 0xaf, 0xca,
|
|
0x1a, 0x3b, 0x16, 0x8b, 0xe4, 0x1b, 0x3c, 0x15,
|
|
0xb8, 0x0d, 0xbd, 0xaf, 0x62, 0x8d, 0xa7, 0x13,
|
|
0xa0, 0x7c, 0xe0, 0x59, 0x0c, 0x4f, 0x8a, 0x6d,
|
|
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00,
|
|
0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05,
|
|
0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08,
|
|
0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08,
|
|
0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03,
|
|
0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x04, 0x00,
|
|
0x02, 0x00, 0x17, 0x00, 0x16, 0x00, 0x00, 0x00,
|
|
0x23, 0x00, 0x00, 0x00, 0x29, 0x00, 0xb9, 0x00,
|
|
0x94, 0x00, 0x8e, 0x0f, 0x12, 0xfa, 0x84, 0x1f,
|
|
0x76, 0x94, 0xd7, 0x09, 0x5e, 0xad, 0x08, 0x51,
|
|
0xb6, 0x80, 0x28, 0x31, 0x8b, 0xfd, 0xc6, 0xbd,
|
|
0x9e, 0xf5, 0x3b, 0x4d, 0x02, 0xbe, 0x1d, 0x73,
|
|
0xea, 0x13, 0x68, 0x00, 0x4c, 0xfd, 0x3d, 0x48,
|
|
0x51, 0xf9, 0x06, 0xbb, 0x92, 0xed, 0x42, 0x9f,
|
|
0x7f, 0x2c, 0x73, 0x9f, 0xd9, 0xb4, 0xef, 0x05,
|
|
0x26, 0x5b, 0x60, 0x5c, 0x0a, 0xfc, 0xa3, 0xbd,
|
|
0x2d, 0x2d, 0x8b, 0xf9, 0xaa, 0x5c, 0x96, 0x3a,
|
|
0xf2, 0xec, 0xfa, 0xe5, 0x57, 0x2e, 0x87, 0xbe,
|
|
0x27, 0xc5, 0x3d, 0x4f, 0x5d, 0xdd, 0xde, 0x1c,
|
|
0x1b, 0xb3, 0xcc, 0x27, 0x27, 0x57, 0x5a, 0xd9,
|
|
0xea, 0x99, 0x27, 0x23, 0xa6, 0x0e, 0xea, 0x9c,
|
|
0x0d, 0x85, 0xcb, 0x72, 0xeb, 0xd7, 0x93, 0xe3,
|
|
0xfe, 0xf7, 0x5c, 0xc5, 0x5b, 0x75, 0x8c, 0x47,
|
|
0x0a, 0x0e, 0xc4, 0x1a, 0xda, 0xef, 0x75, 0xe5,
|
|
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0xfb, 0x92, 0xce, 0xaa, 0x00, 0x21, 0x20,
|
|
0xcb, 0x73, 0x25, 0x80, 0x46, 0x78, 0x4f, 0xe5,
|
|
0x34, 0xf6, 0x91, 0x13, 0x7f, 0xc8, 0x8d, 0xdc,
|
|
0x81, 0x04, 0xb7, 0x0d, 0x49, 0x85, 0x2e, 0x12,
|
|
0x7a, 0x07, 0x23, 0xe9, 0x13, 0xa4, 0x6d, 0x8c,
|
|
0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00, 0x00
|
|
};
|
|
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
|
|
#ifdef WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC
|
|
/* We fail on WOLFSSL_ALERT_COUNT_MAX alerts. */
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
|
|
CERT_FILETYPE));
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
|
|
}
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, Tls13PTASend);
|
|
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientMsgs;
|
|
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
|
|
clientMsgs[sizeof(clientMsgs) - 1] = WOLFSSL_ALERT_COUNT_MAX;
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
}
|
|
/* Alert will be ignored until too many. */
|
|
/* Read all message include CertificateVerify with invalid signature
|
|
* algorithm. */
|
|
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
/* Expect an invalid parameter error. */
|
|
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
|
|
WC_NO_ERR_TRACE(ALERT_COUNT_E));
|
|
|
|
wolfSSL_free(ssl);
|
|
ssl = NULL;
|
|
wolfSSL_CTX_free(ctx);
|
|
ctx = NULL;
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
|
|
CERT_FILETYPE));
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
|
|
}
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, Tls13PTASend);
|
|
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientMsgs;
|
|
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
|
|
clientMsgs[sizeof(clientMsgs) - 1] = WOLFSSL_ALERT_COUNT_MAX - 1;
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
}
|
|
/* Alert will be ignored until too many. */
|
|
/* Read all message include CertificateVerify with invalid signature
|
|
* algorithm. */
|
|
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
/* Expect an invalid parameter error. */
|
|
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
|
|
WC_NO_ERR_TRACE(SOCKET_ERROR_E));
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#else
|
|
/* Fail on plaintext alert when encryption keys on. */
|
|
|
|
/* Set up wolfSSL context. */
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
|
ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE));
|
|
ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
|
|
CERT_FILETYPE));
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
|
|
}
|
|
/* Read from 'msg'. */
|
|
wolfSSL_SetIORecv(ctx, Tls13PTARecv);
|
|
/* No where to send to - dummy sender. */
|
|
wolfSSL_SetIOSend(ctx, Tls13PTASend);
|
|
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
msg.buffer = clientMsgs;
|
|
msg.length = (unsigned int)sizeof(clientMsgs) - 1;
|
|
clientMsgs[sizeof(clientMsgs) - 1] = 1;
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
}
|
|
/* Alert will be ignored until too many. */
|
|
/* Read all message include CertificateVerify with invalid signature
|
|
* algorithm. */
|
|
ExpectIntEQ(wolfSSL_accept(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
/* Expect an invalid parameter error. */
|
|
ExpectIntEQ(wolfSSL_get_error(ssl, WOLFSSL_FATAL_ERROR),
|
|
WC_NO_ERR_TRACE(PARSE_ERROR));
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
#endif
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Test that TLS 1.3 warning-level alerts are treated as fatal (RFC 8446
|
|
* Section 6.2).
|
|
* A peer sending e.g. {alert_warning, handshake_failure} must still cause the
|
|
* connection to be terminated, not silently continued.
|
|
*/
|
|
int test_tls13_warning_alert_is_fatal(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_WOLFSSL_CLIENT)
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_ALERT_HISTORY h;
|
|
/* TLS record: content_type=alert(0x15), version=TLS1.2(0x0303), len=2,
|
|
* level=warning(0x01), code=handshake_failure(0x28=40) */
|
|
static const unsigned char warn_alert[] =
|
|
{ 0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x28 };
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
|
|
wolfTLSv1_3_client_method, NULL), 0);
|
|
|
|
/* Client sends ClientHello, then waits for the server response. */
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
|
|
/* Inject a warning-level handshake_failure alert as if from the server.
|
|
* RFC 8446 Section 6.2: In TLS 1.3, all error alerts MUST be treated as
|
|
* fatalregardless of the AlertLevel byte. */
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
|
|
(const char *)warn_alert, sizeof(warn_alert)), 0);
|
|
|
|
/* Expect the connection to be terminated, not silently continued. */
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(FATAL_ERROR));
|
|
|
|
/* The alert details should be recorded correctly. */
|
|
ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(h.last_rx.code, handshake_failure);
|
|
ExpectIntEQ(h.last_rx.level, alert_warning);
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Test that an unknown extension in a TLS 1.3 server-to-client message is
|
|
* rejected with unsupported_extension (RFC 8446 Sec. 4.2). The client MUST
|
|
* abort the handshake when it receives an extension it did not advertise.
|
|
*/
|
|
int test_tls13_unknown_ext_rejected(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_AES_128) && \
|
|
defined(HAVE_AESGCM) && !defined(NO_SHA256) && \
|
|
!defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
/* HelloRetryRequest carrying TLS_AES_128_GCM_SHA256, supported_versions
|
|
* (TLS 1.3), and an extra unknown extension type 0xFABC.
|
|
*
|
|
* The base HRR (from test_tls13_same_ch) extended with 4 bytes:
|
|
* extensions length: 6 -> 10 (0x00,0x0a)
|
|
* handshake body length: 46 -> 50 (0x00,0x00,0x32)
|
|
* record body length: 50 -> 54 (0x00,0x36)
|
|
* appended: 0xfa,0xbc,0x00,0x00 (unknown type, zero-length value)
|
|
*/
|
|
static const unsigned char hrr_unknown_ext[] = {
|
|
/* TLS record header: handshake, TLS 1.2 compat, len=54 */
|
|
0x16, 0x03, 0x03, 0x00, 0x36,
|
|
/* Handshake header: ServerHello, len=50 */
|
|
0x02, 0x00, 0x00, 0x32,
|
|
/* legacy_version: TLS 1.2 */
|
|
0x03, 0x03,
|
|
/* HelloRetryRequest magic random */
|
|
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
|
|
0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
|
|
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
|
|
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
|
|
/* session ID length: 0 */
|
|
0x00,
|
|
/* cipher suite: TLS_AES_128_GCM_SHA256 */
|
|
0x13, 0x01,
|
|
/* compression: null */
|
|
0x00,
|
|
/* extensions length: 10 */
|
|
0x00, 0x0a,
|
|
/* supported_versions: TLS 1.3 (0x0304) */
|
|
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
|
|
/* unknown extension type 0xFABC, zero-length value */
|
|
0xfa, 0xbc, 0x00, 0x00
|
|
};
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
|
|
wolfTLSv1_3_client_method, NULL), 0);
|
|
|
|
/* Inject the crafted HRR before the client starts the handshake.
|
|
* wolfSSL_connect will send the ClientHello and then read this message. */
|
|
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
|
|
(const char *)hrr_unknown_ext, sizeof(hrr_unknown_ext)), 0);
|
|
|
|
/* RFC 8446 Sec. 4.2: the client MUST abort with unsupported_extension. */
|
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
|
|
WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION));
|
|
|
|
/* The client MUST also transmit the fatal unsupported_extension alert
|
|
* on the wire, not merely surface a local error. The client's outgoing
|
|
* data lands in test_ctx.s_buff; at this point in the handshake no
|
|
* traffic keys are derived yet, so the alert record is plaintext.
|
|
* Expected record: type=alert(0x15), version=TLS1.2(0x0303), len=2,
|
|
* level=fatal(0x02), description=unsupported_extension(0x6e=110). */
|
|
{
|
|
static const unsigned char expected_alert[] =
|
|
{ 0x15, 0x03, 0x03, 0x00, 0x02, 0x02, 0x6e };
|
|
int found = 0;
|
|
int i;
|
|
for (i = 0;
|
|
i + (int)sizeof(expected_alert) <= test_ctx.s_len;
|
|
i++) {
|
|
if (XMEMCMP(test_ctx.s_buff + i, expected_alert,
|
|
sizeof(expected_alert)) == 0) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
ExpectIntEQ(found, 1);
|
|
}
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Test that wolfSSL_set1_sigalgs_list() is honored in TLS 1.3
|
|
*/
|
|
int test_tls13_cert_req_sigalgs(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
!defined(NO_CERTS) && !defined(NO_RSA) && defined(WC_RSA_PSS) && \
|
|
defined(HAVE_ECC) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
!defined(NO_WOLFSSL_SERVER) && defined(OPENSSL_EXTRA) && \
|
|
!defined(NO_FILESYSTEM)
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
struct test_memio_ctx test_ctx;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* Server: require client cert and load ECC client cert for verification */
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_set_verify(ssl_s,
|
|
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
|
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s,
|
|
cliEccCertFile, 0), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Server: restrict CertificateRequest to RSA-PSS+SHA256 only */
|
|
if (EXPECT_SUCCESS()) {
|
|
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_s, "RSA-PSS+SHA256"),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Client: load ECC cert/key */
|
|
if (EXPECT_SUCCESS()) {
|
|
ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliEccCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliEccKeyFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Handshake must fail: ECC client cannot match RSA-PSS+SHA256 */
|
|
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
wolfSSL_free(ssl_c); ssl_c = NULL;
|
|
wolfSSL_free(ssl_s); ssl_s = NULL;
|
|
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
|
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* Server: require client cert and load RSA client cert for verification */
|
|
if (EXPECT_SUCCESS()) {
|
|
wolfSSL_set_verify(ssl_s,
|
|
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
|
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s,
|
|
cliCertFile, 0), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Server: restrict CertificateRequest to RSA-PSS+SHA256 only */
|
|
if (EXPECT_SUCCESS()) {
|
|
ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl_s, "RSA-PSS+SHA256"),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Client: load RSA cert/key */
|
|
if (EXPECT_SUCCESS()) {
|
|
ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
}
|
|
|
|
/* Handshake must succeed: RSA client satisfies RSA-PSS+SHA256 */
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
wolfSSL_free(ssl_c); ssl_c = NULL;
|
|
wolfSSL_free(ssl_s); ssl_s = NULL;
|
|
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
|
|
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
|
|
#endif
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_tls13_derive_keys_no_key(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_CTX *ctx_c = NULL;
|
|
WOLFSSL_CTX *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL;
|
|
WOLFSSL *ssl_s = NULL;
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* DeriveTls13Keys with no_key should succeed (skip secret derivation,
|
|
* only derive keys/IVs from existing secrets). This is used with early
|
|
* data to derive keys without re-deriving the secrets. */
|
|
ExpectIntEQ(DeriveTls13Keys(ssl_s, no_key, DECRYPT_SIDE_ONLY, 0), 0);
|
|
ExpectIntEQ(DeriveTls13Keys(ssl_s, no_key, ENCRYPT_SIDE_ONLY, 0), 0);
|
|
ExpectIntEQ(DeriveTls13Keys(ssl_c, no_key, ENCRYPT_AND_DECRYPT_SIDE, 0),
|
|
0);
|
|
|
|
/* Unknown secret type should return BAD_FUNC_ARG */
|
|
ExpectIntEQ(DeriveTls13Keys(ssl_c, -1, ENCRYPT_SIDE_ONLY, 0),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Test that a truncated PQC hybrid KeyShare in a ServerHello does not cause a
|
|
* heap use-after-free during cleanup. A malicious server sends
|
|
* SECP256R1MLKEM768 with only 10 bytes of key exchange data (expected: 1120+).
|
|
* This exercises the error path in TLSX_KeyShare_ProcessPqcHybridClient().
|
|
* Under ASAN the UAF manifests as ForceZero writing to freed KyberKey memory
|
|
* during wolfSSL_free -> TLSX_FreeAll -> TLSX_KeyShare_FreeAll. */
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(WOLFSSL_HAVE_MLKEM) && defined(WOLFSSL_PQC_HYBRIDS) && \
|
|
!defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY)
|
|
/* Called when writing - discard output. */
|
|
static int PqcHybridUafSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
(void)ssl;
|
|
(void)buf;
|
|
(void)ctx;
|
|
return sz;
|
|
}
|
|
/* Called when reading - feed from buffer. */
|
|
static int PqcHybridUafRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
|
|
{
|
|
WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx;
|
|
int len = (int)msg->length;
|
|
|
|
(void)ssl;
|
|
|
|
if (len > sz)
|
|
len = sz;
|
|
XMEMCPY(buf, msg->buffer, len);
|
|
msg->buffer += len;
|
|
msg->length -= len;
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
int test_tls13_pqc_hybrid_truncated_keyshare(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) && \
|
|
defined(WOLFSSL_HAVE_MLKEM) && defined(WOLFSSL_PQC_HYBRIDS) && \
|
|
!defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
|
|
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
|
|
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY)
|
|
WOLFSSL_CTX *ctx = NULL;
|
|
WOLFSSL *ssl = NULL;
|
|
/* Crafted TLS 1.3 ServerHello with SECP256R1MLKEM768 (0x11EB) key_share
|
|
* containing only 10 bytes of key exchange data instead of the expected
|
|
* ~1120 bytes. This triggers the error cleanup path. */
|
|
byte serverHello[] = {
|
|
/* TLS record: Handshake, TLS 1.2 compat, length 68 */
|
|
0x16, 0x03, 0x03, 0x00, 0x44,
|
|
/* Handshake: ServerHello (0x02), length 64 */
|
|
0x02, 0x00, 0x00, 0x40,
|
|
/* legacy_version */
|
|
0x03, 0x03,
|
|
/* random (32 bytes) */
|
|
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
|
/* legacy_session_id_echo length: 0 */
|
|
0x00,
|
|
/* cipher_suite: TLS_AES_128_GCM_SHA256 */
|
|
0x13, 0x01,
|
|
/* legacy_compression_method: null */
|
|
0x00,
|
|
/* extensions length: 24 */
|
|
0x00, 0x18,
|
|
/* extension: supported_versions -> TLS 1.3 */
|
|
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
|
|
/* extension: key_share (truncated hybrid data) */
|
|
0x00, 0x33, /* type */
|
|
0x00, 0x0e, /* length: 14 */
|
|
0x11, 0xeb, /* named_group: SECP256R1MLKEM768 (4587) */
|
|
0x00, 0x0a, /* key_exchange length: 10 (truncated!) */
|
|
0x41, 0x41, 0x41, 0x41, 0x41, /* bogus key data */
|
|
0x41, 0x41, 0x41, 0x41, 0x41
|
|
};
|
|
WOLFSSL_BUFFER_INFO msg;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
|
wolfSSL_SetIORecv(ctx, PqcHybridUafRecv);
|
|
wolfSSL_SetIOSend(ctx, PqcHybridUafSend);
|
|
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* Generate the client-side PQC hybrid key share so the truncated
|
|
* ServerHello key_share will be processed (group must match). */
|
|
ExpectIntEQ(wolfSSL_UseKeyShare(ssl, WOLFSSL_SECP256R1MLKEM768),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
msg.buffer = serverHello;
|
|
msg.length = (unsigned int)sizeof(serverHello);
|
|
wolfSSL_SetIOReadCtx(ssl, &msg);
|
|
|
|
/* Connect should fail gracefully on the truncated key share. */
|
|
ExpectIntEQ(wolfSSL_connect_TLSv13(ssl),
|
|
WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR));
|
|
|
|
/* The UAF, if present, triggers here: wolfSSL_free -> TLSX_FreeAll ->
|
|
* TLSX_KeyShare_FreeAll -> ForceZero on already-freed KyberKey. */
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
/* Test that a TLS 1.3 NewSessionTicket with a ticket shorter than ID_LEN
|
|
* (32 bytes) does not cause an unsigned integer underflow / OOB read in
|
|
* SetTicket. Uses a full memio handshake, then injects a crafted
|
|
* NewSessionTicket with a 5-byte ticket into the client's read path. */
|
|
int test_tls13_short_session_ticket(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
|
defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
|
|
struct test_memio_ctx test_ctx;
|
|
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
|
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
|
char buf[64];
|
|
|
|
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
|
|
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
|
|
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);
|
|
|
|
/* Complete a TLS 1.3 handshake. The server will send a
|
|
* NewSessionTicket as part of post-handshake messages. */
|
|
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
|
|
|
/* Read on client to consume the server's NewSessionTicket. */
|
|
ExpectIntEQ(wolfSSL_read(ssl_c, buf, sizeof(buf)), -1);
|
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
|
|
|
|
/* Now directly test SetTicket with a short ticket by poking the
|
|
* session. The session object is accessible; replicate the exact
|
|
* vulnerable arithmetic: ticket + length - ID_LEN with length=5.
|
|
* With the fix, sessIdLen is capped to length so no underflow. */
|
|
{
|
|
byte shortTicket[5] = { 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
|
|
word32 length = sizeof(shortTicket);
|
|
word32 sessIdLen = ID_LEN;
|
|
|
|
if (length < ID_LEN)
|
|
sessIdLen = length;
|
|
|
|
XMEMCPY(ssl_c->session->staticTicket, shortTicket, length);
|
|
ssl_c->session->ticketLen = (word16)length;
|
|
ssl_c->session->ticket = ssl_c->session->staticTicket;
|
|
|
|
/* This is the exact code from SetTicket. Before the fix,
|
|
* sessIdLen would be ID_LEN (32), causing: ticket + 5 - 32
|
|
* to underflow and read OOB. */
|
|
XMEMSET(ssl_c->session->sessionID, 0, ID_LEN);
|
|
XMEMCPY(ssl_c->session->sessionID,
|
|
ssl_c->session->ticket + length - sessIdLen,
|
|
sessIdLen);
|
|
ssl_c->session->sessionIDSz = ID_LEN;
|
|
|
|
/* Verify: sessionID should contain only the 5 ticket bytes,
|
|
* zero-padded, not garbage from an OOB read. */
|
|
ExpectBufEQ(ssl_c->session->sessionID, shortTicket, 5);
|
|
}
|
|
|
|
wolfSSL_free(ssl_c);
|
|
wolfSSL_free(ssl_s);
|
|
wolfSSL_CTX_free(ctx_c);
|
|
wolfSSL_CTX_free(ctx_s);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|