fix expected size and add sanity checks

This commit is contained in:
Jacob Barthelmeh
2019-06-04 22:46:16 +07:00
parent a25d04044a
commit 4362ce5f6b
3 changed files with 61 additions and 26 deletions

View File

@ -281,6 +281,14 @@ WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
maxIdx); maxIdx);
} }
WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check)
{
return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
maxIdx, check);
}
/* Get the DER/BER encoded ASN.1 NULL element. /* Get the DER/BER encoded ASN.1 NULL element.
* Ensure that the all fields are as expected and move index past the element. * Ensure that the all fields are as expected and move index past the element.
* *

View File

@ -3332,7 +3332,7 @@ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig,
XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
pkcs7->plainDigest = NULL; pkcs7->plainDigest = NULL;
pkcs7->plainDigestSz = 0; pkcs7->plainDigestSz = 0;
pkcs7->plainDigest = (byte*)XMALLOC(sigSz, pkcs7->heap, pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap,
DYNAMIC_TYPE_DIGEST); DYNAMIC_TYPE_DIGEST);
if (pkcs7->plainDigest == NULL) { if (pkcs7->plainDigest == NULL) {
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@ -3347,7 +3347,7 @@ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig,
XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
pkcs7->pkcs7Digest = NULL; pkcs7->pkcs7Digest = NULL;
pkcs7->pkcs7DigestSz = 0; pkcs7->pkcs7DigestSz = 0;
pkcs7->pkcs7Digest = (byte*)XMALLOC(sigSz, pkcs7->heap, pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap,
DYNAMIC_TYPE_DIGEST); DYNAMIC_TYPE_DIGEST);
if (pkcs7->pkcs7Digest == NULL) { if (pkcs7->pkcs7Digest == NULL) {
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@ -3585,7 +3585,7 @@ void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag)
* *
* returns 0 on success * returns 0 on success
*/ */
static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz, static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz,
word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz) word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz)
{ {
int ret = 0; int ret = 0;
@ -3593,7 +3593,6 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
int version; int version;
word32 sigOID = 0, hashOID = 0; word32 sigOID = 0, hashOID = 0;
word32 idx = *idxIn; word32 idx = *idxIn;
word32 maxIdx = *idxIn + inSz;
WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo"); WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo");
/* require a signer if degenerate case not allowed */ /* require a signer if degenerate case not allowed */
@ -3612,11 +3611,11 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
ret = wc_PKCS7_SignerInfoNew(pkcs7); ret = wc_PKCS7_SignerInfoNew(pkcs7);
/* Get the sequence of the first signerInfo */ /* Get the sequence of the first signerInfo */
if (ret == 0 && GetSequence(in, &idx, &length, maxIdx) < 0) if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* Get the version */ /* Get the version */
if (ret == 0 && GetMyVersion(in, &idx, &version, maxIdx) < 0) if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0) { if (ret == 0) {
@ -3625,7 +3624,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
if (ret == 0 && version == 1) { if (ret == 0 && version == 1) {
/* Get the sequence of IssuerAndSerialNumber */ /* Get the sequence of IssuerAndSerialNumber */
if (GetSequence(in, &idx, &length, maxIdx) < 0) if (GetSequence(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0) { if (ret == 0) {
@ -3635,24 +3634,24 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
} else if (ret == 0 && version == 3) { } else if (ret == 0 && version == 3) {
/* Get the sequence of SubjectKeyIdentifier */ /* Get the sequence of SubjectKeyIdentifier */
if (idx + 1 > maxIdx) if (idx + 1 > inSz)
ret = BUFFER_E; ret = BUFFER_E;
if (ret == 0 && in[idx] == if (ret == 0 && in[idx] ==
(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
idx++; idx++;
if (ret == 0 && GetLength(in, &idx, &length, maxIdx) <= 0) { if (ret == 0 && GetLength(in, &idx, &length, inSz) <= 0) {
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
if (idx + 1 > maxIdx) if (idx + 1 > inSz)
ret = BUFFER_E; ret = BUFFER_E;
if (ret == 0 && in[idx++] != ASN_OCTET_STRING) if (ret == 0 && in[idx++] != ASN_OCTET_STRING)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && GetLength(in, &idx, &length, maxIdx) < 0) if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
else { else {
@ -3660,7 +3659,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
* 3 try to get issuerAndSerial */ * 3 try to get issuerAndSerial */
if (in[idx] == ASN_CONTEXT_SPECIFIC) { if (in[idx] == ASN_CONTEXT_SPECIFIC) {
idx++; idx++;
if (ret == 0 && GetLength(in, &idx, &length, maxIdx) < 0) if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
else { else {
@ -3669,7 +3668,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
if (ret == 0 && GetSequence(in, &idx, &length, maxIdx) < 0) if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
} }
@ -3685,7 +3684,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
} }
/* Get the sequence of digestAlgorithm */ /* Get the sequence of digestAlgorithm */
if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, maxIdx) < 0) { if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, inSz) < 0) {
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
pkcs7->hashOID = (int)hashOID; pkcs7->hashOID = (int)hashOID;
@ -3695,7 +3694,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
idx++; idx++;
if (GetLength(in, &idx, &length, maxIdx) < 0) if (GetLength(in, &idx, &length, inSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* save pointer and length */ /* save pointer and length */
@ -3712,7 +3711,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, int inSz,
} }
/* Get digestEncryptionAlgorithm */ /* Get digestEncryptionAlgorithm */
if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidSigType, maxIdx) < 0) { if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidSigType, inSz) < 0) {
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
@ -3750,7 +3749,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
word32 hashSz, byte* in, word32 inSz, word32 hashSz, byte* in, word32 inSz,
byte* in2, word32 in2Sz) byte* in2, word32 in2Sz)
{ {
word32 idx, outerContentType, contentTypeSz = 0, totalSz = 0; word32 idx, maxIdx = inSz, outerContentType, contentTypeSz = 0, totalSz = 0;
int length = 0, version = 0, ret = 0; int length = 0, version = 0, ret = 0;
byte* content = NULL; byte* content = NULL;
byte* contentDynamic = NULL; byte* contentDynamic = NULL;
@ -3981,6 +3980,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
/* Check for content info, it could be omitted when degenerate */ /* Check for content info, it could be omitted when degenerate */
localIdx = idx; localIdx = idx;
ret = 0; ret = 0;
if (localIdx + 1 > pkiMsgSz) {
ret = BUFFER_E;
break;
}
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;
@ -4070,10 +4074,14 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
/* content expected? */ /* content expected? */
if ((ret == 0 && length > 0) && if ((ret == 0 && length > 0) &&
!(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) {
pkcs7->stream->expected = length + ASN_TAG_SZ; pkcs7->stream->expected = length + ASN_TAG_SZ + MAX_LENGTH_SZ;
} }
else { else {
pkcs7->stream->expected = ASN_TAG_SZ; pkcs7->stream->expected = ASN_TAG_SZ + MAX_LENGTH_SZ;
}
if (pkcs7->stream->expected > (pkcs7->stream->maxLen - idx)) {
pkcs7->stream->expected = pkcs7->stream->maxLen - idx;
} }
if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
@ -4117,6 +4125,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
} }
multiPart = pkcs7->stream->multi; multiPart = pkcs7->stream->multi;
detached = pkcs7->stream->detached; detached = pkcs7->stream->detached;
maxIdx = idx + pkcs7->stream->expected;
#endif #endif
/* Break out before content because it can be optional in degenerate /* Break out before content because it can be optional in degenerate
@ -4250,7 +4259,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
if (ret == 0 && pkiMsg2[idx] == if (ret == 0 && pkiMsg2[idx] ==
(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
idx++; idx++;
if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK)
< 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
@ -4258,7 +4268,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
break; break;
} }
#ifndef NO_PKCS7_STREAM #ifndef NO_PKCS7_STREAM
if (content != NULL && pkcs7->stream->flagOne && length > 0) { if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
stateIdx = idx; /* case where all data was read from in2 */ stateIdx = idx; /* case where all data was read from in2 */
} }
@ -4478,6 +4488,12 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
/* restore content type */ /* restore content type */
contentType = pkcs7->stream->nonce; contentType = pkcs7->stream->nonce;
contentTypeSz = pkcs7->stream->nonceSz; contentTypeSz = pkcs7->stream->nonceSz;
maxIdx = idx + pkcs7->stream->expected;
if (maxIdx > pkiMsg2Sz) {
ret = BUFFER_E;
break;
}
#endif #endif
/* set contentType and size after init of PKCS7 structure */ /* set contentType and size after init of PKCS7 structure */
@ -4486,7 +4502,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* Get the implicit[1] set of crls */ /* Get the implicit[1] set of crls */
if (ret == 0 && idx >= pkiMsg2Sz) if (ret == 0 && idx >= maxIdx)
ret = BUFFER_E; ret = BUFFER_E;
if (ret == 0 && pkiMsg2[idx] == if (ret == 0 && pkiMsg2[idx] ==
@ -4500,7 +4516,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
} }
/* Get the set of signerInfos */ /* Get the set of signerInfos */
if (ret == 0 && GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx,
NO_USER_CHECK) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret != 0) if (ret != 0)
@ -4514,12 +4531,20 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
} }
wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
if (length > 0) { if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
pkcs7->stream->expected = length; if (length > 0) {
pkcs7->stream->expected = length;
}
else {
pkcs7->stream->expected = 0;
}
} }
else { else {
pkcs7->stream->expected = 0; /* last state expect the reset of the buffer */
pkcs7->stream->expected = (pkcs7->stream->maxLen -
pkcs7->stream->totalRd) + pkcs7->stream->length;
} }
#endif #endif
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6);
FALL_THROUGH; FALL_THROUGH;

View File

@ -1025,6 +1025,8 @@ WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check); 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 GetSet_ex(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx, int check);
WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
int* version, word32 maxIdx); int* version, word32 maxIdx);
WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,