diff --git a/src/ssl.c b/src/ssl.c index e18ae778c..bc046ee9f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -34722,8 +34722,13 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) if (no_name == 1) { int length; word32 idx = 0; + byte tag; - if (a->obj[idx++] != ASN_OBJECT_ID) { + if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) { + return WOLFSSL_FAILURE; + } + + if (tag != ASN_OBJECT_ID) { WOLFSSL_MSG("Bad ASN1 Object"); return WOLFSSL_FAILURE; } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 18787949a..f54bdee2c 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -199,18 +199,44 @@ WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, } +/* input : buffer to read from + * inOutIdx : index to start reading from, gets advanced by 1 if successful + * maxIdx : maximum index value + * tag : ASN tag value found + * + * returns 0 on success + */ +int GetASNTag(const byte* input, word32* inOutIdx, byte* tag, word32 maxIdx) +{ + word32 idx; + + if (tag == NULL || inOutIdx == NULL || input == NULL) { + return BAD_FUNC_ARG; + } + + idx = *inOutIdx; + if (idx + ASN_TAG_SZ > maxIdx) { + WOLFSSL_MSG("Buffer too small for ASN tag"); + return BUFFER_E; + } + + *tag = input[idx]; + *inOutIdx = idx + ASN_TAG_SZ; + return 0; +} + + static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len, word32 maxIdx, int check) { word32 idx = *inOutIdx; - byte b; + byte tagFound; int length; - if ((idx + 1) > maxIdx) - return BUFFER_E; + if (GetASNTag(input, &idx, &tagFound, maxIdx) != 0) + return ASN_PARSE_E; - b = input[idx++]; - if (b != tag) + if (tagFound != tag) return ASN_PARSE_E; if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) @@ -450,7 +476,9 @@ static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) if ((idx + 3) > maxIdx) return BUFFER_E; - if (input[idx++] != ASN_INTEGER) + if (GetASNTag(input, &idx, &b, maxIdx) != 0) + return ASN_PARSE_E; + if (b != ASN_INTEGER) return ASN_PARSE_E; if (input[idx++] != 1) return ASN_PARSE_E; @@ -674,11 +702,15 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version, word32 maxIdx) { word32 idx = *inOutIdx; + byte tag; if ((idx + MIN_VERSION_SZ) > maxIdx) return ASN_PARSE_E; - if (input[idx++] != ASN_INTEGER) + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != ASN_INTEGER) return ASN_PARSE_E; if (input[idx++] != 0x01) @@ -697,6 +729,7 @@ WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, { word32 idx = *inOutIdx; word32 len; + byte tag; *number = 0; @@ -704,7 +737,10 @@ WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, if ((idx + 2) > maxIdx) return BUFFER_E; - if (input[idx++] != ASN_INTEGER) + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != ASN_INTEGER) return ASN_PARSE_E; len = input[idx++]; @@ -774,13 +810,14 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, word32 maxIdx) { word32 idx = *inOutIdx; + byte tag; WOLFSSL_ENTER("GetExplicitVersion"); - if ((idx + 1) > maxIdx) - return BUFFER_E; + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; - if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { *inOutIdx = ++idx; /* skip header */ return GetMyVersion(input, inOutIdx, version, maxIdx); } @@ -848,11 +885,13 @@ static int CheckBitString(const byte* input, word32* inOutIdx, int* len, int length; byte b; - if ((idx + 1) > maxIdx) - return BUFFER_E; - - if (input[idx++] != ASN_BIT_STRING) + if (GetASNTag(input, &idx, &b, maxIdx) != 0) { return ASN_BITSTR_E; + } + + if (b != ASN_BIT_STRING) { + return ASN_BITSTR_E; + } if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; @@ -949,6 +988,9 @@ int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz) outSz = *derSz; for (i = 0, j = 0; i < berSz; ) { + word32 localIdx; + byte tag; + /* Check that there is data for an ASN item to parse. */ if (i + 2 > berSz) return ASN_PARSE_E; @@ -971,9 +1013,14 @@ int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz) /* Indefinite length is encoded as: 0x80 */ type = ber[i]; indef = ber[i+1] == ASN_INDEF_LENGTH; + + localIdx = i; + if (GetASNTag(ber, &localIdx, &tag, berSz) != 0) + return ASN_PARSE_E; + if (indef && (type & 0xC0) == 0 && - ber[i] != (ASN_SEQUENCE | ASN_CONSTRUCTED) && - ber[i] != (ASN_SET | ASN_CONSTRUCTED)) { + tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) && + tag != (ASN_SET | ASN_CONSTRUCTED)) { /* Indefinite length OCTET STRING or other simple type. * Put all the data into one entry. */ @@ -2097,14 +2144,16 @@ int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { word32 idx = *inOutIdx; - byte b; int length; + byte tag; if ((idx + 1) > maxIdx) return BUFFER_E; - b = input[idx++]; - if (b != ASN_OBJECT_ID) + if (GetASNTag(input, &idx, &tag, maxIdx) != 0) + return ASN_PARSE_E; + + if (tag != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; if (GetLength(input, &idx, &length, maxIdx) < 0) @@ -2247,10 +2296,17 @@ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, return ASN_OBJECT_ID_E; /* could have NULL tag and 0 terminator, but may not */ - if (idx < maxIdx && input[idx] == ASN_TAG_NULL) { - ret = GetASNNull(input, &idx, maxIdx); - if (ret != 0) - return ret; + if (idx < maxIdx) { + word32 localIdx = idx; /*use localIdx to not advance when checking tag*/ + byte tag; + + if (GetASNTag(input, &localIdx, &tag, maxIdx) == 0) { + if (tag == ASN_TAG_NULL) { + ret = GetASNNull(input, &idx, maxIdx); + if (ret != 0) + return ret; + } + } } *inOutIdx = idx; @@ -2322,6 +2378,7 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, word32 idx; int version, length; int ret; + byte tag; if (input == NULL || inOutIdx == NULL) return BAD_FUNC_ARG; @@ -2337,7 +2394,11 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, if (GetAlgoId(input, &idx, algId, oidKeyType, sz) < 0) return ASN_PARSE_E; - if (input[idx] == ASN_OBJECT_ID) { + if (GetASNTag(input, &idx, &tag, sz) < 0) + return ASN_PARSE_E; + idx = idx - 1; /* reset idx after finding tag */ + + if (tag == ASN_OBJECT_ID) { if (SkipObjectId(input, &idx, sz) < 0) return ASN_PARSE_E; } @@ -3451,8 +3512,16 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password, } /* OPTIONAL key length */ - if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { - if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + if (seqEnd > inOutIdx) { + word32 localIdx = inOutIdx; + byte tag; + + if (GetASNTag(input, &localIdx, &tag, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + if (tag == ASN_INTEGER && + GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_tte); } } @@ -3749,6 +3818,7 @@ int DecryptContent(byte* input, word32 sz,const char* password, int passwordSz) byte salt[MAX_SALT_SIZE]; byte cbcIv[MAX_IV_SIZE]; #endif + byte tag; if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_dc); @@ -3805,8 +3875,15 @@ int DecryptContent(byte* input, word32 sz,const char* password, int passwordSz) } /* OPTIONAL key length */ - if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { - if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + if (seqEnd > inOutIdx) { + word32 localIdx = inOutIdx; + + if (GetASNTag(input, &localIdx, &tag, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (tag == ASN_INTEGER && + GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { ERROR_OUT(ASN_PARSE_E, exit_dc); } } @@ -3847,7 +3924,11 @@ int DecryptContent(byte* input, word32 sz,const char* password, int passwordSz) inOutIdx += length; } - if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (tag != (ASN_CONTEXT_SPECIFIC | 0)) { ERROR_OUT(ASN_PARSE_E, exit_dc); } @@ -3884,7 +3965,8 @@ int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, int ret = 0; int length = 0; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - byte b; + word32 localIdx; + byte tag; #endif if (input == NULL || inOutIdx == NULL) @@ -3894,11 +3976,11 @@ int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, return ASN_PARSE_E; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - if ((*inOutIdx + 1) > inSz) + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) < 0) return BUFFER_E; - b = input[*inOutIdx]; - if (b != ASN_INTEGER) { + if (tag != ASN_INTEGER) { /* not from decoded cert, will have algo id, skip past */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -3910,7 +3992,12 @@ int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, if (*inOutIdx >= inSz) { return BUFFER_E; } - if (input[*inOutIdx] == ASN_TAG_NULL) { + + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) < 0) + return ASN_PARSE_E; + + if (tag == ASN_TAG_NULL) { ret = GetASNNull(input, inOutIdx, inSz); if (ret != 0) return ret; @@ -4498,10 +4585,15 @@ static int GetKey(DecodedCert* cert) int ret; byte seq[5]; int pubLen = length + 1 + SetLength(length, seq); + word32 localIdx; byte* publicKey; + byte tag; - if (cert->source[cert->srcIdx] != - (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + localIdx = cert->srcIdx; + if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) { if (GetObjectId(cert->source, &cert->srcIdx, &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) return ASN_PARSE_E; @@ -4647,7 +4739,8 @@ static int GetName(DecodedCert* cert, int nameType) int ret; char* full; byte* hash; - word32 idx; + word32 idx, localIdx = 0; + byte tag; #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) DecodedName* dName = (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName; @@ -4672,7 +4765,12 @@ static int GetName(DecodedCert* cert, int nameType) return BUFFER_E; } - if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { + localIdx = cert->srcIdx; + if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0) { + return ASN_PARSE_E; + } + + if (tag == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0) @@ -6843,6 +6941,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) word32 lenStartIdx = idx; word32 oid = 0; int ret; + byte tag; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -6861,7 +6960,11 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { WOLFSSL_MSG("\twrong type"); return ASN_PARSE_E; } @@ -6955,8 +7058,9 @@ static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert) cert->isCA = (byte)ret; /* If there isn't any more data, return. */ - if (idx >= (word32)sz) + if (idx >= (word32)sz) { return 0; + } ret = GetInteger7Bit(input, &idx, sz); if (ret < 0) @@ -6976,8 +7080,9 @@ static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert) static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) { - word32 idx = 0; + word32 idx = 0, localIdx; int length = 0; + byte tag = 0; WOLFSSL_ENTER("DecodeCrlDist"); @@ -6992,20 +7097,26 @@ static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) /* The Distribution Point has three explicit optional members * First check for a DistributionPointName */ - if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (input[idx] == - (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | + CRLDP_FULL_NAME)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -7026,8 +7137,10 @@ static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) } /* Check for reasonFlags */ + localIdx = idx; if (idx < (word32)sz && - input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -7036,8 +7149,10 @@ static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) } /* Check for cRLIssuer */ + localIdx = idx; if (idx < (word32)sz && - input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) + GetASNTag(input, &localIdx, &tag, sz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) { idx++; if (GetLength(input, &idx, &length, sz) < 0) @@ -7063,7 +7178,7 @@ static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; - byte b; + byte b = 0; word32 oid; WOLFSSL_ENTER("DecodeAuthInfo"); @@ -7083,7 +7198,9 @@ static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert) /* Only supporting URIs right now. */ - b = input[idx++]; + if (GetASNTag(input, &idx, &b, sz) < 0) + return ASN_PARSE_E; + if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; @@ -7105,6 +7222,7 @@ static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0, ret = 0; + byte tag; WOLFSSL_ENTER("DecodeAuthKeyId"); @@ -7113,7 +7231,11 @@ static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != (ASN_CONTEXT_SPECIFIC | 0)) { WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n"); return 0; } @@ -7564,13 +7686,18 @@ static int DecodeCertExtensions(DecodedCert* cert) word32 oid; byte critical = 0; byte criticalFail = 0; + byte tag = 0; WOLFSSL_ENTER("DecodeCertExtensions"); if (input == NULL || sz == 0) return BAD_FUNC_ARG; - if (input[idx++] != ASN_EXTENSIONS) { + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } + + if (tag != ASN_EXTENSIONS) { WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); return ASN_PARSE_E; } @@ -7586,6 +7713,8 @@ static int DecodeCertExtensions(DecodedCert* cert) } while (idx < (word32)sz) { + word32 localIdx; + if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; @@ -7604,14 +7733,17 @@ static int DecodeCertExtensions(DecodedCert* cert) return BUFFER_E; } - if (input[idx] == ASN_BOOLEAN) { - ret = GetBoolean(input, &idx, sz); - if (ret < 0) { - WOLFSSL_MSG("\tfail: critical boolean"); - return ret; - } + localIdx = idx; + if (GetASNTag(input, &localIdx, &tag, sz) == 0) { + if (tag == ASN_BOOLEAN) { + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; + } - critical = (byte)ret; + critical = (byte)ret; + } } /* process the extension based on the OID */ @@ -7899,6 +8031,9 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, int extAuthKeyIdSet = 0; #endif int ret = 0; + word32 localIdx; + byte tag; + if (cert == NULL) { return BAD_FUNC_ARG; @@ -7929,11 +8064,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, } if (ret == 0) { /* version - optional */ - if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - idx++; - if (GetLength(cert, &idx, &len, certSz) < 0) - ret = ASN_PARSE_E; - idx += len; + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } } } @@ -7989,11 +8127,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, } if (ret == 0) { /* issuerUniqueID - optional */ - if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { - idx++; - if (GetLength(cert, &idx, &len, certSz) < 0) - ret = ASN_PARSE_E; - idx += len; + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } } } if (ret == 0) { @@ -8002,11 +8143,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, } if (ret == 0) { /* subjectUniqueID - optional */ - if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { - idx++; - if (GetLength(cert, &idx, &len, certSz) < 0) - ret = ASN_PARSE_E; - idx += len; + localIdx = idx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) { + if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } } } @@ -8015,7 +8159,9 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, ret = BUFFER_E; } /* extensions - optional */ - if (ret == 0 && cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) { + localIdx = idx; + if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) { idx++; if (GetLength(cert, &idx, &extLen, certSz) < 0) ret = ASN_PARSE_E; @@ -8036,9 +8182,17 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, certSz) < 0) { ret = ASN_PARSE_E; } + + if (ret == 0) { + if ((extIdx + 1) > certSz) + ret = BUFFER_E; + } } + if (ret == 0) { - if (cert[extIdx] == ASN_BOOLEAN) { + localIdx = extIdx; + if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 && + tag == ASN_BOOLEAN) { if (GetBoolean(cert, &extIdx, certSz) < 0) ret = ASN_PARSE_E; } @@ -8055,8 +8209,12 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, if (GetSequence(cert, &extIdx, &extLen, certSz) < 0) ret = ASN_PARSE_E; + if (ret == 0 && (extIdx + 1) >= certSz) + ret = BUFFER_E; + if (ret == 0 && - cert[extIdx++] == (ASN_CONTEXT_SPECIFIC | 0)) { + GetASNTag(cert, &extIdx, &tag, certSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | 0)) { if (GetLength(cert, &extIdx, &extLen, certSz) <= 0) ret = ASN_PARSE_E; if (ret == 0) { @@ -12942,16 +13100,19 @@ int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx, static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded) { int ret = 0; + byte tag; if (decoded->extensions) { - byte b; int length; word32 maxExtensionsIdx; decoded->srcIdx = decoded->extensionsIdx; - b = decoded->source[decoded->srcIdx++]; + if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx) + != 0) { + return ASN_PARSE_E; + } - if (b != ASN_EXTENSIONS) { + if (tag != ASN_EXTENSIONS) { ret = ASN_PARSE_E; } else if (GetLength(decoded->source, &decoded->srcIdx, &length, @@ -13678,12 +13839,15 @@ static int ASNToHexString(const byte* input, word32* inOutIdx, char** out, int len; int i; char* str; + word32 localIdx; + byte tag; if (*inOutIdx >= inSz) { return BUFFER_E; } - if (input[*inOutIdx] == ASN_INTEGER) { + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && tag == ASN_INTEGER) { if (GetASNInt(input, inOutIdx, &len, inSz) < 0) return ASN_PARSE_E; } @@ -13710,7 +13874,8 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, int length; int ret; int curve_id = ECC_CURVE_DEF; - word32 oidSum; + word32 oidSum, localIdx; + byte tag; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -13729,7 +13894,9 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, return BUFFER_E; } - if (input[*inOutIdx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + localIdx = *inOutIdx; + if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && + tag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { #ifdef WOLFSSL_CUSTOM_CURVES ecc_set_type* curve; int len; @@ -13781,7 +13948,9 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, key->heap, DYNAMIC_TYPE_ECC_BUFFER); } if (ret == 0) { - if (*inOutIdx < inSz && input[*inOutIdx] == ASN_BIT_STRING) { + localIdx = *inOutIdx; + if (*inOutIdx < inSz && GetASNTag(input, &localIdx, &tag, inSz) + == 0 && tag == ASN_BIT_STRING) { len = 0; ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz); *inOutIdx += len; @@ -14291,20 +14460,28 @@ static int GetBasicDate(const byte* source, word32* idx, byte* date, #ifdef HAVE_OCSP -static int GetEnumerated(const byte* input, word32* inOutIdx, int *value) +static int GetEnumerated(const byte* input, word32* inOutIdx, int *value, + int sz) { word32 idx = *inOutIdx; word32 len; + byte tag; WOLFSSL_ENTER("GetEnumerated"); *value = 0; - if (input[idx++] != ASN_ENUMERATED) + if (GetASNTag(input, &idx, &tag, sz) < 0) return ASN_PARSE_E; + if (tag != ASN_ENUMERATED) + return ASN_PARSE_E; + + if ((int)idx >= sz) + return BUFFER_E; + len = input[idx++]; - if (len > 4) + if (len > 4 || (int)len > sz) return ASN_PARSE_E; while (len--) { @@ -14320,10 +14497,11 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value) static int DecodeSingleResponse(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { - word32 idx = *ioIndex, prevIndex, oid; + word32 idx = *ioIndex, prevIndex, oid, localIdx; int length, wrapperSz; CertStatus* cs = resp->status; int ret; + byte tag; WOLFSSL_ENTER("DecodeSingleResponse"); @@ -14401,8 +14579,10 @@ static int DecodeSingleResponse(byte* source, /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ + localIdx = idx; if (((int)(idx - prevIndex) < wrapperSz) && - (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))) + GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(source, &idx, &length, size) < 0) @@ -14421,8 +14601,11 @@ static int DecodeSingleResponse(byte* source, #endif #endif } + + localIdx = idx; if (((int)(idx - prevIndex) < wrapperSz) && - (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) + GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(source, &idx, &length, size) < 0) @@ -14443,13 +14626,17 @@ static int DecodeOcspRespExtensions(byte* source, int ext_bound; /* boundary index for the sequence of extensions */ word32 oid; int ret; + byte tag; WOLFSSL_ENTER("DecodeOcspRespExtensions"); if ((idx + 1) > sz) return BUFFER_E; - if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + if (GetASNTag(source, &idx, &tag, sz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) return ASN_PARSE_E; if (GetLength(source, &idx, &length, sz) < 0) @@ -14461,6 +14648,8 @@ static int DecodeOcspRespExtensions(byte* source, ext_bound = idx + length; while (idx < (word32)ext_bound) { + word32 localIdx; + if (GetSequence(source, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); return ASN_PARSE_E; @@ -14478,7 +14667,8 @@ static int DecodeOcspRespExtensions(byte* source, return BUFFER_E; } - if (source[idx] == ASN_BOOLEAN) { + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) { WOLFSSL_MSG("\tfound optional critical flag, moving past"); ret = GetBoolean(source, &idx, sz); if (ret < 0) @@ -14510,11 +14700,11 @@ static int DecodeOcspRespExtensions(byte* source, static int DecodeResponseData(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { - word32 idx = *ioIndex, prev_idx; + word32 idx = *ioIndex, prev_idx, localIdx; int length; int version; - word32 responderId = 0; int ret; + byte tag; WOLFSSL_ENTER("DecodeResponseData"); @@ -14528,7 +14718,9 @@ static int DecodeResponseData(byte* source, * item isn't an EXPLICIT[0], then set version to zero and move * onto the next item. */ - if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, size) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { idx += 2; /* Eat the value and length */ if (GetMyVersion(source, &idx, &version, size) < 0) @@ -14536,10 +14728,12 @@ static int DecodeResponseData(byte* source, } else version = 0; - responderId = source[idx++]; - if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) || - (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2))) + localIdx = idx; + if (GetASNTag(source, &localIdx, &tag, size) == 0 && + ( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) || + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) )) { + idx++; /* advance past ASN tag */ if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; idx += length; @@ -14574,10 +14768,14 @@ static int DecodeCerts(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { word32 idx = *ioIndex; + byte tag; WOLFSSL_ENTER("DecodeCerts"); - if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + if (GetASNTag(source, &idx, &tag, size) < 0) + return ASN_PARSE_E; + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { int length; @@ -14743,6 +14941,7 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) byte* source = resp->source; word32 size = resp->maxIdx; word32 oid; + byte tag; WOLFSSL_ENTER("OcspResponseDecode"); @@ -14751,7 +14950,7 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) return ASN_PARSE_E; /* First get the responseStatus, an ENUMERATED */ - if (GetEnumerated(source, &idx, &resp->responseStatus) < 0) + if (GetEnumerated(source, &idx, &resp->responseStatus, size) < 0) return ASN_PARSE_E; if (resp->responseStatus != OCSP_SUCCESSFUL) @@ -14760,7 +14959,9 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */ if (idx >= size) return ASN_INPUT_E; - if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + if (GetASNTag(source, &idx, &tag, size) < 0) + return ASN_PARSE_E; + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) return ASN_PARSE_E; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; @@ -15070,10 +15271,12 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int length; /* length of all distinguished names */ int ret; word32 dummy; + byte tag; WOLFSSL_ENTER("GetNameHash"); - if (source[*idx] == ASN_OBJECT_ID) { + dummy = *idx; + if (GetASNTag(source, &dummy, &tag, maxIdx) == 0 && tag == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); if (GetLength(source, idx, &length, maxIdx) < 0) @@ -15228,9 +15431,10 @@ int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) { int version, len, doNextDate = 1; - word32 oid, idx = 0, dateIdx; + word32 oid, idx = 0, dateIdx, localIdx; Signer* ca = NULL; SignatureCtx sigCtx; + byte tag; WOLFSSL_MSG("ParseCRL"); @@ -15251,7 +15455,8 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) dcrl->sigIndex = len + idx; /* may have version */ - if (buff[idx] == ASN_INTEGER) { + localIdx = idx; + if (GetASNTag(buff, &localIdx, &tag, sz) == 0 && tag == ASN_INTEGER) { if (GetMyVersion(buff, &idx, &version, sz) < 0) return ASN_PARSE_E; } @@ -15288,7 +15493,9 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) #endif } - if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { + localIdx = idx; + if (idx != dcrl->sigIndex && + GetASNTag(buff, &localIdx, &tag, sz) == 0 && tag != CRL_EXTENSIONS) { if (GetSequence(buff, &idx, &len, sz) < 0) return ASN_PARSE_E; diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index c221f7b22..9c01204d3 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -198,6 +198,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, word32 localIdx = *idx; int ret; int size = 0; + byte tag; safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, DYNAMIC_TYPE_PKCS); @@ -215,7 +216,12 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, safe->oid = oid; /* check tag, length */ - if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; @@ -233,7 +239,12 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, case WC_PKCS12_DATA: WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); /* get octets holding contents */ - if (input[localIdx++] != ASN_OCTET_STRING) { + if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; @@ -347,6 +358,7 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, word32 curIdx = *idx; word32 oid = 0; int size, ret; + byte tag; /* Digest Info : Sequence * DigestAlgorithmIdentifier @@ -380,7 +392,12 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, #endif /* Digest: should be octet type holding digest */ - if (mem[curIdx++] != ASN_OCTET_STRING) { + if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { WOLFSSL_MSG("Failed to get digest"); XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); return ASN_PARSE_E; @@ -411,7 +428,11 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, curIdx += mac->digestSz; /* get salt, should be octet string */ - if (mem[curIdx++] != ASN_OCTET_STRING) { + if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_gsd); + } + + if (tag != ASN_OCTET_STRING) { WOLFSSL_MSG("Failed to get salt"); ERROR_OUT(ASN_PARSE_E, exit_gsd); } @@ -972,13 +993,18 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, byte* data; word32 idx = 0; int size, totalSz; + byte tag; if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { int number; WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); data = ci->data; - if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { @@ -1036,13 +1062,21 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, else { /* type DATA */ WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); data = ci->data; - if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { goto exit_pk12par; } - if (data[idx++] != ASN_OCTET_STRING) { + + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != ASN_OCTET_STRING) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { @@ -1072,8 +1106,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, switch (oid) { case WC_PKCS12_KeyBag: /* 667 */ WOLFSSL_MSG("PKCS12 Key Bag found"); - if (data[idx++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { @@ -1106,8 +1142,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, byte* k; WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); - if (data[idx++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, @@ -1168,8 +1206,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, { WC_DerCertList* node; WOLFSSL_MSG("PKCS12 Cert Bag found"); - if (data[idx++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { @@ -1190,15 +1230,21 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, case WC_PKCS12_CertBag_Type1: /* 675 */ /* type 1 */ WOLFSSL_MSG("PKCS12 cert bag type 1"); - if (data[idx++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC)) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { goto exit_pk12par; } - if (data[idx++] != ASN_OCTET_STRING) { + if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if (tag != ASN_OCTET_STRING) { ERROR_OUT(ASN_PARSE_E, exit_pk12par); } diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c41d6b724..cc3c9d34c 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1196,8 +1196,12 @@ static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidS word32 sz = oidSz; word32 idx = 0; int length = 0; + byte tag; - if (list->oid[idx++] != ASN_OBJECT_ID) { + if (GetASNTag(list->oid, &idx, &tag, list->oidSz) < 0) { + return NULL; + } + if (tag != ASN_OBJECT_ID) { WOLFSSL_MSG("Bad attribute ASN1 syntax"); return NULL; } @@ -3873,7 +3877,8 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, int length; int version; word32 sigOID = 0, hashOID = 0; - word32 idx = *idxIn; + word32 idx = *idxIn, localIdx; + byte tag; WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo"); /* require a signer if degenerate case not allowed */ @@ -3918,8 +3923,9 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, if (idx + 1 > inSz) ret = BUFFER_E; - if (ret == 0 && in[idx] == - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + localIdx = idx; + if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (ret == 0 && GetLength(in, &idx, &length, inSz) <= 0) { @@ -3929,7 +3935,10 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, if (idx + 1 > inSz) ret = BUFFER_E; - if (ret == 0 && in[idx++] != ASN_OCTET_STRING) + if (ret == 0 && GetASNTag(in, &idx, &tag, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) @@ -3938,7 +3947,9 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, else { /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version * 3 try to get issuerAndSerial */ - if (in[idx] == ASN_CONTEXT_SPECIFIC) { + localIdx = idx; + if (GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == ASN_CONTEXT_SPECIFIC) { idx++; if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) ret = ASN_PARSE_E; @@ -3971,8 +3982,9 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ - if (ret == 0 && in[idx] == - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + localIdx = idx; + if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(in, &idx, &length, inSz) < 0) @@ -4042,6 +4054,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 localIdx, start; byte degenerate = 0; byte detached = 0; + byte tag = 0; #ifdef ASN_BER_TO_DER byte* der; #endif @@ -4165,8 +4178,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* get the ContentInfo content */ - if (ret == 0 && pkiMsg[idx++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, totalSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz, @@ -4266,7 +4281,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, break; } - if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, @@ -4278,10 +4296,12 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* get length of content in the case that there is multiple parts */ - if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { multiPart = 1; - localIdx++; /* Get length of all OCTET_STRINGs. */ if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz, NO_USER_CHECK) < 0) @@ -4293,7 +4313,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, ret = BUFFER_E; } - if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) + != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, @@ -4310,7 +4334,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* get length of content in case of single part */ if (ret == 0 && !multiPart) { - if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, @@ -4437,7 +4461,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, start = localIdx; /* Use the data from each OCTET_STRING. */ while (ret == 0 && localIdx < start + contentLen) { - if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + if (GetASNTag(pkiMsg, &localIdx, &tag, totalSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) @@ -4544,8 +4570,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, ret = BUFFER_E; length = 0; /* set length to 0 to check if reading in any certs */ - if (ret == 0 && pkiMsg2[idx] == - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 + && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK) < 0) @@ -4627,7 +4654,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (length < MAX_LENGTH_SZ + ASN_TAG_SZ) ret = BUFFER_E; - if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (ret == 0) + ret = GetASNTag(pkiMsg2, &certIdx, &tag, pkiMsg2Sz); + + if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) ret = ASN_PARSE_E; @@ -4678,8 +4708,14 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, certIdx + 1 < (word32)length; i++) { localIdx = certIdx; - if (pkiMsg2[certIdx++] == - (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (ret == 0 && GetASNTag(pkiMsg2, &certIdx, &tag, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; + break; + } + + if (ret == 0 && + tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (GetLength(pkiMsg2, &certIdx, &sz, pkiMsg2Sz) < 0) { ret = ASN_PARSE_E; @@ -4793,8 +4829,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (ret == 0 && idx >= maxIdx) ret = BUFFER_E; - if (ret == 0 && pkiMsg2[idx] == - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0 + && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) ret = ASN_PARSE_E; @@ -4864,7 +4901,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, ret = BUFFER_E; /* Get the signature */ - if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) { + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, + pkiMsg2Sz) == 0 && tag == ASN_OCTET_STRING) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) @@ -7870,6 +7909,8 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, byte* outKey = NULL; byte* pkiMsg = in; word32 pkiMsgSz = inSz; + byte tag; + #ifndef NO_PKCS7_STREAM word32 tmpIdx = *idx; @@ -8012,16 +8053,20 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, #endif } else { - /* remove SubjectKeyIdentifier */ - if (pkiMsg[(*idx)++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8043,9 +8088,11 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ALGO_ID_E; /* read encryptedKey */ - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; - } if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { return ASN_PARSE_E; @@ -8183,13 +8230,14 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, int ret, length; word32 keyOID, oidSum = 0; int curve_id = ECC_CURVE_DEF; + byte tag; if (kari == NULL || pkiMsg == NULL || idx == NULL) return BAD_FUNC_ARG; /* remove OriginatorIdentifierOrKey */ - if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - (*idx)++; + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -8198,8 +8246,8 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, } /* remove OriginatorPublicKey */ - if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { - (*idx)++; + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -8224,13 +8272,19 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, } /* remove ECPoint BIT STRING */ - if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING)) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_BIT_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if ((pkiMsgSz < (*idx + 1)) || (pkiMsg[(*idx)++] != 0x00)) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_EXPECT_0_E; + + if (tag != ASN_OTHER_TYPE) return ASN_EXPECT_0_E; /* get sender ephemeral public ECDSA key */ @@ -8263,6 +8317,7 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, { int length; word32 savedIdx; + byte tag; if (kari == NULL || pkiMsg == NULL || idx == NULL) return BAD_FUNC_ARG; @@ -8270,7 +8325,11 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, savedIdx = *idx; /* starts with EXPLICIT [1] */ - if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { *idx = savedIdx; return 0; } @@ -8281,8 +8340,11 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, } /* get OCTET STRING */ - if ( (pkiMsgSz > ((*idx) + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + if (tag != ASN_OCTET_STRING) { *idx = savedIdx; return 0; } @@ -8350,15 +8412,18 @@ static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, int* recipFound, byte* rid) { int length; + byte tag; if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL || rid == NULL) return BAD_FUNC_ARG; /* remove RecipientKeyIdentifier IMPLICIT [0] */ - if ( (pkiMsgSz > (*idx + 1)) && - (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -8367,8 +8432,11 @@ static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, } /* remove SubjectKeyIdentifier */ - if ( (pkiMsgSz > (*idx + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8485,6 +8553,8 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, { int length; int ret = 0; + byte tag; + word32 localIdx; if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL || encryptedKey == NULL) @@ -8500,9 +8570,11 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber * or [0] IMMPLICIT RecipientKeyIdentifier */ - if ( (pkiMsgSz > (*idx + 1)) && - (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + localIdx = *idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { /* try to get RecipientKeyIdentifier */ ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, idx, recipFound, rid); @@ -8517,8 +8589,10 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, return ret; /* remove EncryptedKey */ - if ( (pkiMsgSz > (*idx + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8708,6 +8782,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; byte* pkiMsg = in; word32 pkiMsgSz = inSz; + byte tag; #ifndef NO_PKCS7_STREAM word32 tmpIdx = *idx; long rc; @@ -8732,7 +8807,10 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz = (word32)rc; #endif /* remove KeyDerivationAlgorithmIdentifier */ - if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8747,10 +8825,11 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ASN_PARSE_E; /* get KDF salt OCTET STRING */ - if ( (pkiMsgSz > ((*idx) + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; - } if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -8800,8 +8879,12 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if ( (pkiMsgSz > ((*idx) + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; } @@ -8821,8 +8904,12 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, *idx += length; /* get EncryptedKey */ - if ( (pkiMsgSz < ((*idx) + 1)) || - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (tag != ASN_OCTET_STRING) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; } @@ -8916,8 +9003,8 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, int length, keySz, dateLen, direction; byte* keyId = NULL; const byte* datePtr = NULL; - byte dateFormat; - word32 keyIdSz, kekIdSz, keyWrapOID; + byte dateFormat, tag; + word32 keyIdSz, kekIdSz, keyWrapOID, localIdx; int ret = 0; byte* pkiMsg = in; @@ -8952,7 +9039,10 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, kekIdSz = length; - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8964,7 +9054,9 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, *idx += keyIdSz; /* may have OPTIONAL GeneralizedTime */ - if ((*idx < kekIdSz) && (pkiMsg[*idx] == ASN_GENERALIZED_TIME)) { + localIdx = *idx; + if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, + pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) { if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, &dateLen) != 0) { return ASN_PARSE_E; @@ -8973,9 +9065,10 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, } /* may have OPTIONAL OtherKeyAttribute */ - if ((*idx < kekIdSz) && (pkiMsg[*idx] == - (ASN_SEQUENCE | ASN_CONSTRUCTED))) { - + localIdx = *idx; + if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, + pkiMsgSz) == 0 && tag == (ASN_SEQUENCE | + ASN_CONSTRUCTED)) { if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -8988,7 +9081,10 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, return ASN_PARSE_E; /* get EncryptedKey */ - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -9317,6 +9413,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, int version, ret = 0, length; byte* pkiMsg = in; word32 pkiMsgSz = inSz; + byte tag; #ifndef NO_PKCS7_STREAM word32 tmpIdx; long rc; @@ -9416,12 +9513,18 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, #endif } else { + word32 localIdx; /* kari is IMPLICIT[1] */ *idx = savedIdx; - if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + localIdx = *idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) { + /* no room for recipient info */ + break; + } + + if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { (*idx)++; - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -9447,8 +9550,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, return ret; /* kekri is IMPLICIT[2] */ - } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | - ASN_CONTEXT_SPECIFIC | 2)) { + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) { (*idx)++; if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) @@ -9476,8 +9578,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, return ret; /* pwri is IMPLICIT[3] */ - } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | - ASN_CONTEXT_SPECIFIC | 3)) { + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) { #if !defined(NO_PWDBASED) && !defined(NO_SHA) (*idx)++; @@ -9509,8 +9610,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, #endif /* ori is IMPLICIT[4] */ - } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | - ASN_CONTEXT_SPECIFIC | 4)) { + } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 4)) { (*idx)++; /* found ori */ @@ -9552,6 +9652,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, word32 contentType; byte* pkiMsg = in; word32 pkiMsgSz = inSz; + byte tag; #ifndef NO_PKCS7_STREAM word32 tmpIdx = 0; long rc; @@ -9687,8 +9788,11 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, } } - if (ret == 0 && pkiMsg[(*idx)++] != - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (ret == 0 && GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + | 0)) ret = ASN_PARSE_E; if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz, @@ -9852,6 +9956,8 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, byte padLen; byte* encryptedContent = NULL; int explicitOctet; + word32 localIdx; + byte tag; if (pkcs7 == NULL) return BAD_FUNC_ARG; @@ -9985,7 +10091,11 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) != 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && tag != ASN_OCTET_STRING) { ret = ASN_PARSE_E; } @@ -10042,12 +10152,16 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, XMEMCPY(tmpIv, &pkiMsg[idx], length); idx += length; - explicitOctet = pkiMsg[idx] == - (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + explicitOctet = 0; + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + explicitOctet = 1; + } /* read encryptedContent, cont[0] */ - if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && - pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0) && + tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { ret = ASN_PARSE_E; } idx++; @@ -10058,7 +10172,12 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0 && explicitOctet) { - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + break; + } + + if (tag != ASN_OCTET_STRING) { ret = ASN_PARSE_E; break; } @@ -10716,6 +10835,8 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, word32 encodedAttribIdx = 0, encodedAttribSz = 0; byte* authAttrib = NULL; int authAttribSz = 0; + word32 localIdx; + byte tag; if (pkcs7 == NULL) return BAD_FUNC_ARG; @@ -10845,7 +10966,11 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } /* get nonce, stored in OPTIONAL parameter of AlgoID */ - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && tag != ASN_OCTET_STRING) { ret = ASN_PARSE_E; } @@ -10898,16 +11023,23 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0) { - explicitOctet = pkiMsg[idx] == - (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + explicitOctet = 0; + localIdx = idx; + if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) + explicitOctet = 1; } /* read encryptedContent, cont[0] */ - if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && - pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + if (ret == 0) { + ret = GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz); + } + + if (ret == 0 && + tag != (ASN_CONTEXT_SPECIFIC | 0) && + tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { ret = ASN_PARSE_E; } - idx++; if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { @@ -10915,7 +11047,10 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (explicitOctet) { - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + if (ret == 0 && tag != ASN_OCTET_STRING) { ret = ASN_PARSE_E; } @@ -10989,8 +11124,9 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, #endif /* may have IMPLICIT [1] authenticatedAttributes */ - if (ret == 0 && pkiMsg[idx] == - (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + localIdx = idx; + if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && + tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { encodedAttribIdx = idx; encodedAttribs = pkiMsg + idx; idx++; @@ -11098,7 +11234,10 @@ authenv_atrbend: /* get authTag OCTET STRING */ - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + if (ret == 0 && tag != ASN_OCTET_STRING) { ret = ASN_PARSE_E; } @@ -11529,6 +11668,7 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, { int ret, attribLen; word32 idx; + byte tag; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || inOutIdx == NULL) @@ -11536,9 +11676,11 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, idx = *inOutIdx; - if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) return ASN_PARSE_E; - idx++; if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -11577,6 +11719,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, byte* pkiMsg = in; word32 pkiMsgSz = inSz; + byte tag; if (pkcs7 == NULL || ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) && @@ -11653,8 +11796,10 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz = (word32)rc; #endif if (pkcs7->version != 3) { - if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED | - ASN_CONTEXT_SPECIFIC | 0)) + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) @@ -11746,7 +11891,9 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; #endif - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) @@ -11793,7 +11940,9 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, XMEMCPY(tmpIv, &pkiMsg[idx], length); idx += length; /* read encryptedContent, cont[0] */ - if (ret == 0 && pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) + if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, @@ -12144,7 +12293,10 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } /* get ContentInfo content EXPLICIT SEQUENCE */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) @@ -12185,14 +12337,20 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, pkcs7->contentOID = contentType; /* get eContent EXPLICIT SEQUENCE */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; /* get content OCTET STRING */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) + if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (tag != ASN_OCTET_STRING) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index b7f5cd5bd..cfdd4743c 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -1330,6 +1330,7 @@ static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, int curveIdx; unsigned char* point = NULL; int pointSz; + byte tag; CK_RV rv; CK_ATTRIBUTE tmpl[] = { { CKA_EC_POINT, NULL_PTR, 0 }, @@ -1360,7 +1361,9 @@ static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, if (ret == 0 && pointSz < key->dp->size * 2 + 1 + 2) ret = ASN_PARSE_E; /* Step over the OCTET_STRING wrapper. */ - if (ret == 0 && point[i++] != ASN_OCTET_STRING) + if (ret == 0 && GetASNTag(point, &i, &tag, pointSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_OCTET_STRING) ret = ASN_PARSE_E; if (ret == 0 && point[i] >= ASN_LONG_LENGTH) { if (point[i++] != (ASN_LONG_LENGTH | 1)) @@ -1690,7 +1693,9 @@ static int Pkcs11ECDSASig_Decode(const byte* in, word32 inSz, byte* sig, ret = ASN_PARSE_E; /* Check INT */ - if (ret == 0 && in[i++] != ASN_INTEGER) + if (ret == 0 && GetASNTag(in, &i, &tag, inSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_INTGER) ret = ASN_PARSE_E; if (ret == 0 && (len = in[i++]) > sz + 1) ret = ASN_PARSE_E; @@ -1712,7 +1717,9 @@ static int Pkcs11ECDSASig_Decode(const byte* in, word32 inSz, byte* sig, if (ret == 0 && i + 2 > inSz) ret = ASN_PARSE_E; /* Check INT */ - if (ret == 0 && in[i++] != ASN_INTEGER) + if (ret == 0 && GetASNTag(in, &i, &tag, inSz) != 0) + ret = ASN_PARSE_E; + if (ret == 0 && tag != ASN_INTGER) ret = ASN_PARSE_E; if (ret == 0 && (len = in[i++]) > sz + 1) ret = ASN_PARSE_E; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 008ebe2da..96a2e4c7f 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1052,6 +1052,8 @@ WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx); WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx); +WOLFSSL_LOCAL int GetASNTag(const byte* input, word32* idx, byte* tag, + word32 inputSz); WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output); WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output); WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output);