Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d3f9e9d
F-6559 - Reject certs with critical policyConstraints/inhibitAnyPolicy
aidangarske Jul 10, 2026
cb95598
F-6731 - ForceZero PreSharedKey identity holding resumption secret be…
aidangarske Jul 10, 2026
010b72d
F-6730 - Use DTLS-aware header size for ECH inner ClientHello buffer
aidangarske Jul 10, 2026
2b7a4eb
F-6723 - Silently discard ChangeCipherSpec records on DTLS 1.3
aidangarske Jul 10, 2026
bde3f77
F-6711 - Publish bn_one via atomic compare-exchange to fix init race
aidangarske Jul 10, 2026
61f3b88
F-4112 - Map check_cert_key errors to failure in dual-alg check_priva…
aidangarske Jul 10, 2026
ce7b94c
F-4111 - NULL-check ssl in wolfSSL_get_ocsp_producedDate accessors
aidangarske Jul 10, 2026
39c7639
F-6328 - Fix mis-gated key->dp NULL check in wc_BuildEccKeyDer
aidangarske Jul 10, 2026
44b3f1a
F-6704 - Free WOLFSSL_X509 on CopyDecodedToX509 failure in X509_STORE…
aidangarske Jul 10, 2026
356fdf2
F-6705 - Log peerCert copy failure only on actual failure
aidangarske Jul 10, 2026
e720f36
F-5585 - Take cert ownership after incorporation to avoid double-free
aidangarske Jul 10, 2026
00c38cd
F-6712 - Guard gDrbgDefCtx lazy init/free with globalRNGMutex
aidangarske Jul 10, 2026
fa1b6ca
F-5625 - Cap BIO file read at MAX_WOLFSSL_FILE_SIZE
aidangarske Jul 10, 2026
eac4c97
F-6557 - Lock ticket key/expiry read against concurrent regeneration
aidangarske Jul 10, 2026
b6bbbfa
F-5729 - Guard PKCS7 streaming content size against word32 overflow
aidangarske Jul 10, 2026
b6cd139
F-6708 - Honor verify callback rejection in X509StoreVerifyCert
aidangarske Jul 10, 2026
f53288d
F-4154 - Zero ML-KEM key struct so unconditional free is safe
aidangarske Jul 10, 2026
bc68c89
F-4155 - Add INT_MAX guard on plainlen/aadlen in quic_aead_encrypt
aidangarske Jul 10, 2026
772e0a6
F-5755 - Add INT_MAX guard on aadlen in quic_aead_decrypt
aidangarske Jul 10, 2026
79ffdf3
F-5859 - Add INT_MAX guards on secretlen/infolen in quic_hkdf_expand
aidangarske Jul 10, 2026
12955ca
F-5860 - Add INT_MAX guards on saltlen/secretlen/infolen in quic_hkdf
aidangarske Jul 10, 2026
b40a9f5
F-6523 - Read remaining length (fcur) not total (flen) in d2i_OCSP_RE…
aidangarske Jul 10, 2026
81f8ec2
F-5626 - Reject out-of-range port in wolfSSL_BIO_new_connect
aidangarske Jul 10, 2026
0f86261
F-3886 - NULL-check ssl and validate depth in wolfSSL_set_verify_depth
aidangarske Jul 10, 2026
6ef9692
F-4149 - ForceZero MD5 CertVerify digest scratch buffer
aidangarske Jul 10, 2026
c9f6793
F-4150 - ForceZero SHA CertVerify digest scratch buffer
aidangarske Jul 10, 2026
2b7f6a7
F-4616 - ForceZero MD5 SSLv3 Finished digest scratch buffer
aidangarske Jul 10, 2026
aaba9a2
F-4617 - ForceZero SHA SSLv3 Finished digest scratch buffer
aidangarske Jul 10, 2026
a512c78
F-1839 - ForceZero entropy seed in wolfSSL_RAND_pseudo_bytes
aidangarske Jul 10, 2026
687c9ea
F-1842 - ForceZero assembled 3DES key in wolfSSL_DES_ede3_cbc_encrypt
aidangarske Jul 10, 2026
b2aa338
F-6729 - Reject un-offered certificate type selected by peer
aidangarske Jul 10, 2026
e2a52ab
F-6303 - Bounds-check ato24 reads in sniffer ProcessCertificate
aidangarske Jul 10, 2026
283834e
F-6712 - Skip globalRNGMutex lock when unavailable during cleanup
aidangarske Jul 10, 2026
b7ca353
F-6559 - Gate critical policyConstraints test to strict-ASN builds
aidangarske Jul 10, 2026
a5c2508
F-6559 - Backdate policyConstraints test cert so only critical-ext re…
aidangarske Jul 10, 2026
9d19430
F-6708 - Make verify callback rejection terminal to prevent second-pa…
aidangarske Jul 10, 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 @@ -12867,6 +12867,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 @@ -12912,6 +12914,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 @@ -15355,7 +15359,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 @@ -23775,6 +23779,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 @@ -25226,6 +25238,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 @@ -25272,6 +25286,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 @@ -42548,15 +42564,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 @@ -1159,7 +1159,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 @@ -4482,6 +4482,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 @@ -4491,6 +4495,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
28 changes: 27 additions & 1 deletion src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -12361,7 +12361,13 @@ void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl)
{
#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 @@ -16065,6 +16071,7 @@ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num)
(void)hash;
(void)secret;
#endif
ForceZero(secret, DRBG_SEED_LEN);
return ret;
}

Expand Down Expand Up @@ -16939,20 +16946,39 @@ int wolfSSL_FIPS_drbg_uninstantiate(WOLFSSL_DRBG_CTX *ctx)
void wolfSSL_FIPS_drbg_free(WOLFSSL_DRBG_CTX *ctx)
{
if (ctx != NULL) {
int locked = 0;
/* As safety check if free'ing the default drbg, then mark global NULL.
* Technically the user should not call free on the default drbg. */
#ifndef WOLFSSL_MUTEX_INITIALIZER
/* wolfSSL_Cleanup may free the mutex before this runs. */
if ((globalRNGMutex_valid == 1) && (wc_LockMutex(&globalRNGMutex) == 0))
#else
if (wc_LockMutex(&globalRNGMutex) == 0)
#endif
locked = 1;
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)
{
int locked = 0;
#ifndef WOLFSSL_MUTEX_INITIALIZER
if ((globalRNGMutex_valid == 1) && (wc_LockMutex(&globalRNGMutex) == 0))
#else
if (wc_LockMutex(&globalRNGMutex) == 0)
#endif
locked = 1;
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