Skip to content

Commit 3304644

Browse files
committed
Harden chain depth bounds and parser input validation
Enforce MAX_CHAIN_DEPTH limits in OCSP chain processing (SendCertificateStatus, ProcessChainOCSPRequest), certificate loading (ProcessUserChain), and TLS 1.3 certificate sending (SendTls13Certificate). Add idx bounds checks to chain accessors in ssl.c. Harden SNI extension parser (TLSX_SNI_GetFromBuffer) with length checks preventing buffer overreads on malformed ClientHello. Fix off-by-one in TLSX_CSR_Free where <= should be < since csr->requests is a count, not a max index. Add remaining-buffer bounds checks to PKCS7 decoders: DecodeEnvelopedData, DecodeAuthEnvelopedData (encryptedContentSz and authTagSz), DecodeEncryptedData, SignedData null signature tag, and PwriKek_KeyUnWrap cekLen validation.
1 parent 5074cf3 commit 3304644

6 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/internal.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26026,7 +26026,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
2602626026
}
2602726027

2602826028
if (chain && chain->buffer) {
26029-
while (ret == 0 && idx + OPAQUE24_LEN < chain->length) {
26029+
while (ret == 0 && i < MAX_CHAIN_DEPTH &&
26030+
idx + OPAQUE24_LEN < chain->length) {
2603026031
c24to32(chain->buffer + idx, &der.length);
2603126032
idx += OPAQUE24_LEN;
2603226033

@@ -26065,7 +26066,7 @@ int SendCertificateStatus(WOLFSSL* ssl)
2606526066
WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
2606626067
}
2606726068
else {
26068-
while (ret == 0 &&
26069+
while (ret == 0 && i < MAX_CHAIN_DEPTH &&
2606926070
NULL != (request = ssl->ctx->chainOcspRequest[i])) {
2607026071
if ((i + 1) >= MAX_CERT_EXTENSIONS) {
2607126072
ret = MAX_CERT_EXTENSIONS_ERR;

src/ssl.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13944,7 +13944,7 @@ int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
1394413944
int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
1394513945
{
1394613946
WOLFSSL_ENTER("wolfSSL_get_chain_length");
13947-
if (chain)
13947+
if (chain && idx >= 0 && idx < chain->count)
1394813948
return chain->certs[idx].length;
1394913949

1395013950
return 0;
@@ -13955,7 +13955,7 @@ int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
1395513955
byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx)
1395613956
{
1395713957
WOLFSSL_ENTER("wolfSSL_get_chain_cert");
13958-
if (chain)
13958+
if (chain && idx >= 0 && idx < chain->count)
1395913959
return chain->certs[idx].buffer;
1396013960

1396113961
return 0;
@@ -13970,7 +13970,7 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
1397013970
WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
1397113971

1397213972
WOLFSSL_ENTER("wolfSSL_get_chain_X509");
13973-
if (chain != NULL && idx < MAX_CHAIN_DEPTH) {
13973+
if (chain != NULL && idx >= 0 && idx < chain->count) {
1397413974
#ifdef WOLFSSL_SMALL_STACK
1397513975
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
1397613976
DYNAMIC_TYPE_DCERT);

src/ssl_load.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,13 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
325325
while ((ret == 0) && (consumed < sz)) {
326326
DerBuffer* part = NULL;
327327

328+
/* Enforce maximum chain depth. */
329+
if (cnt >= MAX_CHAIN_DEPTH) {
330+
WOLFSSL_MSG("Chain depth limit reached");
331+
ret = MAX_CHAIN_ERROR;
332+
break;
333+
}
334+
328335
/* Get a certificate as DER. */
329336
ret = DataToDerBuffer(buff + consumed, (word32)(sz - consumed),
330337
format, type, info, heap, &part, NULL);

src/tls.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2820,6 +2820,9 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
28202820
ato16(clientHello + offset, &listLen);
28212821
offset += OPAQUE16_LEN;
28222822

2823+
if (listLen != extLen - OPAQUE16_LEN)
2824+
return BUFFER_ERROR;
2825+
28232826
if (helloSz < offset + listLen)
28242827
return BUFFER_ERROR;
28252828

@@ -2830,6 +2833,9 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
28302833
ato16(clientHello + offset, &sniLen);
28312834
offset += OPAQUE16_LEN;
28322835

2836+
if (sniLen > listLen - (ENUM_LEN + OPAQUE16_LEN))
2837+
return BUFFER_ERROR;
2838+
28332839
if (helloSz < offset + sniLen)
28342840
return BUFFER_ERROR;
28352841

@@ -3387,7 +3393,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
33873393

33883394
switch (csr->status_type) {
33893395
case WOLFSSL_CSR_OCSP:
3390-
for (i = 0; i <= csr->requests; i++) {
3396+
for (i = 0; i < csr->requests; i++) {
33913397
FreeOcspRequest(&csr->request.ocsp[i]);
33923398
}
33933399
break;

src/tls13.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9334,6 +9334,10 @@ static int SendTls13Certificate(WOLFSSL* ssl)
93349334
}
93359335
/* Certificate Data */
93369336
certSz = ssl->buffers.certificate->length;
9337+
if (ssl->buffers.certChainCnt > MAX_CHAIN_DEPTH) {
9338+
WOLFSSL_MSG("Certificate chain count exceeds maximum depth");
9339+
return MAX_CHAIN_ERROR;
9340+
}
93379341
/* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */
93389342
headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ +
93399343
CERT_HEADER_SZ;

wolfcrypt/src/pkcs7.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14879,6 +14879,12 @@ int wc_PKCS7_DecodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1487914879
}
1488014880
}
1488114881

14882+
if (ret == 0 && encryptedContentSz > (int)(pkiMsgSz - idx)) {
14883+
#ifdef NO_PKCS7_STREAM
14884+
ret = BUFFER_E;
14885+
#endif
14886+
}
14887+
1488214888
if (ret < 0)
1488314889
break;
1488414890

@@ -15141,6 +15147,12 @@ int wc_PKCS7_DecodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* in,
1514115147
#endif
1514215148
idx = localIdx;
1514315149

15150+
#ifdef NO_PKCS7_STREAM
15151+
if (ret == 0 && authTagSz > (word32)(pkiMsgSz - idx)) {
15152+
ret = BUFFER_E;
15153+
}
15154+
#endif
15155+
1514415156
if (ret == 0 && authTagSz > (word32)sizeof(authTag)) {
1514515157
WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer");
1514615158
ret = ASN_PARSE_E;

0 commit comments

Comments
 (0)