Add negative length validation to d2i wrappers, PEM helpers, and buffer loaders

Reject negative signed lengths before they are cast to unsigned (word32/size_t),
preventing heap buffer over-reads and oversized allocations. Covers d2i_* OpenSSL
compat wrappers, ProcessBuffer, PemToDer, certgen helpers, and CRL buffer paths.
This commit is contained in:
Colton Willey
2026-04-13 11:42:17 -07:00
parent 4e491ed3db
commit 7de624ff08
9 changed files with 71 additions and 12 deletions
+2 -2
View File
@@ -849,7 +849,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
WOLFSSL_ENTER("BufferLoadCRL");
if (crl == NULL || buff == NULL || sz == 0)
if (crl == NULL || buff == NULL || sz <= 0)
return BAD_FUNC_ARG;
if (type == WOLFSSL_FILETYPE_PEM) {
@@ -1175,7 +1175,7 @@ int GetCRLInfo(WOLFSSL_CRL* crl, CrlInfo* info, const byte* buff,
WOLFSSL_ENTER("GetCRLInfo");
if (crl == NULL || info == NULL || buff == NULL || sz == 0)
if (crl == NULL || info == NULL || buff == NULL || sz <= 0)
return BAD_FUNC_ARG;
if (type == WOLFSSL_FILETYPE_PEM) {
+2
View File
@@ -1272,6 +1272,8 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
if (data == NULL)
return NULL;
if (len <= 0)
return NULL;
if (response != NULL)
resp = *response;
+5
View File
@@ -449,6 +449,8 @@ static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
if (in_pp == NULL || *in_pp == NULL)
return NULL;
if (inSz <= 0)
return NULL;
in = *in_pp;
@@ -5001,6 +5003,9 @@ WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig,
if (pp == NULL) {
err = 1;
}
if ((!err) && (len <= 0)) {
err = 1;
}
if (!err) {
if (sig != NULL) {
/* Use the ECDSA signature object passed in. */
+8
View File
@@ -454,6 +454,10 @@ WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **out,
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
if ((!err) && (derSz <= 0)) {
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
/* Create a new RSA key to return. */
if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
WOLFSSL_ERROR_MSG("RSA_new failed");
@@ -503,6 +507,10 @@ WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **out,
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
if ((!err) && (derSz <= 0)) {
WOLFSSL_ERROR_MSG("Bad argument");
err = 1;
}
/* Create a new RSA key to return. */
if ((!err) && ((rsa = wolfSSL_RSA_new()) == NULL)) {
WOLFSSL_ERROR_MSG("RSA_new failed");
+9 -4
View File
@@ -913,7 +913,7 @@ WOLFSSL_ASN1_BIT_STRING* wolfSSL_d2i_ASN1_BIT_STRING(
WOLFSSL_ENTER("wolfSSL_d2i_ASN1_BIT_STRING");
if (src == NULL || *src == NULL || len == 0)
if (src == NULL || *src == NULL || len <= 0)
return NULL;
if (GetASNTag(*src, &idx, &tag, (word32)len) < 0)
@@ -2984,7 +2984,7 @@ static WOLFSSL_ASN1_STRING* d2i_ASN1_STRING(WOLFSSL_ASN1_STRING** out,
WOLFSSL_ENTER("d2i_ASN1_STRING");
if (src == NULL || *src == NULL || len == 0)
if (src == NULL || *src == NULL || len <= 0)
return NULL;
if (GetASNTag(*src, &idx, &tag, (word32)len) < 0)
@@ -3159,6 +3159,11 @@ int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int sz)
}
if (ret == 1) {
/* Cast to size_t BEFORE adding 1 to prevent signed overflow
* when sz == INT_MAX. By this point sz >= 0 (negative sz is
* handled above as OpenSSL -1/strlen compat). */
size_t allocSz = (size_t)sz + 1;
/* Dispose of any existing dynamic data. */
if (asn1->isDynamic) {
XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
@@ -3166,9 +3171,9 @@ int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int sz)
}
/* Check string will fit - including NUL. */
if (sz + 1 > CTC_NAME_SIZE) {
if (allocSz > CTC_NAME_SIZE) {
/* Allocate new buffer. */
asn1->data = (char*)XMALLOC((size_t)(sz + 1), NULL,
asn1->data = (char*)XMALLOC(allocSz, NULL,
DYNAMIC_TYPE_OPENSSL);
if (asn1->data == NULL) {
ret = 0;
+4
View File
@@ -2423,6 +2423,10 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz,
if ((ret == 0) && (type == CHAIN_CERT_TYPE)) {
ret = BAD_FUNC_ARG;
}
/* Reject negative size - would wrap to huge word32. */
if ((ret == 0) && (sz < 0)) {
ret = BAD_FUNC_ARG;
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 0) {
+2 -2
View File
@@ -4147,7 +4147,7 @@ static WOLFSSL_X509* d2i_X509orX509REQ(WOLFSSL_X509** x509,
WOLFSSL_ENTER("wolfSSL_X509_d2i");
if (in != NULL && len != 0
if (in != NULL && len > 0
#ifndef WOLFSSL_CERT_REQ
&& req == 0
#else
@@ -11291,7 +11291,7 @@ WOLFSSL_X509_ALGOR* wolfSSL_d2i_X509_ALGOR(WOLFSSL_X509_ALGOR** out,
WOLFSSL_ENTER("wolfSSL_d2i_X509_ALGOR");
if (src == NULL || *src == NULL || len == 0)
if (src == NULL || *src == NULL || len <= 0)
return NULL;
if (GetAlgoId(*src, &idx, &oid, oidIgnoreType, (word32)len) != 0)
+31 -2
View File
@@ -24671,10 +24671,10 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
const char* headerEnd = NULL;
const char* footerEnd = NULL;
const char* consumedEnd = NULL;
const char* bufferEnd = (const char*)(buff + longSz);
const char* bufferEnd = NULL;
long neededSz;
int ret = 0;
word32 sz = (word32)longSz;
word32 sz = 0;
int encrypted_key = 0;
DerBuffer* der;
word32 algId = 0;
@@ -24695,6 +24695,14 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
WOLFSSL_ENTER("PemToDer");
/* Reject negative size - would wrap word32 and corrupt pointer arithmetic. */
if (longSz < 0) {
return BAD_FUNC_ARG;
}
bufferEnd = (const char*)(buff + longSz);
sz = (word32)longSz;
/* get PEM header and footer based on type */
ret = wc_PemGetHeaderFooter(type, &header, &footer);
if (ret != 0)
@@ -29958,6 +29966,9 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
@@ -30462,6 +30473,9 @@ int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
cert->selfSigned = 0;
@@ -30491,6 +30505,9 @@ int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
@@ -30518,6 +30535,9 @@ int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
@@ -30552,6 +30572,9 @@ int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
@@ -30589,6 +30612,9 @@ int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
@@ -30616,6 +30642,9 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
if (cert == NULL) {
ret = BAD_FUNC_ARG;
}
else if (derSz < 0) {
ret = BAD_FUNC_ARG;
}
else {
/* Check if decodedCert is cached */
if (cert->der != der) {
+8 -2
View File
@@ -1464,12 +1464,18 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey,
{
int ret;
WOLFSSL_EVP_PKEY* key = NULL;
const byte* der = *pp;
const byte* der;
word32 idx = 0;
int len = 0;
int cnt = 0;
word32 algId;
word32 keyLen = (word32)length;
word32 keyLen;
if (pp == NULL || *pp == NULL || length <= 0)
return NULL;
der = *pp;
keyLen = (word32)length;
/* Take off PKCS#8 wrapper if found. */
if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) {