Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6b65490
F-6559 - Reject certs with critical policyConstraints/inhibitAnyPolicy
aidangarske Jul 10, 2026
764c974
F-6731 - ForceZero PreSharedKey identity holding resumption secret be…
aidangarske Jul 10, 2026
a58610c
F-6730 - Use DTLS-aware header size for ECH inner ClientHello buffer
aidangarske Jul 10, 2026
d27f08a
F-6723 - Silently discard ChangeCipherSpec records on DTLS 1.3
aidangarske Jul 10, 2026
c0361a1
F-6711 - Publish bn_one via atomic compare-exchange to fix init race
aidangarske Jul 10, 2026
0b7c603
F-4112 - Map check_cert_key errors to failure in dual-alg check_priva…
aidangarske Jul 10, 2026
83d0078
F-4111 - NULL-check ssl in wolfSSL_get_ocsp_producedDate accessors
aidangarske Jul 10, 2026
5275012
F-6328 - Fix mis-gated key->dp NULL check in wc_BuildEccKeyDer
aidangarske Jul 10, 2026
3243436
F-6704 - Free WOLFSSL_X509 on CopyDecodedToX509 failure in X509_STORE…
aidangarske Jul 10, 2026
1fc1050
F-6705 - Log peerCert copy failure only on actual failure
aidangarske Jul 10, 2026
2184958
F-5585 - Take cert ownership after incorporation to avoid double-free
aidangarske Jul 10, 2026
f85e570
F-6712 - Guard gDrbgDefCtx lazy init/free with globalRNGMutex
aidangarske Jul 10, 2026
f416cfe
F-5625 - Cap BIO file read at MAX_WOLFSSL_FILE_SIZE
aidangarske Jul 10, 2026
1e45969
F-6557 - Lock ticket key/expiry read against concurrent regeneration
aidangarske Jul 10, 2026
4404b0c
F-5729 - Guard PKCS7 streaming content size against word32 overflow
aidangarske Jul 10, 2026
463a010
F-6708 - Honor verify callback rejection in X509StoreVerifyCert
aidangarske Jul 10, 2026
0b4f44d
F-4154 - Zero ML-KEM key struct so unconditional free is safe
aidangarske Jul 10, 2026
50594a9
F-4155 - Add INT_MAX guard on plainlen/aadlen in quic_aead_encrypt
aidangarske Jul 10, 2026
86fdfa1
F-5755 - Add INT_MAX guard on aadlen in quic_aead_decrypt
aidangarske Jul 10, 2026
23013f3
F-5859 - Add INT_MAX guards on secretlen/infolen in quic_hkdf_expand
aidangarske Jul 10, 2026
16a28a3
F-5860 - Add INT_MAX guards on saltlen/secretlen/infolen in quic_hkdf
aidangarske Jul 10, 2026
567aa3a
F-6523 - Read remaining length (fcur) not total (flen) in d2i_OCSP_RE…
aidangarske Jul 10, 2026
b855a2f
F-5626 - Reject out-of-range port in wolfSSL_BIO_new_connect
aidangarske Jul 10, 2026
4bc24ee
F-3886 - NULL-check ssl and validate depth in wolfSSL_set_verify_depth
aidangarske Jul 10, 2026
9c65f9c
F-4149 - ForceZero MD5 CertVerify digest scratch buffer
aidangarske Jul 10, 2026
9928a24
F-4150 - ForceZero SHA CertVerify digest scratch buffer
aidangarske Jul 10, 2026
16b29e6
F-4616 - ForceZero MD5 SSLv3 Finished digest scratch buffer
aidangarske Jul 10, 2026
dac9ec3
F-4617 - ForceZero SHA SSLv3 Finished digest scratch buffer
aidangarske Jul 10, 2026
ed421d7
F-1842 - ForceZero assembled 3DES key in wolfSSL_DES_ede3_cbc_encrypt
aidangarske Jul 10, 2026
84b3b8d
F-6729 - Reject un-offered certificate type selected by peer
aidangarske Jul 10, 2026
2c08392
F-6303 - Bounds-check ato24 reads in sniffer ProcessCertificate
aidangarske Jul 10, 2026
2b38507
F-6712 - Skip globalRNGMutex lock when unavailable during cleanup
aidangarske Jul 10, 2026
418edd3
F-6559 - Gate critical policyConstraints test to strict-ASN builds
aidangarske Jul 10, 2026
9d0aee4
F-6559 - Backdate policyConstraints test cert so only critical-ext re…
aidangarske Jul 10, 2026
61b23ce
F-6708 - Make verify callback rejection terminal to prevent second-pa…
aidangarske Jul 10, 2026
42da053
6559 - Expect critical inhibitAnyPolicy rejection in cert_test
aidangarske Jul 15, 2026
ec45a2f
Guard gDrbgDefCtx access on lock success in FIPS DRBG helpers
aidangarske Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
if (bio) {
const char* port;
int portVal = 0;
#ifdef WOLFSSL_IPV6
const char* ipv6Start = XSTRSTR(str, "[");
const char* ipv6End = XSTRSTR(str, "]");
Expand All @@ -2466,8 +2467,13 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
#endif
port = XSTRSTR(str, ":");

if (port != NULL)
bio->port = (word16)XATOI(port + 1);
if (port != NULL) {
portVal = XATOI(port + 1);
/* Reject out-of-range ports instead of truncating to word16. */
if ((portVal < 0) || (portVal > 65535))
portVal = 0;
bio->port = (word16)portVal;
}
else
port = str + XSTRLEN(str); /* point to null terminator */

Expand Down
31 changes: 30 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -12945,6 +12945,8 @@ static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
}
}

ForceZero(md5_result, WC_MD5_DIGEST_SIZE);

WC_FREE_VAR_EX(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);

return ret;
Expand Down Expand Up @@ -12990,6 +12992,8 @@ static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
}
}

ForceZero(sha_result, WC_SHA_DIGEST_SIZE);

WC_FREE_VAR_EX(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);

return ret;
Expand Down Expand Up @@ -15433,7 +15437,7 @@ int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt,
if (args->certIdx == 0) {
FreeX509(&ssl->peerCert);
InitX509(&ssl->peerCert, 0, ssl->heap);
if (CopyDecodedToX509(&ssl->peerCert, args->dCert) == 0)
if (CopyDecodedToX509(&ssl->peerCert, args->dCert) != 0)
WOLFSSL_MSG("Unable to copy to ssl->peerCert");
store->current_cert = &ssl->peerCert; /* use existing X509 */
}
Expand Down Expand Up @@ -23949,6 +23953,14 @@ static int CheckResumptionConsistency(WOLFSSL* ssl)
static int DoChangeCipherSpecTls13(WOLFSSL* ssl)
{
word32 i = ssl->buffers.inputBuffer.idx;
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
/* CCS is not part of DTLS 1.3; discard the record without alerting so a
* spoofed CCS cannot tear down the handshake. */
ssl->buffers.inputBuffer.idx += ssl->curSize;
return 0;
}
#endif
if (ssl->options.handShakeState == HANDSHAKE_DONE) {
SendAlert(ssl, alert_fatal, unexpected_message);
WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE);
Expand Down Expand Up @@ -25437,6 +25449,8 @@ static int BuildMD5_CertVerify(const WOLFSSL* ssl, byte* digest)
}
}

ForceZero(md5_result, WC_MD5_DIGEST_SIZE);

WC_FREE_VAR_EX(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);

return ret;
Expand Down Expand Up @@ -25483,6 +25497,8 @@ static int BuildSHA_CertVerify(const WOLFSSL* ssl, byte* digest)
}
}

ForceZero(sha_result, WC_SHA_DIGEST_SIZE);

WC_FREE_VAR_EX(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);

return ret;
Expand Down Expand Up @@ -42863,15 +42879,28 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
/* Update AAD with index. */
aad[WOLFSSL_TICKET_NAME_SZ - 1] |= keyIdx;

#ifndef SINGLE_THREADED
/* Hold the lock over the key/expiry read so a concurrent regen can't swap the key mid-decrypt. */
if (wc_LockMutex(&keyCtx->mutex) != 0) {
WOLFSSL_MSG("Couldn't lock key context mutex");
return WOLFSSL_TICKET_RET_REJECT;
}
#endif
/* Check expirary */
if (keyCtx->expirary[keyIdx] <= LowResTimer()) {
#ifndef SINGLE_THREADED
wc_UnLockMutex(&keyCtx->mutex);
#endif
return WOLFSSL_TICKET_RET_REJECT;
}

/* Decrypt ticket data. */
ret = TicketEncDec(keyCtx->key[keyIdx], WOLFSSL_TICKET_KEY_SZ, iv, aad,
aadSz, ticket, inLen, ticket, outLen, mac, ssl->heap,
0);
#ifndef SINGLE_THREADED
wc_UnLockMutex(&keyCtx->mutex);
#endif
if (ret != 0) {
return WOLFSSL_TICKET_RET_REJECT;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
return NULL;
dataAlloced = 1;

len = wolfSSL_BIO_read(bio, (char *)data, (int)flen);
len = wolfSSL_BIO_read(bio, (char *)data, (int)fcur);
}
#endif
else
Expand Down
16 changes: 15 additions & 1 deletion src/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,11 @@ int wolfSSL_quic_hkdf_expand(uint8_t* dest, size_t destlen,

WOLFSSL_ENTER("wolfSSL_quic_hkdf_expand");

if (secretlen > INT_MAX || infolen > INT_MAX) {
ret = WOLFSSL_FAILURE;
goto cleanup;
}

pctx = wolfSSL_EVP_PKEY_CTX_new_id(WC_NID_hkdf, NULL);
if (pctx == NULL) {
ret = WOLFSSL_FAILURE;
Expand Down Expand Up @@ -1279,6 +1284,11 @@ int wolfSSL_quic_hkdf(uint8_t* dest, size_t destlen,

WOLFSSL_ENTER("wolfSSL_quic_hkdf");

if (secretlen > INT_MAX || saltlen > INT_MAX || infolen > INT_MAX) {
ret = WOLFSSL_FAILURE;
goto cleanup;
}

pctx = wolfSSL_EVP_PKEY_CTX_new_id(WC_NID_hkdf, NULL);
if (pctx == NULL) {
ret = WOLFSSL_FAILURE;
Expand Down Expand Up @@ -1348,6 +1358,10 @@ int wolfSSL_quic_aead_encrypt(uint8_t* dest, WOLFSSL_EVP_CIPHER_CTX* ctx,
* TODO: there is some fiddling in OpenSSL+quic in regard to CCM ciphers
* which we need to check.
*/
if (plainlen > INT_MAX || aadlen > INT_MAX) {
return WOLFSSL_FAILURE;
}

if (wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, 1) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_CipherUpdate(
ctx, NULL, &len, aad, (int)aadlen) != WOLFSSL_SUCCESS
Expand All @@ -1373,7 +1387,7 @@ int wolfSSL_quic_aead_decrypt(uint8_t* dest, WOLFSSL_EVP_CIPHER_CTX* ctx,
const uint8_t* tag;

/* See rationale for wolfSSL_quic_aead_encrypt() on why this is here */
if (enclen > INT_MAX || ctx->authTagSz > (int)enclen) {
if (enclen > INT_MAX || aadlen > INT_MAX || ctx->authTagSz > (int)enclen) {
return WOLFSSL_FAILURE;
}

Expand Down
8 changes: 8 additions & 0 deletions src/sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4494,6 +4494,10 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
}
#endif

if (OPAQUE24_LEN > *sslBytes) {
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
ato24(input, &certChainSz);
*sslBytes -= CERT_HEADER_SZ;
input += CERT_HEADER_SZ;
Expand All @@ -4503,6 +4507,10 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
return WOLFSSL_FATAL_ERROR;
}

if (OPAQUE24_LEN > *sslBytes) {
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
ato24(input, &certSz);
input += OPAQUE24_LEN;
if (*sslBytes < (int)certSz) {
Expand Down
40 changes: 35 additions & 5 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -7810,7 +7810,13 @@ void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
{
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
WOLFSSL_ENTER("wolfSSL_set_verify_depth");
ssl->options.verifyDepth = (byte)depth;
/* Reject out-of-range depths; valid range is 0 to MAX_CHAIN_DEPTH. */
if ((ssl == NULL) || (depth < 0) || (depth > MAX_CHAIN_DEPTH)) {
WOLFSSL_MSG("Bad depth argument, too large or less than 0");
}
else {
ssl->options.verifyDepth = (byte)depth;
}
#endif
}

Expand Down Expand Up @@ -10533,20 +10539,44 @@ int wolfSSL_FIPS_drbg_uninstantiate(WOLFSSL_DRBG_CTX *ctx)
void wolfSSL_FIPS_drbg_free(WOLFSSL_DRBG_CTX *ctx)
{
if (ctx != NULL) {
int locked = 0;
int haveMutex = 1;
/* As safety check if free'ing the default drbg, then mark global NULL.
* Technically the user should not call free on the default drbg. */
if (ctx == gDrbgDefCtx) {
gDrbgDefCtx = NULL;
#ifndef WOLFSSL_MUTEX_INITIALIZER
/* wolfSSL_Cleanup may free the mutex before this runs. */
haveMutex = (globalRNGMutex_valid == 1);
#endif
if (haveMutex && (wc_LockMutex(&globalRNGMutex) == 0))
locked = 1;
/* Touch the global under the lock, or unlocked only when no mutex. */
if (locked || !haveMutex) {
if (ctx == gDrbgDefCtx) {
gDrbgDefCtx = NULL;
}
}
if (locked)
wc_UnLockMutex(&globalRNGMutex);
wolfSSL_FIPS_drbg_uninstantiate(ctx);
XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
WOLFSSL_DRBG_CTX* wolfSSL_FIPS_get_default_drbg(void)
{
if (gDrbgDefCtx == NULL) {
gDrbgDefCtx = wolfSSL_FIPS_drbg_new(0, 0);
int locked = 0;
int haveMutex = 1;
#ifndef WOLFSSL_MUTEX_INITIALIZER
haveMutex = (globalRNGMutex_valid == 1);
#endif
if (haveMutex && (wc_LockMutex(&globalRNGMutex) == 0))
locked = 1;
if (locked || !haveMutex) {
if (gDrbgDefCtx == NULL) {
gDrbgDefCtx = wolfSSL_FIPS_drbg_new(0, 0);
}
}
if (locked)
wc_UnLockMutex(&globalRNGMutex);
return gDrbgDefCtx;
}
void wolfSSL_FIPS_get_timevec(unsigned char* buf, unsigned long* pctr)
Expand Down
6 changes: 6 additions & 0 deletions src/ssl_api_crl_ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,9 @@ int wolfSSL_get_ocsp_producedDate(
size_t producedDate_space,
int *producedDateFormat)
{
if (ssl == NULL)
return BAD_FUNC_ARG;

if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
(ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
return BAD_FUNC_ARG;
Expand All @@ -415,6 +418,9 @@ int wolfSSL_get_ocsp_producedDate(
int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
int idx = 0;

if (ssl == NULL)
return BAD_FUNC_ARG;

if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
(ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
return BAD_FUNC_ARG;
Expand Down
2 changes: 1 addition & 1 deletion src/ssl_api_pk.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
res = check_cert_key(ctx->certificate, privateKey, altPrivateKey,
ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel,
ctx->privateKeyId, ctx->altPrivateKeyDevId,
ctx->altPrivateKeyLabel, ctx->altPrivateKeyId) != 0;
ctx->altPrivateKeyLabel, ctx->altPrivateKeyId) == 1;
}
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
/* Dispose of the unblinded buffers. */
Expand Down
24 changes: 11 additions & 13 deletions src/ssl_bn.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,23 +326,21 @@ const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void)
wolfSSL_BN_free(one);
one = NULL;
}
else
else {
#ifndef SINGLE_THREADED
/* Ensure global has not been set by another thread. */
if (bn_one == NULL)
#endif
{
void* expected = NULL;
/* Publish atomically so a losing thread frees only its own object,
* never a pointer already handed to another thread. */
if (!wolfSSL_Atomic_Ptr_CompareExchange((void* volatile*)&bn_one,
&expected, one)) {
wolfSSL_BN_free(one);
one = (WOLFSSL_BIGNUM*)expected;
}
#else
/* Set this big number as the global. */
bn_one = one;
}
#ifndef SINGLE_THREADED
/* Check if another thread has set the global. */
if (bn_one != one) {
/* Dispose of this big number and return the global. */
wolfSSL_BN_free(one);
one = bn_one;
}
#endif
}
}

return one;
Expand Down
2 changes: 2 additions & 0 deletions src/ssl_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2880,6 +2880,8 @@ void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input,
}
}
wc_Des3Free(des3);

ForceZero(key, DES3_KEY_SIZE);
}

WC_FREE_VAR_EX(des3, NULL, DYNAMIC_TYPE_CIPHER);
Expand Down
5 changes: 5 additions & 0 deletions src/ssl_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data)

/* Update total read. */
ret += sz;
/* Cap total like the direct-file path to avoid int overflow. */
if (ret > MAX_WOLFSSL_FILE_SIZE) {
sz = BUFFER_E;
break;
}
/* Calculate remaining unused memory. */
remaining = READ_BIO_FILE_CHUNK - (ret % READ_BIO_FILE_CHUNK);
/* Check for space remaining. */
Expand Down
8 changes: 4 additions & 4 deletions src/ssl_p7p12.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
{
int ret;
WOLFSSL_PKCS7* p7;
WOLFSSL_STACK* certHead = certs;
WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs");

if (!pkcs7 || !certs || !out) {
Expand All @@ -912,10 +913,6 @@ int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,

p7 = (WOLFSSL_PKCS7*)pkcs7;

/* take ownership of certs */
p7->certs = certs;
/* TODO: takes ownership even on failure below but not on above failure. */

if (pkcs7->certList) {
WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same "
"struct");
Expand Down Expand Up @@ -957,6 +954,9 @@ int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
certs = certs->next;
}

/* certs are now incorporated into pkcs7; take ownership (earlier failures leave ownership with the caller). */
p7->certs = certHead;

if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) {
WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error");
return WOLFSSL_FAILURE;
Expand Down
Loading
Loading