diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8792d382a..671f313f9 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -36360,17 +36360,7 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value, static const ASNItem singleResponseASN[] = { /* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 }, /* certId */ -/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 }, - /* hashAlgorithm */ -/* CID_HASHALGO_SEQ */ { 2, ASN_SEQUENCE, 1, 1, 0 }, -/* CID_HASHALGO_OID */ { 3, ASN_OBJECT_ID, 0, 0, 0 }, -/* CID_HASHALGO_NULL */ { 3, ASN_TAG_NULL, 0, 0, 1 }, - /* issuerNameHash */ -/* CID_ISSUERHASH */ { 2, ASN_OCTET_STRING, 0, 0, 0 }, - /* issuerKeyHash */ -/* CID_ISSUERKEYHASH */ { 2, ASN_OCTET_STRING, 0, 0, 0 }, - /* serialNumber */ -/* CID_SERIAL */ { 2, ASN_INTEGER, 0, 0, 0 }, +/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 0 }, /* certStatus - CHOICE */ /* good [0] IMPLICIT NULL */ /* CS_GOOD */ { 1, ASN_CONTEXT_SPECIFIC | 0, 0, 0, 2 }, @@ -36396,12 +36386,6 @@ static const ASNItem singleResponseASN[] = { enum { SINGLERESPONSEASN_IDX_SEQ = 0, SINGLERESPONSEASN_IDX_CID_SEQ, - SINGLERESPONSEASN_IDX_CID_HASHALGO_SEQ, - SINGLERESPONSEASN_IDX_CID_HASHALGO_OID, - SINGLERESPONSEASN_IDX_CID_HASHALGO_NULL, - SINGLERESPONSEASN_IDX_CID_ISSUERHASH, - SINGLERESPONSEASN_IDX_CID_ISSUERKEYHASH, - SINGLERESPONSEASN_IDX_CID_SERIAL, SINGLERESPONSEASN_IDX_CS_GOOD, SINGLERESPONSEASN_IDX_CS_REVOKED, SINGLERESPONSEASN_IDX_CS_REVOKED_TIME, @@ -36416,13 +36400,139 @@ enum { /* Number of items in ASN.1 template for OCSP single response. */ #define singleResponseASN_Length (sizeof(singleResponseASN) / sizeof(ASNItem)) + +static const ASNItem certIDASNItems[] = { + /* hashAlgorithm */ +/* CID_HASHALGO_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 }, +/* CID_HASHALGO_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 }, +/* CID_HASHALGO_NULL */ { 1, ASN_TAG_NULL, 0, 0, 1 }, + /* issuerNameHash */ +/* CID_ISSUERHASH */ { 0, ASN_OCTET_STRING, 0, 0, 0 }, + /* issuerKeyHash */ +/* CID_ISSUERKEYHASH */ { 0, ASN_OCTET_STRING, 0, 0, 0 }, + /* serialNumber */ +/* CID_SERIAL */ { 0, ASN_INTEGER, 0, 0, 0 }, +}; + +enum { + CERTIDASN_IDX_CID_HASHALGO_SEQ, + CERTIDASN_IDX_CID_HASHALGO_OID, + CERTIDASN_IDX_CID_HASHALGO_NULL, + CERTIDASN_IDX_CID_ISSUERHASH, + CERTIDASN_IDX_CID_ISSUERKEYHASH, + CERTIDASN_IDX_CID_SERIAL, +}; + +#define certidasn_Length (sizeof(certIDASNItems) / sizeof(ASNItem)) #endif +#ifndef WOLFSSL_ASN_TEMPLATE +static int OcspDecodeCertIDInt(const byte* input, word32* inOutIdx, word32 inSz, + OcspEntry* entry) +{ + int length; + word32 oid; + int ret; + /* Hash algorithm */ + ret = GetAlgoId(input, inOutIdx, &oid, oidHashType, inSz); + if (ret < 0) + return ret; + entry->hashAlgoOID = oid; + /* Save reference to the hash of CN */ + ret = GetOctetString(input, inOutIdx, &length, inSz); + if (ret < 0) + return ret; + if (length != OCSP_DIGEST_SIZE) + return ASN_PARSE_E; + XMEMCPY(entry->issuerHash, input + *inOutIdx, length); + *inOutIdx += length; + /* Save reference to the hash of the issuer public key */ + ret = GetOctetString(input, inOutIdx, &length, inSz); + if (ret < 0) + return ret; + if (length != OCSP_DIGEST_SIZE) + return ASN_PARSE_E; + XMEMCPY(entry->issuerKeyHash, input + *inOutIdx, length); + *inOutIdx += length; + + /* Get serial number */ + if (wc_GetSerialNumber(input, inOutIdx, entry->status->serial, + &entry->status->serialSz, inSz) < 0) + return ASN_PARSE_E; + return 0; +} +#else +static int OcspDecodeCertIDInt(const byte* input, word32* inOutIdx, word32 inSz, + OcspEntry* entry) +{ + DECL_ASNGETDATA(dataASN, certidasn_Length); + word32 issuerKeyHashLen = OCSP_DIGEST_SIZE; + word32 issuerHashLen = OCSP_DIGEST_SIZE; + word32 serialSz = EXTERNAL_SERIAL_SIZE; + word32 digestSz; + int ret = 0; + + WOLFSSL_ENTER("DecodeCertIdTemplate"); + CALLOC_ASNGETDATA(dataASN, certidasn_Length, ret, NULL); + if (ret != 0) + return ret; + + GetASN_OID(&dataASN[CERTIDASN_IDX_CID_HASHALGO_OID], oidHashType); + GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_ISSUERHASH], entry->issuerHash, + &issuerHashLen); + GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_ISSUERKEYHASH], + entry->issuerKeyHash, &issuerKeyHashLen); + GetASN_Buffer(&dataASN[CERTIDASN_IDX_CID_SERIAL], entry->status->serial, + &serialSz); + ret = GetASN_Items(certIDASNItems, dataASN, certidasn_Length, + 1, input, inOutIdx, inSz); + if (ret != 0) { + goto out; + } + entry->status->serialSz = serialSz; + entry->hashAlgoOID = + dataASN[CERTIDASN_IDX_CID_HASHALGO_OID].data.oid.sum; + digestSz = wc_HashGetDigestSize(wc_OidGetHash(entry->hashAlgoOID)); + if (issuerKeyHashLen != digestSz || issuerHashLen != digestSz) { + ret = ASN_PARSE_E; + goto out; + } +out: + FREE_ASNGETDATA(dataASN, NULL); + return ret; +} +#endif + +int OcspDecodeCertID(const byte *input, word32 *inOutIdx, word32 inSz, + OcspEntry *entry) +{ + word32 seqIdx = 0; + int len = inSz; + int ret; + +#ifndef WOLFSSL_ASN_TEMPLATE + ret = GetSequence(input, inOutIdx, &len, inSz); +#else + ret = GetASN_Sequence(input, inOutIdx, &len, inSz, 0); +#endif + if (ret < 0) + return ASN_PARSE_E; + ret = OcspDecodeCertIDInt(input + *inOutIdx, &seqIdx, len, entry); + if (ret < 0) + return ASN_PARSE_E; + if (seqIdx != (word32)len) + return ASN_PARSE_E; + *inOutIdx += len; + + return 0; +} + + static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, int wrapperSz, OcspEntry* single) { #ifndef WOLFSSL_ASN_TEMPLATE - word32 idx = *ioIndex, prevIndex, oid, localIdx, certIdIdx; + word32 idx = *ioIndex, prevIndex, localIdx, certIdIdx; int length; int ret; byte tag; @@ -36440,31 +36550,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; single->rawCertId = source + certIdIdx; - /* Hash algorithm */ - ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size); + ret = OcspDecodeCertIDInt(source, &idx, size, single); if (ret < 0) - return ret; - single->hashAlgoOID = oid; - /* Save reference to the hash of CN */ - ret = GetOctetString(source, &idx, &length, size); - if (ret < 0) - return ret; - if (length > (int)sizeof(single->issuerHash)) - return BUFFER_E; - XMEMCPY(single->issuerHash, source + idx, length); - idx += length; - /* Save reference to the hash of the issuer public key */ - ret = GetOctetString(source, &idx, &length, size); - if (ret < 0) - return ret; - if (length > (int)sizeof(single->issuerKeyHash)) - return BUFFER_E; - XMEMCPY(single->issuerKeyHash, source + idx, length); - idx += length; - - /* Get serial number */ - if (wc_GetSerialNumber(source, &idx, single->status->serial, - &single->status->serialSz, size) < 0) return ASN_PARSE_E; single->rawCertIdSize = idx - certIdIdx; @@ -36577,13 +36664,10 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, #else /* WOLFSSL_ASN_TEMPLATE */ DECL_ASNGETDATA(dataASN, singleResponseASN_Length); int ret = 0; - word32 ocspDigestSize = OCSP_DIGEST_SIZE; CertStatus* cs = NULL; - word32 serialSz; - word32 issuerHashLen; - word32 issuerKeyHashLen; word32 thisDateLen; word32 nextDateLen; + word32 certIdSeqIdx; (void)wrapperSz; @@ -36592,25 +36676,12 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, CALLOC_ASNGETDATA(dataASN, singleResponseASN_Length, ret, NULL); if (ret == 0) { - /* Certificate Status field. */ cs = single->status; - /* Set maximum lengths for data. */ - issuerHashLen = OCSP_DIGEST_SIZE; - issuerKeyHashLen = OCSP_DIGEST_SIZE; - serialSz = EXTERNAL_SERIAL_SIZE; thisDateLen = MAX_DATE_SIZE; nextDateLen = MAX_DATE_SIZE; /* Set OID type, buffers to hold data and variables to hold size. */ - GetASN_OID(&dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID], - oidHashType); - GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_ISSUERHASH], - single->issuerHash, &issuerHashLen); - GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_ISSUERKEYHASH], - single->issuerKeyHash, &issuerKeyHashLen); - GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_CID_SERIAL], cs->serial, - &serialSz); GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_THISUPDATE_GT], cs->thisDate, &thisDateLen); GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_NEXTUPDATE_GT], @@ -36621,27 +36692,11 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size, 1, source, ioIndex, size); } if (ret == 0) { - single->hashAlgoOID = - dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum; - ocspDigestSize = (word32)wc_HashGetDigestSize( - wc_OidGetHash((int)single->hashAlgoOID)); - } - /* Validate the issuer hash length is the size required. */ - if ((ret == 0) && (issuerHashLen != ocspDigestSize)) { - ret = ASN_PARSE_E; - } - /* Validate the issuer key hash length is the size required. */ - if (ret == 0) { - if (issuerKeyHashLen != ocspDigestSize) { - ret = ASN_PARSE_E; - } + certIdSeqIdx = 0; + ret = OcspDecodeCertIDInt(dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.data, + &certIdSeqIdx, dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.length, single); } if (ret == 0) { - /* Store serial size. */ - cs->serialSz = (int)serialSz; - /* Set the hash algorithm OID */ - single->hashAlgoOID = - dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum; /* Determine status by which item was found. */ if (dataASN[SINGLERESPONSEASN_IDX_CS_GOOD].tag != 0) { diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 798d013f4..15efecd5a 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2831,7 +2831,8 @@ WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp); - +WOLFSSL_LOCAL int OcspDecodeCertID(const byte* input, word32* inOutIdx, word32 inSz, + OcspEntry* entry); #endif /* HAVE_OCSP */