From e86893975cbdbf101965622990f13213c56e9b86 Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Mon, 13 Apr 2026 17:46:41 -0700 Subject: [PATCH] Guard against negative length in BIO, I/O callbacks and PKCS12 PBKDF - src/bio.c: Add BIO self-cycle UAF guard and negative nread/nwrite checks - src/wolfio.c: Add negative sz guards to EmbedSend/EmbedReceive - wolfcrypt/src/pwdbased.c: Add pLen/sLen/totalLen overflow checks in wc_PKCS12_PBKDF_ex --- src/bio.c | 24 ++++++++++++++++++++++++ src/wolfio.c | 24 ++++++++++++++++++++++++ wolfcrypt/src/pwdbased.c | 25 +++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/bio.c b/src/bio.c index 41183a104bd..1fb366a3080 100644 --- a/src/bio.c +++ b/src/bio.c @@ -281,6 +281,10 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } } + if (len < 0) { + return WOLFSSL_BIO_ERROR; + } + /* start at end of list (or a WOLFSSL_BIO_SSL object since it takes care of * the rest of the chain) and work backwards */ while (bio != NULL && bio->next != NULL && bio->type != WOLFSSL_BIO_SSL) { @@ -693,6 +697,10 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) } } + if (len < 0) { + return WOLFSSL_BIO_ERROR; + } + while (bio != NULL && ret >= 0) { #ifdef WOLFSSL_BIO_HAVE_FLOW_STATS int inhibit_flow_increment = 0; @@ -1572,6 +1580,10 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) return 0; } + if (num < 0) { + return WOLFSSL_BIO_ERROR; + } + /* get amount able to read and set buffer pointer */ sz = wolfSSL_BIO_nread0(bio, buf); if (sz < 0) { @@ -1626,6 +1638,10 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) return 0; } + if (num < 0) { + return WOLFSSL_BIO_ERROR; + } + if (bio->wrIdx < bio->rdIdx) { /* if wrapped around only write up to read index. In this case * rdIdx is always greater then wrIdx so sz will not be negative. */ @@ -3162,6 +3178,14 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) if (top == NULL) { return append; } + { + WOLFSSL_BIO* cur = append; + while (cur != NULL) { + if (cur == top) + return top; /* would create cycle */ + cur = cur->next; + } + } top->next = append; if (append != NULL) { append->prev = top; diff --git a/src/wolfio.c b/src/wolfio.c index c6ffe7da11b..7b242996691 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -674,6 +674,9 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedReceiveFrom"); (void)ret; /* possibly unused */ + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + XMEMSET(&lclPeer, 0, sizeof(lclPeer)); #ifdef WOLFSSL_RW_THREADED @@ -917,6 +920,9 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedSendTo"); + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + if (!isDGramSock(sd)) { /* Probably a TCP socket. peer and peerSz MUST be NULL and 0 */ } @@ -963,6 +969,9 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedReceiveFromMcast"); + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, NULL, NULL); recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); @@ -993,6 +1002,9 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) (void)ctx; + if (sz < 0) + return BAD_FUNC_ARG; + XMEMSET(&peer, 0, sizeof(peer)); if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); @@ -1221,6 +1233,9 @@ int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) { int recvd; + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + recvd = (int)RECV_FUNCTION(sd, buf, (size_t)sz, rdFlags); recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); @@ -1231,6 +1246,9 @@ int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) { int sent; + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + sent = (int)SEND_FUNCTION(sd, buf, (size_t)sz, wrFlags); sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING); @@ -1244,6 +1262,9 @@ int wolfIO_RecvFrom(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int int recvd; socklen_t addr_len = (socklen_t)sizeof(*addr); + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, rdFlags, addr ? &addr->sa : NULL, addr ? &addr_len : 0); @@ -1257,6 +1278,9 @@ int wolfIO_SendTo(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int wr int sent; socklen_t addr_len = addr ? wolfSSL_BIO_ADDR_size(addr) : 0; + if (sz < 0) + return WOLFSSL_CBIO_ERR_GENERAL; + sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, wrFlags, addr ? &addr->sa : NULL, addr_len); diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index c2ed5c042f5..389484789f8 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -439,8 +439,22 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, /* with passLen checked at the top of the function for >= 0 then passLen * must be 1 or greater here and is always 'true' */ pLen = v * (((word32)passLen + v - 1) / v); + + /* Guard against overflow in iLen = sLen + pLen and totalLen = dLen + iLen. + * Individual sLen/pLen values fit in word32 (max 0x80000000 for INT_MAX + * inputs), but their sum can overflow. */ + if (sLen > 0xFFFFFFFFU - pLen) { + WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } iLen = sLen + pLen; + if (iLen > 0xFFFFFFFFU - v) { + WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } totalLen = dLen + sLen + pLen; if (totalLen > sizeof(staticBuffer)) { @@ -632,8 +646,19 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, sLen = v * (((word32)saltLen + v - 1) / v); /* RFC 7292 B.2 step 3: P = password repeated to ceil(passLen/v)*v bytes */ pLen = v * (((word32)passLen + v - 1) / v); + + /* Guard against overflow in iLen = sLen + pLen and totalLen = v + iLen. + * Individual sLen/pLen values fit in word32 (max 0x80000000 for INT_MAX + * inputs), but their sum can overflow. */ + if (sLen > 0xFFFFFFFFU - pLen) { + return BAD_FUNC_ARG; + } /* RFC 7292 B.2 step 4: I = S || P */ iLen = sLen + pLen; + + if (iLen > 0xFFFFFFFFU - v) { + return BAD_FUNC_ARG; + } totalLen = v + iLen; nwc = v / (word32)sizeof(PKCS12_WORD);