fixes after more fuzz testing

This commit is contained in:
Jacob Barthelmeh
2018-10-26 10:06:54 -06:00
committed by David Garske
parent cc32466603
commit 448f91b56d
3 changed files with 119 additions and 38 deletions

View File

@@ -137,6 +137,14 @@ ASN Options:
WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx) word32 maxIdx)
{
return GetLength_ex(input, inOutIdx, len, maxIdx, 1);
}
/* give option to check length value found against index. 1 to check 0 to not */
WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check)
{ {
int length = 0; int length = 0;
word32 idx = *inOutIdx; word32 idx = *inOutIdx;
@@ -166,7 +174,7 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
else else
length = b; length = b;
if ((idx + length) > maxIdx) { /* for user of length */ if (check && (idx + length) > maxIdx) { /* for user of length */
WOLFSSL_MSG("GetLength value exceeds buffer length"); WOLFSSL_MSG("GetLength value exceeds buffer length");
return BUFFER_E; return BUFFER_E;
} }
@@ -179,6 +187,29 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
} }
static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len,
word32 maxIdx, int check)
{
word32 idx = *inOutIdx;
byte b;
int length;
if ((idx + 1) > maxIdx)
return BUFFER_E;
b = input[idx++];
if (b != tag)
return ASN_PARSE_E;
if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
return ASN_PARSE_E;
*len = length;
*inOutIdx = idx;
return length;
}
/* Get the DER/BER encoding of an ASN.1 header. /* Get the DER/BER encoding of an ASN.1 header.
* *
* input Buffer holding DER/BER encoded data. * input Buffer holding DER/BER encoded data.
@@ -193,25 +224,10 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
word32 maxIdx) word32 maxIdx)
{ {
word32 idx = *inOutIdx; return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
byte b;
int length;
if ((idx + 1) > maxIdx)
return BUFFER_E;
b = input[idx++];
if (b != tag)
return ASN_PARSE_E;
if (GetLength(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
*len = length;
*inOutIdx = idx;
return length;
} }
WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx) word32 maxIdx)
{ {
@@ -220,6 +236,14 @@ WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
} }
WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check)
{
return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
maxIdx, check);
}
WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx) word32 maxIdx)
{ {

View File

@@ -58,6 +58,8 @@ typedef enum {
WC_PKCS7_DECODE WC_PKCS7_DECODE
} pkcs7Direction; } pkcs7Direction;
#define NO_USER_CHECK 0
#ifndef NO_PKCS7_STREAM #ifndef NO_PKCS7_STREAM
#define MAX_PKCS7_STREAM_BUFFER 256 #define MAX_PKCS7_STREAM_BUFFER 256
@@ -301,13 +303,13 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz,
* if no flag value is set then the stored max length is returned. * if no flag value is set then the stored max length is returned.
* returns length found on success and defSz if no stored data is found * returns length found on success and defSz if no stored data is found
*/ */
static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, static long wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in,
word32 defSz) word32 defSz)
{ {
/* check there is a buffer to read from */ /* check there is a buffer to read from */
if (pkcs7) { if (pkcs7) {
int length = 0, ret; int length = 0, ret;
word32 idx = 0; word32 idx = 0, maxIdx;
byte* pt; byte* pt;
if (flag != PKCS7_DEFAULT_PEEK) { if (flag != PKCS7_DEFAULT_PEEK) {
@@ -319,13 +321,15 @@ static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in,
length = defSz; length = defSz;
pt = in; pt = in;
} }
maxIdx = (word32)length;
if (length < MAX_SEQ_SZ) { if (length < MAX_SEQ_SZ) {
WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n");
return 0; return 0;
} }
if (flag == PKCS7_SEQ_PEEK) { if (flag == PKCS7_SEQ_PEEK) {
if ((ret = GetSequence(pt, &idx, &length, (word32)-1)) < 0) { if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx,
NO_USER_CHECK)) < 0) {
return ret; return ret;
} }
pkcs7->stream->maxLen = length + idx; pkcs7->stream->maxLen = length + idx;
@@ -3328,7 +3332,15 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
break; break;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); {
long rc;
rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz);
if (rc < 0) {
ret = (int)rc;
break;
}
}
pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz;
#endif #endif
/* determine total message size */ /* determine total message size */
@@ -3358,7 +3370,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
pkiMsg = pkcs7->der; pkiMsg = pkcs7->der;
pkiMsgSz = len; pkiMsgSz = len;
idx = 0; idx = 0;
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
NO_USER_CHECK) < 0)
return ASN_PARSE_E; return ASN_PARSE_E;
#else #else
ret = BER_INDEF_E; ret = BER_INDEF_E;
@@ -3429,12 +3442,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
break; break;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz);
wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0);
pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz;
#endif #endif
/* Get the inner ContentInfo sequence */ /* Get the inner ContentInfo sequence */
if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* Get the inner ContentInfo contentType */ /* Get the inner ContentInfo contentType */
@@ -3459,7 +3473,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0) if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
NO_USER_CHECK) <= 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
@@ -3469,7 +3484,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
localIdx++; localIdx++;
/* Get length of all OCTET_STRINGs. */ /* Get length of all OCTET_STRINGs. */
if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0) if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* Check whether there is one OCTET_STRING inside. */ /* Check whether there is one OCTET_STRING inside. */
@@ -3477,7 +3493,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0) { if (ret == 0) {
@@ -3493,7 +3510,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
if (pkiMsg[localIdx++] != ASN_OCTET_STRING) if (pkiMsg[localIdx++] != ASN_OCTET_STRING)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
@@ -3545,8 +3563,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
case WC_PKCS7_VERIFY_STAGE3: case WC_PKCS7_VERIFY_STAGE3:
#ifndef NO_PKCS7_STREAM #ifndef NO_PKCS7_STREAM
if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
&pkiMsg, &idx)) != 0) { pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
break; break;
} }
@@ -3727,6 +3745,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
} }
XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length);
pkiMsg2 = pkcs7->stream->tmpCert; pkiMsg2 = pkcs7->stream->tmpCert;
pkiMsg2Sz = length;
idx = 0; idx = 0;
} }
#endif #endif
@@ -3740,18 +3759,26 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
word32 certIdx = idx; word32 certIdx = idx;
if (length < MAX_LENGTH_SZ + ASN_TAG_SZ)
ret = BUFFER_E;
if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
cert = &pkiMsg2[idx]; cert = &pkiMsg2[idx];
certSz += (certIdx - idx); certSz += (certIdx - idx);
if (certSz > length) {
ret = BUFFER_E;
break;
}
} }
#ifdef ASN_BER_TO_DER #ifdef ASN_BER_TO_DER
der = pkcs7->der; der = pkcs7->der;
#endif #endif
contentDynamic = pkcs7->contentDynamic; contentDynamic = pkcs7->contentDynamic;
if (ret == 0) { if (ret == 0) {
#ifndef NO_PKCS7_STREAM #ifndef NO_PKCS7_STREAM
PKCS7State* stream = pkcs7->stream; PKCS7State* stream = pkcs7->stream;
@@ -3814,6 +3841,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
* used then don't advance idx. */ * used then don't advance idx. */
if (pkcs7->stream->flagOne && pkcs7->stream->length == 0) { if (pkcs7->stream->flagOne && pkcs7->stream->length == 0) {
idx = stateIdx + idx; idx = stateIdx + idx;
if (idx > inSz) {
/* index is more than input size */
ret = BUFFER_E;
break;
}
} }
else { else {
stateIdx = idx; /* didn't read any from internal buffer */ stateIdx = idx; /* didn't read any from internal buffer */
@@ -3834,6 +3866,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
pkcs7->stream->expected = (pkcs7->stream->maxLen - pkcs7->stream->expected = (pkcs7->stream->maxLen -
pkcs7->stream->totalRd) + pkcs7->stream->length; pkcs7->stream->totalRd) + pkcs7->stream->length;
wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0);
wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
#endif #endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5);
@@ -4011,6 +4044,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
WOLFSSL_MSG("Failed to set public key OID from signature"); WOLFSSL_MSG("Failed to set public key OID from signature");
} }
if (idx >= pkiMsg2Sz)
ret = BUFFER_E;
/* Get the signature */ /* Get the signature */
if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) { if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) {
idx++; idx++;
@@ -8469,7 +8505,15 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in,
return ret; return ret;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); {
long rc;
rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz);
if (rc < 0) {
ret = (int)rc;
break;
}
pkiMsgSz = (word32)rc;
}
#endif #endif
/* read past ContentInfo, verify type is envelopedData */ /* read past ContentInfo, verify type is envelopedData */
if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
@@ -8532,7 +8576,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in,
return ret; return ret;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz;
#endif #endif
if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
@@ -8552,7 +8596,8 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in,
(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret < 0) if (ret < 0)
@@ -8785,7 +8830,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
return ret; return ret;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz);
#endif #endif
/* remove EncryptedContentInfo */ /* remove EncryptedContentInfo */
@@ -8849,7 +8894,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in,
return ret; return ret;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz);
wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length);
tmpIv = pkcs7->stream->tmpIv; tmpIv = pkcs7->stream->tmpIv;
#endif #endif
@@ -9612,7 +9657,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in,
break; break;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz);
#endif #endif
if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) {
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
@@ -10313,7 +10358,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz,
return ret; return ret;
} }
pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); {
long rc;
rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz);
if (rc < 0) {
ret = (int)rc;
break;
}
pkiMsgSz = (word32)rc;
}
#endif #endif
/* read past ContentInfo, verify type is encrypted-data */ /* read past ContentInfo, verify type is encrypted-data */

View File

@@ -1017,8 +1017,12 @@ WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number,
WOLFSSL_LOCAL char* GetSigName(int oid); WOLFSSL_LOCAL char* GetSigName(int oid);
WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx); word32 maxIdx);
WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check);
WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx); word32 maxIdx);
WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check);
WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx); word32 maxIdx);
WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,