mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 15:10:48 +02:00
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:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user