forked from wolfSSL/wolfssl
asn: ocsp: refactor out CERT ID decoding
It will be reused in d2i_CERT_ID
This commit is contained in:
@@ -36360,17 +36360,7 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
|
|||||||
static const ASNItem singleResponseASN[] = {
|
static const ASNItem singleResponseASN[] = {
|
||||||
/* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
|
/* SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
|
||||||
/* certId */
|
/* certId */
|
||||||
/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 },
|
/* CID_SEQ */ { 1, ASN_SEQUENCE, 1, 0, 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 },
|
|
||||||
/* certStatus - CHOICE */
|
/* certStatus - CHOICE */
|
||||||
/* good [0] IMPLICIT NULL */
|
/* good [0] IMPLICIT NULL */
|
||||||
/* CS_GOOD */ { 1, ASN_CONTEXT_SPECIFIC | 0, 0, 0, 2 },
|
/* CS_GOOD */ { 1, ASN_CONTEXT_SPECIFIC | 0, 0, 0, 2 },
|
||||||
@@ -36396,12 +36386,6 @@ static const ASNItem singleResponseASN[] = {
|
|||||||
enum {
|
enum {
|
||||||
SINGLERESPONSEASN_IDX_SEQ = 0,
|
SINGLERESPONSEASN_IDX_SEQ = 0,
|
||||||
SINGLERESPONSEASN_IDX_CID_SEQ,
|
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_GOOD,
|
||||||
SINGLERESPONSEASN_IDX_CS_REVOKED,
|
SINGLERESPONSEASN_IDX_CS_REVOKED,
|
||||||
SINGLERESPONSEASN_IDX_CS_REVOKED_TIME,
|
SINGLERESPONSEASN_IDX_CS_REVOKED_TIME,
|
||||||
@@ -36416,13 +36400,139 @@ enum {
|
|||||||
|
|
||||||
/* Number of items in ASN.1 template for OCSP single response. */
|
/* Number of items in ASN.1 template for OCSP single response. */
|
||||||
#define singleResponseASN_Length (sizeof(singleResponseASN) / sizeof(ASNItem))
|
#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
|
#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,
|
static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
||||||
int wrapperSz, OcspEntry* single)
|
int wrapperSz, OcspEntry* single)
|
||||||
{
|
{
|
||||||
#ifndef WOLFSSL_ASN_TEMPLATE
|
#ifndef WOLFSSL_ASN_TEMPLATE
|
||||||
word32 idx = *ioIndex, prevIndex, oid, localIdx, certIdIdx;
|
word32 idx = *ioIndex, prevIndex, localIdx, certIdIdx;
|
||||||
int length;
|
int length;
|
||||||
int ret;
|
int ret;
|
||||||
byte tag;
|
byte tag;
|
||||||
@@ -36440,31 +36550,8 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
|||||||
if (GetSequence(source, &idx, &length, size) < 0)
|
if (GetSequence(source, &idx, &length, size) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
single->rawCertId = source + certIdIdx;
|
single->rawCertId = source + certIdIdx;
|
||||||
/* Hash algorithm */
|
ret = OcspDecodeCertIDInt(source, &idx, size, single);
|
||||||
ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size);
|
|
||||||
if (ret < 0)
|
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;
|
return ASN_PARSE_E;
|
||||||
single->rawCertIdSize = idx - certIdIdx;
|
single->rawCertIdSize = idx - certIdIdx;
|
||||||
|
|
||||||
@@ -36577,13 +36664,10 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
|||||||
#else /* WOLFSSL_ASN_TEMPLATE */
|
#else /* WOLFSSL_ASN_TEMPLATE */
|
||||||
DECL_ASNGETDATA(dataASN, singleResponseASN_Length);
|
DECL_ASNGETDATA(dataASN, singleResponseASN_Length);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
word32 ocspDigestSize = OCSP_DIGEST_SIZE;
|
|
||||||
CertStatus* cs = NULL;
|
CertStatus* cs = NULL;
|
||||||
word32 serialSz;
|
|
||||||
word32 issuerHashLen;
|
|
||||||
word32 issuerKeyHashLen;
|
|
||||||
word32 thisDateLen;
|
word32 thisDateLen;
|
||||||
word32 nextDateLen;
|
word32 nextDateLen;
|
||||||
|
word32 certIdSeqIdx;
|
||||||
|
|
||||||
(void)wrapperSz;
|
(void)wrapperSz;
|
||||||
|
|
||||||
@@ -36592,25 +36676,12 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
|||||||
CALLOC_ASNGETDATA(dataASN, singleResponseASN_Length, ret, NULL);
|
CALLOC_ASNGETDATA(dataASN, singleResponseASN_Length, ret, NULL);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Certificate Status field. */
|
|
||||||
cs = single->status;
|
cs = single->status;
|
||||||
|
|
||||||
/* Set maximum lengths for data. */
|
/* Set maximum lengths for data. */
|
||||||
issuerHashLen = OCSP_DIGEST_SIZE;
|
|
||||||
issuerKeyHashLen = OCSP_DIGEST_SIZE;
|
|
||||||
serialSz = EXTERNAL_SERIAL_SIZE;
|
|
||||||
thisDateLen = MAX_DATE_SIZE;
|
thisDateLen = MAX_DATE_SIZE;
|
||||||
nextDateLen = MAX_DATE_SIZE;
|
nextDateLen = MAX_DATE_SIZE;
|
||||||
|
|
||||||
/* Set OID type, buffers to hold data and variables to hold 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],
|
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_THISUPDATE_GT],
|
||||||
cs->thisDate, &thisDateLen);
|
cs->thisDate, &thisDateLen);
|
||||||
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_NEXTUPDATE_GT],
|
GetASN_Buffer(&dataASN[SINGLERESPONSEASN_IDX_NEXTUPDATE_GT],
|
||||||
@@ -36621,27 +36692,11 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
|
|||||||
1, source, ioIndex, size);
|
1, source, ioIndex, size);
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
single->hashAlgoOID =
|
certIdSeqIdx = 0;
|
||||||
dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum;
|
ret = OcspDecodeCertIDInt(dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.data,
|
||||||
ocspDigestSize = (word32)wc_HashGetDigestSize(
|
&certIdSeqIdx, dataASN[SINGLERESPONSEASN_IDX_CID_SEQ].data.ref.length, single);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
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. */
|
/* Determine status by which item was found. */
|
||||||
if (dataASN[SINGLERESPONSEASN_IDX_CS_GOOD].tag != 0) {
|
if (dataASN[SINGLERESPONSEASN_IDX_CS_GOOD].tag != 0) {
|
||||||
|
@@ -2831,7 +2831,8 @@ WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output,
|
|||||||
|
|
||||||
|
|
||||||
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp);
|
WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp);
|
||||||
|
WOLFSSL_LOCAL int OcspDecodeCertID(const byte* input, word32* inOutIdx, word32 inSz,
|
||||||
|
OcspEntry* entry);
|
||||||
|
|
||||||
#endif /* HAVE_OCSP */
|
#endif /* HAVE_OCSP */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user