diff --git a/src/ocsp.c b/src/ocsp.c index 45780ecbda..8ded866ac7 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -727,13 +727,23 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( WOLFSSL_CERT_MANAGER* cm = NULL; int ret = -1; DerBuffer* derCert = NULL; + int dgstType; #ifdef WOLFSSL_SMALL_STACK DecodedCert *cert = NULL; #else DecodedCert cert[1]; #endif - (void)dgst; + if (dgst == NULL) { + dgstType = WC_HASH_TYPE_SHA; + } + else if (wolfSSL_EVP_get_hashinfo(dgst, &dgstType, NULL) != + WOLFSSL_SUCCESS) { + return NULL; + } + + if (dgstType != OCSP_DIGEST) + return NULL; cm = wolfSSL_CertManagerNew(); if (cm == NULL @@ -785,6 +795,7 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( goto out; } else { + certId->hashAlgoOID = wc_HashGetOID(OCSP_DIGEST); XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE); XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE); XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz); @@ -822,6 +833,78 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) wolfSSL_OCSP_RESPONSE_free(basicResponse); } +/* Calculate ancode CertID DER encoding following RFC 6960: + CertID ::= SEQUENCE { + hashAlgorithm AlgorithmIdentifier, + issuerNameHash OCTET STRING, + issuerKeyHash OCTET STRING, + serialNumber CertificateSerialNumber } +*/ +static int OcspEncodeCertID(WOLFSSL_OCSP_CERTID* id, byte* output, + word32* totalSz, word32* intSize) +{ + word32 idx = 0; + int ret; + + if (id == NULL || totalSz == NULL || intSize == NULL || + (output != NULL && (*totalSz == 0 || *totalSz <= *intSize))) + return BAD_FUNC_ARG; + + if (output != NULL) { + ret = SetSequence(*intSize, output); + if (ret < 0) + return ret; + idx += ret; + } + + ret = SetAlgoID(id->hashAlgoOID, ((output != NULL) ? output + idx : output), + oidHashType, 0); + if (ret <= 0) + return -1; + idx += ret; + + /* issuerNameHash */ + ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output)); + if (ret < 0) + return ret; + idx += ret; + if (output != NULL) + XMEMCPY(output + idx, id->issuerHash, OCSP_DIGEST_SIZE); + idx += OCSP_DIGEST_SIZE; + + /* issuerKeyHash */ + ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output)); + if (ret < 0) + return ret; + idx += ret; + if (output != NULL) + XMEMCPY(output + idx, id->issuerKeyHash, OCSP_DIGEST_SIZE); + idx += OCSP_DIGEST_SIZE; + + /* serialNumber */ + ret = SetASNInt(id->status->serialSz, id->status->serial[0], ((output != NULL) ? output + idx : output)); + if (ret < 0) + return ret; + idx += ret; + if (output != NULL) + XMEMCPY(output + idx, id->status->serial, id->status->serialSz); + idx += id->status->serialSz; + + if (output == NULL) { + *intSize = idx; + ret = SetSequence(idx, NULL); + if (ret < 0) + return ret; + idx += ret; + *totalSz = idx; + } + else if (idx != *totalSz) { + return BUFFER_E; + } + + return 0; +} + static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash, const byte* keyHash) { @@ -1284,22 +1367,59 @@ int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data) { - if (id == NULL || data == NULL) - return WOLFSSL_FAILURE; + int allocated = 0; + word32 derSz = 0; + word32 intSz = 0; + int ret; + WOLFSSL_ENTER("wolfSSL_i2d_OCSP_CERTID"); + + if (id == NULL) + return -1; - if (*data != NULL) { - XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize); - *data = *data + id->rawCertIdSize; + if (id->rawCertId != NULL) { + derSz = id->rawCertIdSize; } else { - *data = (unsigned char*)XMALLOC((size_t)id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL); + ret = OcspEncodeCertID(id, NULL, &derSz, &intSz); + if (ret != 0) { + WOLFSSL_MSG("Failed to calculate CertID size"); + return -1; + } + } + + if (data == NULL) { + return derSz; + } + + if (*data == NULL) { + /* Allocate buffer for DER encoding */ + *data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); if (*data == NULL) { - return WOLFSSL_FAILURE; + WOLFSSL_MSG("Failed to allocate memory for CertID DER encoding"); + return -1; + } + allocated = 1; + } + + if (id->rawCertId != NULL) { + XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); + } + else { + ret = OcspEncodeCertID(id, *data, &derSz, &intSz); + if (ret < 0) { + WOLFSSL_MSG("Failed to encode CertID"); + if (allocated) { + XFREE(*data, NULL, DYNAMIC_TYPE_OPENSSL); + *data = NULL; + } + return -1; } - XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize); } - return id->rawCertIdSize; + if (!allocated) + *data += derSz; + + return derSz; } WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut, @@ -1307,44 +1427,50 @@ WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut, int length) { WOLFSSL_OCSP_CERTID *cid = NULL; + int isAllocated = 0; + word32 idx = 0; + int ret; - if ((cidOut != NULL) && (derIn != NULL) && (*derIn != NULL) && - (length > 0)) { + if (derIn == NULL || *derIn == NULL || length <= 0) + return NULL; + if (cidOut != NULL && *cidOut != NULL) { cid = *cidOut; + FreeOcspEntry(cid, NULL); + } + else { + cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (cid == NULL) + return NULL; + isAllocated = 1; + } - /* If a NULL is passed we allocate the memory for the caller. */ - if (cid == NULL) { - cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(*cid), NULL, - DYNAMIC_TYPE_OPENSSL); - } - else if (cid->rawCertId != NULL) { - XFREE(cid->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL); - cid->rawCertId = NULL; - cid->rawCertIdSize = 0; - } - - if (cid != NULL) { - cid->rawCertId = (byte*)XMALLOC((size_t)length + 1, NULL, DYNAMIC_TYPE_OPENSSL); - if (cid->rawCertId != NULL) { - XMEMCPY(cid->rawCertId, *derIn, (size_t)length); - cid->rawCertIdSize = length; - - /* Per spec. advance past the data that is being returned - * to the caller. */ - *cidOut = cid; - *derIn = *derIn + length; + XMEMSET(cid, 0, sizeof(WOLFSSL_OCSP_CERTID)); + cid->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_OCSP_STATUS); + if (cid->status == NULL) { + XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + XMEMSET(cid->status, 0, sizeof(CertStatus)); + cid->ownStatus = 1; - return cid; - } + ret = OcspDecodeCertID(*derIn, &idx, length, cid); + if (ret != 0) { + FreeOcspEntry(cid, NULL); + if (isAllocated) { + XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL); } + return NULL; } - if ((cid != NULL) && ((cidOut == NULL) || (cid != *cidOut))) { - XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL); - } + *derIn += idx; - return NULL; + if (isAllocated && cidOut != NULL) + *cidOut = cid; + + return cid; } const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id( diff --git a/tests/api.c b/tests/api.c index 354b0eb7bf..6f1f5a3355 100644 --- a/tests/api.c +++ b/tests/api.c @@ -71324,7 +71324,8 @@ static int test_wolfSSL_OCSP_id_get0_info(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && \ - defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + !defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3) X509* cert = NULL; X509* issuer = NULL; OCSP_CERTID* id = NULL; @@ -71456,10 +71457,9 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void) WOLFSSL_OCSP_CERTID* certId = NULL; ExpectNotNull(certId = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, sizeof(rawCertId))); - ExpectIntEQ(certId->rawCertIdSize, sizeof(rawCertId)); if (certId != NULL) { XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL); - XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + wolfSSL_OCSP_CERTID_free(certId); } } @@ -71477,10 +71477,9 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void) ExpectNotNull(certIdGood = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, sizeof(rawCertId))); ExpectPtrEq(certIdGood, certId); - ExpectIntEQ(certId->rawCertIdSize, sizeof(rawCertId)); if (certId != NULL) { XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL); - XFREE(certId, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_OCSP_CERTID_free(certId); certId = NULL; } } @@ -71489,8 +71488,6 @@ static int test_wolfSSL_d2i_OCSP_CERTID(void) * always be returned. */ { WOLFSSL_OCSP_CERTID* certId = NULL; - ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(NULL, &rawCertIdPtr, - sizeof(rawCertId))); ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, NULL, sizeof(rawCertId))); ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, 0)); @@ -95500,6 +95497,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_ocsp_status_callback), TEST_DECL(test_ocsp_basic_verify), TEST_DECL(test_ocsp_response_parsing), + TEST_DECL(test_ocsp_certid_enc_dec), /* This test needs to stay at the end to clean up any caches allocated. */ TEST_DECL(test_wolfSSL_Cleanup) }; diff --git a/tests/api/create_ocsp_test_blobs.py b/tests/api/create_ocsp_test_blobs.py index 435d625cb3..a887efe42a 100644 --- a/tests/api/create_ocsp_test_blobs.py +++ b/tests/api/create_ocsp_test_blobs.py @@ -401,7 +401,7 @@ def create_bad_response(rd: dict) -> bytes: }, ] - with open('./tests/api/ocsp_test_blobs.h', 'w') as f: + with open('./tests/api/test_ocsp_test_blobs.h', 'w') as f: f.write( """/* * This file is generated automatically by running ./tests/api/create_ocsp_test_blobs.py. diff --git a/tests/api/test_ocsp.c b/tests/api/test_ocsp.c index a32e604de3..7d2c9fddf9 100644 --- a/tests/api/test_ocsp.c +++ b/tests/api/test_ocsp.c @@ -34,7 +34,7 @@ #include #include -#if defined(HAVE_OCSP) +#if defined(HAVE_OCSP) && !defined(NO_SHA) struct ocsp_cb_ctx { byte* response; int responseSz; @@ -158,12 +158,12 @@ int test_ocsp_response_parsing(void) return EXPECT_SUCCESS(); } -#else /* HAVE_OCSP */ +#else /* HAVE_OCSP && !NO_SHA */ int test_ocsp_response_parsing(void) { return TEST_SKIPPED; } -#endif /* HAVE_OCSP */ +#endif /* HAVE_OCSP && !NO_SHA */ #if defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) static int test_ocsp_create_x509store(WOLFSSL_X509_STORE** store, @@ -222,7 +222,7 @@ int test_ocsp_basic_verify(void) ExpectIntEQ(response->responseStatus, 0); ExpectIntEQ(response->responderIdType, OCSP_RESPONDER_ID_KEY); ExpectBufEQ(response->responderId.keyHash, cert.subjectKeyHash, - OCSP_DIGEST_SIZE); + OCSP_RESPONDER_ID_KEY_SZ); wolfSSL_OCSP_RESPONSE_free(response); /* decoding with no embedded certificates */ @@ -592,3 +592,71 @@ int test_ocsp_status_callback(void) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ !defined(WOLFSSL_NO_TLS12) \ && defined(OPENSSL_ALL) */ + +#if !defined(NO_SHA) && defined(OPENSSL_ALL) && defined(HAVE_OCSP) && \ + !defined(WOLFSSL_SM3) && !defined(WOLFSSL_SM2) +int test_ocsp_certid_enc_dec(void) +{ + EXPECT_DECLS; + WOLFSSL_OCSP_CERTID* certIdDec = NULL; + WOLFSSL_OCSP_CERTID* certId = NULL; + WOLFSSL_X509* subject = NULL; + WOLFSSL_X509* issuer = NULL; + unsigned char* temp = NULL; + unsigned char* der2 = NULL; + unsigned char* der = NULL; + int derSz = 0, derSz1 = 0; + + /* Load test certificates */ + ExpectNotNull( + subject = wolfSSL_X509_load_certificate_file( + "./certs/ocsp/intermediate1-ca-cert.pem", WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file( + "./certs/ocsp/root-ca-cert.pem", WOLFSSL_FILETYPE_PEM)); + + /* Create CERTID from certificates */ + ExpectNotNull(certId = wolfSSL_OCSP_cert_to_id(NULL, subject, issuer)); + + /* get len */ + ExpectIntGT(derSz = wolfSSL_i2d_OCSP_CERTID(certId, NULL), 0); + + /* encode it */ + ExpectIntGT(derSz1 = wolfSSL_i2d_OCSP_CERTID(certId, &der), 0); + ExpectIntEQ(derSz, derSz1); + + if (EXPECT_SUCCESS()) + temp = der2 = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); + ExpectNotNull(der2); + /* encode without allocation */ + ExpectIntGT(derSz1 = wolfSSL_i2d_OCSP_CERTID(certId, &der2), 0); + ExpectIntEQ(derSz, derSz1); + ExpectPtrEq(der2, temp + derSz); + ExpectBufEQ(der, temp, derSz); + XFREE(temp, NULL, DYNAMIC_TYPE_OPENSSL); + + /* save original */ + temp = der; + /* decode it */ + ExpectNotNull(certIdDec = wolfSSL_d2i_OCSP_CERTID(NULL, + (const unsigned char**)&der, derSz)); + /* check ptr is advanced */ + ExpectPtrEq(der, temp + derSz); + der = der2; + XFREE(temp, NULL, DYNAMIC_TYPE_OPENSSL); + + /* compare */ + ExpectIntEQ(wolfSSL_OCSP_id_cmp(certId, certIdDec), 0); + + wolfSSL_OCSP_CERTID_free(certId); + wolfSSL_OCSP_CERTID_free(certIdDec); + wolfSSL_X509_free(subject); + wolfSSL_X509_free(issuer); + + return EXPECT_SUCCESS(); +} +#else /* !NO_SHA && OPENSSL_ALL && HAVE_OCSP && !WOLFSSL_SM3 && !WOLFSSL_SM2 */ +int test_ocsp_certid_enc_dec(void) +{ + return TEST_SKIPPED; +} +#endif diff --git a/tests/api/test_ocsp.h b/tests/api/test_ocsp.h index 8ba5a634c9..55065b9d6e 100644 --- a/tests/api/test_ocsp.h +++ b/tests/api/test_ocsp.h @@ -22,6 +22,7 @@ #ifndef WOLFSSL_TEST_OCSP_H #define WOLFSSL_TEST_OCSP_H +int test_ocsp_certid_enc_dec(void); int test_ocsp_status_callback(void); int test_ocsp_basic_verify(void); int test_ocsp_response_parsing(void); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8507503d35..671f313f96 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); - 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); + ret = OcspDecodeCertIDInt(source, &idx, size, single); 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) { @@ -36950,7 +37005,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex, /* compute the hash of the name */ resp->responderIdType = OCSP_RESPONDER_ID_NAME; ret = CalcHashId_ex(source + idx, length, - resp->responderId.nameHash, WC_SHA); + resp->responderId.nameHash, OCSP_RESPONDER_ID_HASH_TYPE); if (ret != 0) return ret; idx += length; @@ -36964,7 +37019,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex, if (GetOctetString(source, &idx, &length, size) < 0) return ASN_PARSE_E; - if (length != KEYID_SIZE) + if (length != OCSP_RESPONDER_ID_KEY_SZ) return ASN_PARSE_E; resp->responderIdType = OCSP_RESPONDER_ID_KEY; XMEMCPY(resp->responderId.keyHash, source + idx, length); @@ -37027,7 +37082,7 @@ static int DecodeResponseData(byte* source, word32* ioIndex, int ret = 0; byte version; word32 dateSz = 0; - word32 responderByKeySz = KEYID_SIZE; + word32 responderByKeySz = OCSP_RESPONDER_ID_KEY_SZ; word32 idx = *ioIndex; OcspEntry* single = NULL; @@ -37070,10 +37125,11 @@ static int DecodeResponseData(byte* source, word32* ioIndex, ret = CalcHashId_ex( dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.data, dataASN[OCSPRESPDATAASN_IDX_BYNAME].data.ref.length, - resp->responderId.nameHash, WC_SHA); + resp->responderId.nameHash, OCSP_RESPONDER_ID_HASH_TYPE); } else { resp->responderIdType = OCSP_RESPONDER_ID_KEY; - if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length != KEYID_SIZE) { + if (dataASN[OCSPRESPDATAASN_IDX_BYKEY_OCT].length + != OCSP_RESPONDER_ID_KEY_SZ) { ret = ASN_PARSE_E; } else { resp->responderIdType = OCSP_RESPONDER_ID_KEY; @@ -37226,10 +37282,14 @@ enum { static int OcspRespIdMatch(OcspResponse *resp, const byte *NameHash, const byte *keyHash) { + if (resp->responderIdType == OCSP_RESPONDER_ID_INVALID) + return 0; if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) return XMEMCMP(NameHash, resp->responderId.nameHash, SIGNER_DIGEST_SIZE) == 0; - return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0; + /* OCSP_RESPONDER_ID_KEY */ + return ((int)KEYID_SIZE == OCSP_RESPONDER_ID_KEY_SZ) && + XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0; } #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK @@ -37268,7 +37328,7 @@ static Signer *OcspFindSigner(OcspResponse *resp, WOLFSSL_CERT_MANAGER *cm) if (s) return s; } - else { + else if ((int)KEYID_SIZE == OCSP_RESPONDER_ID_KEY_SZ) { s = GetCAByKeyHash(cm, resp->responderId.keyHash); if (s) return s; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 3e9387e699..15efecd5a5 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2707,6 +2707,14 @@ struct CertStatus { typedef struct OcspEntry OcspEntry; +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) +#define OCSP_DIGEST WC_HASH_TYPE_SM3 +#elif defined(NO_SHA) +#define OCSP_DIGEST WC_HASH_TYPE_SHA256 +#else +#define OCSP_DIGEST WC_HASH_TYPE_SHA +#endif + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) #define OCSP_DIGEST_SIZE WC_SM3_DIGEST_SIZE #elif defined(NO_SHA) @@ -2732,6 +2740,12 @@ struct OcspEntry WC_BITFIELD used:1; /* entry used */ }; +#define OCSP_RESPONDER_ID_KEY_SZ 20 +#if !defined(NO_SHA) +#define OCSP_RESPONDER_ID_HASH_TYPE WC_SHA +#else +#define OCSP_RESPONDER_ID_HASH_TYPE WC_SHA256 +#endif enum responderIdType { OCSP_RESPONDER_ID_INVALID = 0, OCSP_RESPONDER_ID_NAME = 1, @@ -2750,7 +2764,7 @@ struct OcspResponse { enum responderIdType responderIdType; union { - byte keyHash[KEYID_SIZE]; + byte keyHash[OCSP_RESPONDER_ID_KEY_SZ]; byte nameHash[KEYID_SIZE]; } responderId ; @@ -2817,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 */