mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-07 04:50:48 +02:00
@@ -120,6 +120,16 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len)
|
||||
WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_read");
|
||||
}
|
||||
|
||||
/* Reject a negative length up front. Callers are expected to validate, but
|
||||
* guarding here too prevents a negative len from defeating the signed
|
||||
* bounds checks below (sz/memSz comparisons) and reaching XMEMCPY with a
|
||||
* length of (size_t)-1. Return the same error the public wolfSSL_BIO_read()
|
||||
* does for a negative length rather than silently reporting 0 bytes read. A
|
||||
* zero length is handled correctly by the logic below (copies nothing). */
|
||||
if (len < 0) {
|
||||
return WOLFSSL_BIO_ERROR;
|
||||
}
|
||||
|
||||
sz = wolfSSL_BIO_pending(bio);
|
||||
if (sz > 0) {
|
||||
int memSz;
|
||||
|
||||
+19
-21
@@ -15690,31 +15690,29 @@ PRAGMA_GCC_DIAG_POP
|
||||
ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl), extraSigners);
|
||||
|
||||
#if defined(HAVE_RPK)
|
||||
/* if cert type has negotiated with peer, confirm the cert received has
|
||||
* the same type.
|
||||
*/
|
||||
if (ret == 0 ) {
|
||||
if (ssl->options.side == WOLFSSL_CLIENT_END) {
|
||||
if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) {
|
||||
/* Confirm the received certificate's form (X.509 vs raw public key) matches
|
||||
* the type negotiated with the peer. A raw public key (RFC 7250) has no
|
||||
* chain, so ParseCertRelative() accepts it without any trust verification;
|
||||
* it must only be accepted when RPK was negotiated for this peer. When no
|
||||
* type was negotiated the default is X.509 (RFC 7250/8446), so an
|
||||
* un-negotiated bare key is rejected. The negotiated type is the received
|
||||
* server cert type (client) or the selected client cert type (server). */
|
||||
if (ret == 0) {
|
||||
cType = WOLFSSL_CERT_TYPE_X509;
|
||||
if (ssl->options.side == WOLFSSL_CLIENT_END) {
|
||||
if (ssl->options.rpkState.received_ServerCertTypeCnt == 1)
|
||||
cType = ssl->options.rpkState.received_ServerCertTypes[0];
|
||||
if ((cType == WOLFSSL_CERT_TYPE_RPK && !args->dCert->isRPK) ||
|
||||
(cType == WOLFSSL_CERT_TYPE_X509 && args->dCert->isRPK)) {
|
||||
/* cert type mismatch */
|
||||
WOLFSSL_MSG("unsupported certificate type received");
|
||||
ret = UNSUPPORTED_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) {
|
||||
if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1)
|
||||
cType = ssl->options.rpkState.sending_ClientCertTypes[0];
|
||||
if ((cType == WOLFSSL_CERT_TYPE_RPK && !args->dCert->isRPK) ||
|
||||
(cType == WOLFSSL_CERT_TYPE_X509 && args->dCert->isRPK)) {
|
||||
/* cert type mismatch */
|
||||
WOLFSSL_MSG("unsupported certificate type received");
|
||||
ret = UNSUPPORTED_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((cType == WOLFSSL_CERT_TYPE_RPK && !args->dCert->isRPK) ||
|
||||
(cType != WOLFSSL_CERT_TYPE_RPK && args->dCert->isRPK)) {
|
||||
/* cert type mismatch - includes an un-negotiated raw public key */
|
||||
WOLFSSL_MSG("unsupported certificate type received");
|
||||
ret = UNSUPPORTED_CERTIFICATE;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_RPK */
|
||||
|
||||
+8
-3
@@ -3205,10 +3205,15 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
|
||||
}
|
||||
#ifndef ALLOW_INVALID_CERTSIGN
|
||||
else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
|
||||
type != WOLFSSL_TEMP_CA && !cert->selfSigned &&
|
||||
!cert->selfSigned && cert->extKeyUsageSet &&
|
||||
(cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
|
||||
/* Intermediate CA certs are required to have the keyCertSign
|
||||
* extension set. User loaded root certs are not. */
|
||||
/* Intermediate CA certs - including chain-supplied temporary CAs
|
||||
* (WOLFSSL_TEMP_CA) added while building a path - are required to have
|
||||
* the keyCertSign key usage when a Key Usage extension is present.
|
||||
* Only operator-loaded root certs (WOLFSSL_USER_CA) and self-signed
|
||||
* roots are exempt. Per RFC 5280 an absent Key Usage extension implies
|
||||
* all usages, so only enforce this when the extension is actually
|
||||
* present (extKeyUsageSet). */
|
||||
WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
|
||||
ret = NOT_CA_ERROR;
|
||||
}
|
||||
|
||||
@@ -816,6 +816,19 @@ int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs,
|
||||
if (ret != 0)
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
/* Reject a degenerate (certs-only) PKCS#7 with no verified signer. Such an
|
||||
* object has empty signerInfos, so wc_PKCS7_VerifySignedData() succeeds
|
||||
* without authenticating the content. pkcs7.verifyCert is only set once a
|
||||
* signer's signature has actually been verified, so a NULL value here means
|
||||
* the content carries no valid signature and must not be reported as
|
||||
* verified - regardless of PKCS7_NOVERIFY, which only suppresses signer
|
||||
* certificate chain validation, not the requirement that a signature exist.
|
||||
*/
|
||||
if (p7->pkcs7.verifyCert == NULL) {
|
||||
WOLFSSL_MSG("PKCS7 has no verified signer (degenerate/certs-only)");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) {
|
||||
/* Verify signer certificates */
|
||||
if (store == NULL || store->cm == NULL) {
|
||||
|
||||
+17
-2
@@ -11835,7 +11835,10 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
#endif
|
||||
if (
|
||||
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
|
||||
!ssl->options.verifyPostHandshake &&
|
||||
/* Exempt only the initial handshake; a pending post-handshake
|
||||
* CertificateRequest (certReqCtx != NULL) still requires a peer
|
||||
* certificate and a valid CertificateVerify. */
|
||||
(!ssl->options.verifyPostHandshake || ssl->certReqCtx != NULL) &&
|
||||
#endif
|
||||
(!ssl->options.havePeerCert || !ssl->options.havePeerVerify)) {
|
||||
ret = NO_PEER_CERT; /* NO_PEER_VERIFY */
|
||||
@@ -13507,7 +13510,19 @@ static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type)
|
||||
*/
|
||||
if (ssl->options.verifyPeer &&
|
||||
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
|
||||
!ssl->options.verifyPostHandshake &&
|
||||
/* The post-handshake-auth exemption is only valid during
|
||||
* the initial handshake. On the server, once a
|
||||
* post-handshake CertificateRequest is outstanding
|
||||
* (certReqCtx != NULL), a Certificate is required again.
|
||||
* Scoped to the server: certReqCtx means something
|
||||
* different on the client (a received request) and the
|
||||
* client does not process an inbound Finished in that
|
||||
* state. Whether an empty Certificate is then accepted
|
||||
* follows the verify mode (FAIL_IF_NO_PEER_CERT), exactly
|
||||
* as for first-handshake client authentication. */
|
||||
(!ssl->options.verifyPostHandshake ||
|
||||
(ssl->options.side == WOLFSSL_SERVER_END &&
|
||||
ssl->certReqCtx != NULL)) &&
|
||||
#endif
|
||||
!ssl->msgsReceived.got_certificate) {
|
||||
WOLFSSL_MSG("Finished received out of order - "
|
||||
|
||||
@@ -578,6 +578,110 @@ int test_wc_ecc_shared_secret(void)
|
||||
return EXPECT_RESULT();
|
||||
} /* END tests_wc_ecc_shared_secret */
|
||||
|
||||
#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) && \
|
||||
(defined(HAVE_ECC384) || defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES))
|
||||
/* Verify the output-buffer size contract of wc_ecc_shared_secret() at the
|
||||
* field-size boundary. The single-precision (SP) math secret generators for
|
||||
* P-384/P-521 historically validated the caller's buffer against the wrong
|
||||
* length (e.g. P-521 checked 65 but writes 66), so a buffer declared one byte
|
||||
* short of the field size slipped past the check and was overwritten. Assert
|
||||
* that fieldSz-1 is rejected with BUFFER_E and fieldSz succeeds, for whichever
|
||||
* math backend is built.
|
||||
*
|
||||
* Coverage note: this drives the blocking generators only (wc_ecc_shared_secret
|
||||
* is synchronous). The fix also corrected the non-blocking (_nb) variants
|
||||
* (sp_ecc_secret_gen_384_nb / _521_nb), which need WOLFSSL_SP_NONBLOCK plus the
|
||||
* specialized SP build and are not exercised here. Of the blocking cases only
|
||||
* P-521 (65->66) actually fails without the fix; P-384 already used 48, so its
|
||||
* case is a guard against regression rather than a reproduction. */
|
||||
static int ecc_shared_secret_size_bound(WC_RNG* rng, int curveId, int fieldSz)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
ecc_key key;
|
||||
ecc_key pub;
|
||||
byte out[80]; /* >= P-521 field size (66) */
|
||||
word32 outlen;
|
||||
int keyInit = 0, pubInit = 0;
|
||||
int ret;
|
||||
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
XMEMSET(&pub, 0, sizeof(pub));
|
||||
|
||||
ExpectIntEQ(wc_ecc_init(&key), 0);
|
||||
if (EXPECT_SUCCESS()) keyInit = 1;
|
||||
ExpectIntEQ(wc_ecc_init(&pub), 0);
|
||||
if (EXPECT_SUCCESS()) pubInit = 1;
|
||||
|
||||
ret = wc_ecc_make_key_ex(rng, fieldSz, &key, curveId);
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE);
|
||||
#endif
|
||||
ExpectIntEQ(ret, 0);
|
||||
|
||||
ret = wc_ecc_make_key_ex(rng, fieldSz, &pub, curveId);
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &pub.asyncDev, WC_ASYNC_FLAG_NONE);
|
||||
#endif
|
||||
ExpectIntEQ(ret, 0);
|
||||
|
||||
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
|
||||
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
|
||||
!defined(HAVE_SELFTEST)
|
||||
ExpectIntEQ(wc_ecc_set_rng(&key, rng), 0);
|
||||
#endif
|
||||
|
||||
/* One byte short of the field size: must be rejected, not written past. */
|
||||
outlen = (word32)(fieldSz - 1);
|
||||
ExpectIntEQ(wc_ecc_shared_secret(&key, &pub, out, &outlen),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
|
||||
/* Exactly the field size: must succeed and report the field size. */
|
||||
outlen = (word32)fieldSz;
|
||||
ExpectIntEQ(wc_ecc_shared_secret(&key, &pub, out, &outlen), 0);
|
||||
ExpectIntEQ(outlen, (word32)fieldSz);
|
||||
|
||||
if (pubInit)
|
||||
wc_ecc_free(&pub);
|
||||
if (keyInit)
|
||||
wc_ecc_free(&key);
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Testing wc_ecc_shared_secret() output buffer bounds at the field-size edge.
|
||||
*/
|
||||
int test_wc_ecc_shared_secret_size_bounds(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(HAVE_ECC) && defined(HAVE_ECC_DHE) && !defined(WC_NO_RNG) && \
|
||||
(defined(HAVE_ECC384) || defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES))
|
||||
WC_RNG rng;
|
||||
int rngInit = 0;
|
||||
|
||||
XMEMSET(&rng, 0, sizeof(rng));
|
||||
PRIVATE_KEY_UNLOCK();
|
||||
ExpectIntEQ(wc_InitRng(&rng), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
rngInit = 1;
|
||||
|
||||
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
|
||||
ExpectIntEQ(ecc_shared_secret_size_bound(&rng, ECC_SECP384R1, 48), 1);
|
||||
#endif
|
||||
#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
|
||||
ExpectIntEQ(ecc_shared_secret_size_bound(&rng, ECC_SECP521R1, 66), 1);
|
||||
#endif
|
||||
|
||||
if (rngInit)
|
||||
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
||||
#ifdef FP_ECC
|
||||
wc_ecc_fp_free();
|
||||
#endif
|
||||
PRIVATE_KEY_LOCK();
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/*
|
||||
* testint wc_ecc_export_x963()
|
||||
*/
|
||||
|
||||
@@ -36,6 +36,7 @@ int test_wc_ecc_size(void);
|
||||
int test_wc_ecc_params(void);
|
||||
int test_wc_ecc_signVerify_hash(void);
|
||||
int test_wc_ecc_shared_secret(void);
|
||||
int test_wc_ecc_shared_secret_size_bounds(void);
|
||||
int test_wc_ecc_export_x963(void);
|
||||
int test_wc_ecc_export_x963_ex(void);
|
||||
int test_wc_ecc_import_x963(void);
|
||||
@@ -74,6 +75,7 @@ int test_wc_EccPrivateKeyToDer(void);
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_params), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_signVerify_hash), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_shared_secret_size_bounds), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_export_x963_ex), \
|
||||
TEST_DECL_GROUP("ecc", test_wc_ecc_import_x963), \
|
||||
|
||||
@@ -980,6 +980,45 @@ int test_wolfSSL_BIO_write(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* A negative length must never defeat the memory-BIO read bounds check and
|
||||
* reach XMEMCPY with (size_t)-1. This exercises the public BIO_read() boundary
|
||||
* (which rejects a negative length before dispatch); the matching guard in the
|
||||
* static wolfSSL_BIO_MEMORY_read() sink is defense-in-depth and not separately
|
||||
* reachable through the public API. Verify a negative length is rejected with
|
||||
* an error without copying, a zero length reads nothing, and the pending data
|
||||
* is left intact and still readable. */
|
||||
int test_wolfSSL_BIO_read_negative_len(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_EXTRA)
|
||||
BIO* bio = NULL;
|
||||
char msg[] = "negative length test";
|
||||
int msgLen = (int)XSTRLEN(msg);
|
||||
char out[64];
|
||||
|
||||
ExpectNotNull(bio = BIO_new(BIO_s_mem()));
|
||||
ExpectIntEQ(BIO_write(bio, msg, msgLen), msgLen);
|
||||
|
||||
/* Negative length: must be rejected with an error, not a wild copy and not
|
||||
* a silent 0-byte read. */
|
||||
XMEMSET(out, 0, sizeof(out));
|
||||
ExpectIntLT(BIO_read(bio, out, -1), 0);
|
||||
/* Data must be untouched - still all pending. */
|
||||
ExpectIntEQ(BIO_pending(bio), msgLen);
|
||||
|
||||
/* Zero length: nothing read, data still pending. */
|
||||
ExpectIntEQ(BIO_read(bio, out, 0), 0);
|
||||
ExpectIntEQ(BIO_pending(bio), msgLen);
|
||||
|
||||
/* A normal read still returns the intact message. */
|
||||
ExpectIntEQ(BIO_read(bio, out, (int)sizeof(out)), msgLen);
|
||||
ExpectIntEQ(XMEMCMP(out, msg, msgLen), 0);
|
||||
|
||||
BIO_free(bio);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
|
||||
int test_wolfSSL_BIO_printf(void)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ int test_wolfSSL_BIO_datagram(void);
|
||||
int test_wolfSSL_BIO_s_null(void);
|
||||
int test_wolfSSL_BIO_accept(void);
|
||||
int test_wolfSSL_BIO_write(void);
|
||||
int test_wolfSSL_BIO_read_negative_len(void);
|
||||
int test_wolfSSL_BIO_printf(void);
|
||||
int test_wolfSSL_BIO_f_md(void);
|
||||
int test_wolfSSL_BIO_up_ref(void);
|
||||
@@ -55,6 +56,7 @@ int test_wolfSSL_BIO_get_init(void);
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_should_retry), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_s_null), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_write), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_read_negative_len), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_printf), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_f_md), \
|
||||
TEST_DECL_GROUP("ossl_bio", test_wolfSSL_BIO_up_ref), \
|
||||
|
||||
@@ -675,6 +675,101 @@ int test_wolfSSL_PKCS7_verify_signer_forgery(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* A degenerate (certs-only) PKCS#7 - one with an empty signerInfos SET and
|
||||
* therefore no signature at all - must NOT be reported as verified, even when
|
||||
* the embedded certificate chains to a trusted CA, and even when
|
||||
* PKCS7_NOVERIFY is set (which only suppresses signer-cert chain validation,
|
||||
* not the requirement that a signature exist). */
|
||||
int test_wolfSSL_PKCS7_verify_degenerate(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) && !defined(NO_BIO) && \
|
||||
!defined(NO_FILESYSTEM) && !defined(NO_RSA)
|
||||
const char* signerCertFile = "./certs/server-cert.pem";
|
||||
const char* caFile = "./certs/ca-cert.pem";
|
||||
const byte attackerContent[] = "ATTACKER-CONTENT";
|
||||
PKCS7* encodeP7 = NULL;
|
||||
PKCS7* p7 = NULL;
|
||||
X509* signerCert = NULL;
|
||||
X509* caCert = NULL;
|
||||
STACK_OF(X509)* sk = NULL;
|
||||
X509_STORE* store = NULL;
|
||||
BIO* certBio = NULL;
|
||||
BIO* caBio = NULL;
|
||||
BIO* derBio = NULL;
|
||||
BIO* inBio = NULL;
|
||||
BIO* outBio = NULL;
|
||||
const byte* der = NULL;
|
||||
const byte* outData = NULL;
|
||||
int derSz = 0;
|
||||
|
||||
/* ---- Build a degenerate certs-only PKCS#7 wrapping server-cert. ---- */
|
||||
ExpectNotNull(certBio = BIO_new_file(signerCertFile, "r"));
|
||||
ExpectNotNull(signerCert = PEM_read_bio_X509(certBio, NULL, 0, NULL));
|
||||
ExpectNotNull(sk = sk_X509_new_null());
|
||||
ExpectIntGT(sk_X509_push(sk, signerCert), 0);
|
||||
if (EXPECT_SUCCESS())
|
||||
signerCert = NULL; /* now owned by sk */
|
||||
|
||||
ExpectNotNull(encodeP7 = PKCS7_new());
|
||||
if (encodeP7 != NULL) {
|
||||
encodeP7->version = 1;
|
||||
#ifdef NO_SHA
|
||||
encodeP7->hashOID = SHA256h;
|
||||
#else
|
||||
encodeP7->hashOID = SHAh;
|
||||
#endif
|
||||
}
|
||||
ExpectNotNull(derBio = BIO_new(BIO_s_mem()));
|
||||
/* wolfSSL_PKCS7_encode_certs() takes ownership of sk (sets p7->certs, freed
|
||||
* by PKCS7_free(encodeP7) below) whenever it is called with a valid PKCS7
|
||||
* and BIO - success or failure. It only declines ownership when encodeP7 or
|
||||
* derBio is NULL, in which case the test still owns sk and frees it in
|
||||
* cleanup. */
|
||||
ExpectIntEQ(wolfSSL_PKCS7_encode_certs(encodeP7, sk, derBio), 1);
|
||||
if (encodeP7 != NULL && derBio != NULL)
|
||||
sk = NULL; /* now owned by encodeP7 */
|
||||
ExpectIntGT((derSz = BIO_get_mem_data(derBio, &der)), 0);
|
||||
|
||||
/* ---- Re-parse it; a degenerate bundle parses successfully. ---- */
|
||||
ExpectNotNull(p7 = d2i_PKCS7(NULL, &der, derSz));
|
||||
|
||||
/* ---- Trust store contains the embedded cert's issuer (ca-cert). ---- */
|
||||
ExpectNotNull(caBio = BIO_new_file(caFile, "r"));
|
||||
ExpectNotNull(caCert = PEM_read_bio_X509(caBio, NULL, 0, NULL));
|
||||
ExpectNotNull(store = X509_STORE_new());
|
||||
ExpectIntEQ(X509_STORE_add_cert(store, caCert), 1);
|
||||
|
||||
/* ---- Attacker-supplied detached content + capture of any output. ---- */
|
||||
ExpectNotNull(inBio = BIO_new_mem_buf(attackerContent,
|
||||
(int)sizeof(attackerContent) - 1));
|
||||
ExpectNotNull(outBio = BIO_new(BIO_s_mem()));
|
||||
|
||||
/* With a trust store (flags = 0): must be rejected, and the attacker
|
||||
* content must NOT be emitted through the output BIO. */
|
||||
ExpectIntEQ(PKCS7_verify(p7, NULL, store, inBio, outBio, 0),
|
||||
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
||||
ExpectIntLE(BIO_get_mem_data(outBio, &outData), 0);
|
||||
|
||||
/* PKCS7_NOVERIFY must not turn a signature-less bundle into a pass. */
|
||||
ExpectIntEQ(PKCS7_verify(p7, NULL, store, inBio, NULL, PKCS7_NOVERIFY),
|
||||
WC_NO_ERR_TRACE(WOLFSSL_FAILURE));
|
||||
|
||||
PKCS7_free(p7);
|
||||
PKCS7_free(encodeP7); /* frees sk + signerCert once owned */
|
||||
X509_STORE_free(store);
|
||||
X509_free(caCert);
|
||||
sk_X509_pop_free(sk, X509_free); /* no-op if ownership passed to encodeP7 */
|
||||
X509_free(signerCert); /* no-op if pushed onto sk */
|
||||
BIO_free(certBio);
|
||||
BIO_free(caBio);
|
||||
BIO_free(derBio);
|
||||
BIO_free(inBio);
|
||||
BIO_free(outBio);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Exercise the SignerInfo-sid binding enforcement end-to-end.
|
||||
*
|
||||
* For both supported sid encodings (v1 = IssuerAndSerialNumber, v3 =
|
||||
|
||||
@@ -29,6 +29,7 @@ int test_wolfSSL_PKCS7_certs(void);
|
||||
int test_wolfSSL_PKCS7_sign(void);
|
||||
int test_wolfSSL_PKCS7_verify_signer_forgery(void);
|
||||
int test_wolfSSL_PKCS7_verify_sid_binding(void);
|
||||
int test_wolfSSL_PKCS7_verify_degenerate(void);
|
||||
int test_wolfSSL_PKCS7_SIGNED_new(void);
|
||||
int test_wolfSSL_PEM_write_bio_PKCS7(void);
|
||||
int test_wolfSSL_PEM_write_bio_encryptedKey(void);
|
||||
@@ -42,6 +43,7 @@ int test_wolfSSL_PKCS12(void);
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PKCS7_sign), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PKCS7_verify_signer_forgery), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PKCS7_verify_sid_binding), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PKCS7_verify_degenerate), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PKCS7_SIGNED_new), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PEM_write_bio_PKCS7), \
|
||||
TEST_DECL_GROUP("ossl_p7", test_wolfSSL_PEM_write_bio_encryptedKey), \
|
||||
|
||||
@@ -1507,6 +1507,187 @@ int test_X509_verify_cert_untrusted_inter(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \
|
||||
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \
|
||||
!defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \
|
||||
!defined(NO_ASN_TIME)
|
||||
/* Build a CA:TRUE intermediate signed by the 2048-bit test root
|
||||
* (ca_cert_der_2048 / ca_key_der_2048). keyUsage == NULL omits the KeyUsage
|
||||
* extension entirely. Returns the DER length, or <= 0 on failure. */
|
||||
static int gen_ca_int_keyusage(byte* out, int outMax, RsaKey* subjKey,
|
||||
RsaKey* caKey, WC_RNG* rng, const char* cn, const char* keyUsage)
|
||||
{
|
||||
Cert cert;
|
||||
|
||||
if (wc_InitCert(&cert) != 0)
|
||||
return -1;
|
||||
cert.isCA = 1;
|
||||
cert.sigType = CTC_SHA256wRSA;
|
||||
XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1);
|
||||
XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1);
|
||||
XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1);
|
||||
if (wc_SetSubjectKeyIdFromPublicKey(&cert, subjKey, NULL) != 0)
|
||||
return -1;
|
||||
if (wc_SetAuthKeyIdFromCert(&cert, ca_cert_der_2048,
|
||||
(int)sizeof_ca_cert_der_2048) != 0)
|
||||
return -1;
|
||||
if (keyUsage != NULL && wc_SetKeyUsage(&cert, keyUsage) != 0)
|
||||
return -1;
|
||||
if (wc_SetIssuerBuffer(&cert, ca_cert_der_2048,
|
||||
(int)sizeof_ca_cert_der_2048) != 0)
|
||||
return -1;
|
||||
if (wc_MakeCert(&cert, out, (word32)outMax, subjKey, NULL, rng) < 0)
|
||||
return -1;
|
||||
return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, caKey,
|
||||
NULL, rng);
|
||||
}
|
||||
|
||||
/* Build a leaf signed by the given intermediate (its DER + private key). */
|
||||
static int gen_leaf_under_int(byte* out, int outMax, RsaKey* leafKey,
|
||||
const byte* issuerDer, int issuerDerSz, RsaKey* issuerKey, WC_RNG* rng,
|
||||
const char* cn)
|
||||
{
|
||||
Cert cert;
|
||||
|
||||
if (wc_InitCert(&cert) != 0)
|
||||
return -1;
|
||||
cert.isCA = 0;
|
||||
cert.sigType = CTC_SHA256wRSA;
|
||||
XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1);
|
||||
XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1);
|
||||
XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1);
|
||||
if (wc_SetSubjectKeyIdFromPublicKey(&cert, leafKey, NULL) != 0)
|
||||
return -1;
|
||||
if (wc_SetAuthKeyIdFromCert(&cert, issuerDer, issuerDerSz) != 0)
|
||||
return -1;
|
||||
if (wc_SetKeyUsage(&cert, "digitalSignature") != 0)
|
||||
return -1;
|
||||
if (wc_SetIssuerBuffer(&cert, issuerDer, issuerDerSz) != 0)
|
||||
return -1;
|
||||
if (wc_MakeCert(&cert, out, (word32)outMax, leafKey, NULL, rng) < 0)
|
||||
return -1;
|
||||
return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax,
|
||||
issuerKey, NULL, rng);
|
||||
}
|
||||
|
||||
/* Verify "leaf <- intermediate <- root(ca-cert)" where the intermediate is
|
||||
* supplied only as an untrusted candidate. Returns the X509_verify_cert()
|
||||
* result (1 verified, 0 rejected) via *verifyRet. */
|
||||
static int run_int_keyusage_case(const byte* intDer, int intSz,
|
||||
const byte* leafDer, int leafSz, X509* root, int* verifyRet)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
X509* inter = NULL;
|
||||
X509* leaf = NULL;
|
||||
X509_STORE* store = NULL;
|
||||
X509_STORE_CTX* ctx = NULL;
|
||||
STACK_OF(X509)* untrusted = NULL;
|
||||
const byte* p;
|
||||
|
||||
p = intDer;
|
||||
ExpectNotNull(inter = d2i_X509(NULL, &p, intSz));
|
||||
p = leafDer;
|
||||
ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz));
|
||||
ExpectNotNull(store = X509_STORE_new());
|
||||
ExpectIntEQ(X509_STORE_add_cert(store, root), 1);
|
||||
ExpectNotNull(untrusted = sk_X509_new_null());
|
||||
ExpectIntGT(sk_X509_push(untrusted, inter), 0);
|
||||
ExpectNotNull(ctx = X509_STORE_CTX_new());
|
||||
ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1);
|
||||
if (verifyRet != NULL)
|
||||
*verifyRet = X509_verify_cert(ctx);
|
||||
X509_STORE_CTX_free(ctx);
|
||||
X509_STORE_free(store);
|
||||
sk_X509_free(untrusted);
|
||||
X509_free(leaf);
|
||||
X509_free(inter);
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Regression: a chain-supplied (untrusted) intermediate that is CA:TRUE but
|
||||
* whose KeyUsage extension does NOT assert keyCertSign must NOT be usable to
|
||||
* sign the leaf - RFC 5280 4.2.1.3. Previously such an intermediate, added as
|
||||
* a temporary CA during path building, was accepted as a signing CA.
|
||||
*
|
||||
* Conversely, an intermediate with NO KeyUsage extension implies all usages
|
||||
* (including keyCertSign) and must still verify - the fix must not over-reject
|
||||
* those. */
|
||||
int test_X509_verify_cert_ca_no_keycertsign(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \
|
||||
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \
|
||||
!defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \
|
||||
!defined(NO_ASN_TIME)
|
||||
WC_RNG rng;
|
||||
RsaKey caKey, intKey, leafKey;
|
||||
int rngI = 0, caI = 0, intI = 0, leafI = 0;
|
||||
word32 idx;
|
||||
byte* intDer = NULL;
|
||||
byte* leafDer = NULL;
|
||||
int intSz = 0, leafSz = 0;
|
||||
int verifyRet = -1;
|
||||
const byte* p;
|
||||
X509* root = NULL;
|
||||
|
||||
intDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
ExpectNotNull(intDer);
|
||||
ExpectNotNull(leafDer);
|
||||
|
||||
ExpectIntEQ(wc_InitRng(&rng), 0);
|
||||
if (EXPECT_SUCCESS()) rngI = 1;
|
||||
ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0);
|
||||
if (EXPECT_SUCCESS()) caI = 1;
|
||||
idx = 0;
|
||||
ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey,
|
||||
sizeof_ca_key_der_2048), 0);
|
||||
ExpectIntEQ(wc_InitRsaKey(&intKey, NULL), 0);
|
||||
if (EXPECT_SUCCESS()) intI = 1;
|
||||
idx = 0;
|
||||
ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &intKey,
|
||||
sizeof_server_key_der_2048), 0);
|
||||
ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0);
|
||||
if (EXPECT_SUCCESS()) leafI = 1;
|
||||
idx = 0;
|
||||
ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey,
|
||||
sizeof_client_key_der_2048), 0);
|
||||
|
||||
p = ca_cert_der_2048;
|
||||
ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048));
|
||||
|
||||
/* Case 1: intermediate CA WITHOUT keyCertSign -> verification must fail. */
|
||||
ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey,
|
||||
&rng, "No keyCertSign Intermediate", "digitalSignature")), 0);
|
||||
ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey,
|
||||
intDer, intSz, &intKey, &rng, "Leaf under bad int")), 0);
|
||||
verifyRet = -1;
|
||||
ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root,
|
||||
&verifyRet), 1);
|
||||
ExpectIntNE(verifyRet, 1);
|
||||
|
||||
/* Case 2: intermediate CA with NO KeyUsage extension -> must verify. */
|
||||
ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey,
|
||||
&rng, "No KeyUsage Intermediate", NULL)), 0);
|
||||
ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey,
|
||||
intDer, intSz, &intKey, &rng, "Leaf under noKU int")), 0);
|
||||
verifyRet = -1;
|
||||
ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root,
|
||||
&verifyRet), 1);
|
||||
ExpectIntEQ(verifyRet, 1);
|
||||
|
||||
X509_free(root);
|
||||
if (rngI) wc_FreeRng(&rng);
|
||||
if (caI) wc_FreeRsaKey(&caKey);
|
||||
if (intI) wc_FreeRsaKey(&intKey);
|
||||
if (leafI) wc_FreeRsaKey(&leafKey);
|
||||
XFREE(intDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM)
|
||||
static int test_X509_STORE_untrusted_load_cert_to_stack(const char* filename,
|
||||
STACK_OF(X509)* chain)
|
||||
|
||||
@@ -30,6 +30,7 @@ int test_wolfSSL_X509_STORE_CTX_get0_store(void);
|
||||
int test_wolfSSL_X509_STORE_CTX(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_ex(void);
|
||||
int test_X509_verify_cert_untrusted_inter(void);
|
||||
int test_X509_verify_cert_ca_no_keycertsign(void);
|
||||
int test_X509_STORE_untrusted(void);
|
||||
int test_X509_STORE_InvalidCa(void);
|
||||
int test_X509_STORE_InvalidCa_NoCallback(void);
|
||||
@@ -53,6 +54,8 @@ int test_wolfSSL_CTX_set_cert_store(void);
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX_ex), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_untrusted_inter), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", \
|
||||
test_X509_verify_cert_ca_no_keycertsign), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_untrusted), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa_NoCallback), \
|
||||
|
||||
@@ -2751,6 +2751,143 @@ int test_tls13_rpk_handshake(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Regression: a peer must not present a raw public key (RPK) that was never
|
||||
* negotiated. Neither side calls set_client/server_cert_type, so RPK is not
|
||||
* negotiated and the default type is X.509; a received bare key must be
|
||||
* rejected instead of accepted without any chain verification (auth bypass).
|
||||
* Covers both directions: server presenting an RPK to the client, and client
|
||||
* presenting an RPK to the server. */
|
||||
int test_tls13_rpk_handshake_no_negotiation(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(HAVE_RPK) && defined(WOLFSSL_TLS13) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
int tp = 0;
|
||||
|
||||
/* Direction 1: server loads an RPK cert, client is a plain X.509 client. */
|
||||
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);
|
||||
|
||||
/* Handshake must fail and the client must not record RPK as negotiated. */
|
||||
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl_c, &tp),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(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;
|
||||
|
||||
/* Direction 2: client loads an RPK cert and the server requests client
|
||||
* auth (VERIFY_PEER, set in the helper). The server expects X.509 and must
|
||||
* reject the client's un-negotiated bare key. */
|
||||
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);
|
||||
|
||||
/* Handshake must fail and the server must not record RPK as negotiated. */
|
||||
ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl_s, &tp),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntNE(tp, WOLFSSL_CERT_TYPE_RPK);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* Post-handshake authentication (PHA) positive guard. A server configured with
|
||||
* WOLFSSL_VERIFY_POST_HANDSHAKE must complete the initial handshake WITHOUT a
|
||||
* client certificate (verification is deferred) and then be able to request one
|
||||
* post-handshake. This guards the property the auth-bypass fix must preserve:
|
||||
* the missing-certificate exemption stays in force while no post-handshake
|
||||
* request is outstanding (certReqCtx == NULL). If the fix wrongly treated the
|
||||
* initial handshake as a pending PHA request, the handshake below would fail.
|
||||
*
|
||||
* Scope: this is a positive guard only.
|
||||
* - The bypass itself is NOT reproduced here: the
|
||||
* SanityCheckTls13MsgReceived / DoTls13Finished branches the fix re-enables
|
||||
* only fire when a client sends a Finished with NO Certificate message at all
|
||||
* (got_certificate == 0). A conformant wolfSSL client always sends at least
|
||||
* an empty Certificate, so reproducing the bypass needs a non-conformant
|
||||
* client; the report used a state-machine model. The negative direction
|
||||
* rests on code review.
|
||||
* - Driving the full post-handshake certificate exchange to completion is
|
||||
* intentionally not asserted: whether the peer chain ends up populated
|
||||
* depends on build options unrelated to this fix (it differs between
|
||||
* --enable-all and the user_settings_all header build), so it is not a
|
||||
* portable assertion. */
|
||||
int test_tls13_pha(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
|
||||
defined(WOLFSSL_POST_HANDSHAKE_AUTH) && defined(SESSION_CERTS) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \
|
||||
!defined(NO_RSA) && !defined(NO_CERTS)
|
||||
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
|
||||
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
|
||||
struct test_memio_ctx test_ctx;
|
||||
WOLFSSL_X509_CHAIN* chain = 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: trust the (self-signed) client certificate and defer
|
||||
* verification to post-handshake. */
|
||||
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, cliCertFile, NULL),
|
||||
WOLFSSL_SUCCESS);
|
||||
wolfSSL_set_verify(ssl_s,
|
||||
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_POST_HANDSHAKE, NULL);
|
||||
|
||||
/* Client: load a cert/key and advertise post-handshake auth. */
|
||||
ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile,
|
||||
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile,
|
||||
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_allow_post_handshake_auth(ssl_c), 0);
|
||||
|
||||
/* Initial handshake must complete even though no client cert was sent -
|
||||
* the verifyPostHandshake exemption (certReqCtx == NULL) is intact. */
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
|
||||
ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s));
|
||||
ExpectIntEQ(wolfSSL_get_chain_count(chain), 0);
|
||||
|
||||
/* And the server can issue a post-handshake certificate request. */
|
||||
ExpectIntEQ(wolfSSL_request_certificate(ssl_s), WOLFSSL_SUCCESS);
|
||||
|
||||
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_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \
|
||||
defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
|
||||
|
||||
@@ -28,6 +28,8 @@ int test_tls13_apis(void);
|
||||
int test_tls13_cipher_suites(void);
|
||||
int test_tls13_bad_psk_binder(void);
|
||||
int test_tls13_rpk_handshake(void);
|
||||
int test_tls13_rpk_handshake_no_negotiation(void);
|
||||
int test_tls13_pha(void);
|
||||
int test_tls13_pq_groups(void);
|
||||
int test_tls13_multi_pqc_key_share(void);
|
||||
int test_tls13_early_data(void);
|
||||
@@ -88,6 +90,8 @@ int test_tls13_AEAD_limit_KU_aes128_ccm_8_sha256(void);
|
||||
TEST_DECL_GROUP("tls13", test_tls13_cipher_suites), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_bad_psk_binder), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_rpk_handshake), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_rpk_handshake_no_negotiation), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_pha), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_pq_groups), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_multi_pqc_key_share), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_early_data), \
|
||||
|
||||
@@ -96378,7 +96378,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -124117,7 +124117,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 17);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -124158,7 +124158,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -65945,7 +65945,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -110680,7 +110680,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 9);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -110721,7 +110721,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -114511,7 +114511,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -128390,7 +128390,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 17);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -128431,7 +128431,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -32973,7 +32973,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -40644,7 +40644,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 21);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -40685,7 +40685,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -33026,7 +33026,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -40025,7 +40025,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 9);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -40066,7 +40066,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -50559,7 +50559,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -63136,7 +63136,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
SP_DECL_VAR(sp_digit, k, 17);
|
||||
int err = MP_OKAY;
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -63177,7 +63177,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
@@ -48834,7 +48834,7 @@ int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 48U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -89503,7 +89503,7 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
||||
word32 cpuid_flags = cpuid_get_flags();
|
||||
#endif
|
||||
|
||||
if (*outLen < 65U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -89552,7 +89552,7 @@ int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
||||
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
||||
(void)sizeof(ctx_size_test);
|
||||
|
||||
if (*outLen < 32U) {
|
||||
if (*outLen < 66U) {
|
||||
err = BUFFER_E;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user