From 08a7c4590ea35498c42fed365aa8173766c7eaca Mon Sep 17 00:00:00 2001 From: Ruby Martin Date: Tue, 26 May 2026 12:10:05 -0600 Subject: [PATCH] Remove CheckOcspResponderChain and related references. Function is not compliant with RFC 6960, 4.2.2.2. remove unused vp parameter Update ChangeLog.md to include OCSP responder change --- .wolfssl_known_macro_extras | 1 - ChangeLog.md | 8 ++++ src/ocsp.c | 89 +------------------------------------ wolfcrypt/src/asn.c | 8 ++-- wolfcrypt/src/asn_orig.c | 2 +- wolfssl/ocsp.h | 2 +- 6 files changed, 16 insertions(+), 94 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index fb34d7c6f2..08f7b2b43c 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -844,7 +844,6 @@ WOLFSSL_NO_KCAPI_SHA224 WOLFSSL_NO_KTRI_ORACLE_WARNING WOLFSSL_NO_LMS_SHAKE256_256 WOLFSSL_NO_OCSP_DATE_CHECK -WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK WOLFSSL_NO_OCSP_OPTIONAL_CERTS WOLFSSL_NO_RSA_KEY_CHECK WOLFSSL_NO_SERVER_GROUPS_EXT diff --git a/ChangeLog.md b/ChangeLog.md index ef01745e95..9deacce2ce 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -46,6 +46,14 @@ per-record nonce. Scoped to TLS 1.3, non-DTLS, non-QUIC; requires `WOLF_CRYPTO_CB` and `WOLF_CRYPTO_CB_AES_SETKEY`. +* **BREAKING (RFC 6960 4.2.2.2)**: OCSP responder authorization is now + strictly enforced. Removes the non-compliant `CheckOcspResponderChain()` + fallback, which authorized any OCSP responder cert issued by an ancestor + of the target's issuer; [RFC 6960 4.2.2.2](https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.2.2) + requires direct issuance by the CA identified in the request. Also + removes the now-unused `WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK` macro and + the `vp` parameter from `CheckOcspResponder()`. + # wolfSSL Release 5.9.1 (Apr. 8, 2026) Release 5.9.1 has been developed according to wolfSSL's development and QA diff --git a/src/ocsp.c b/src/ocsp.c index 14d5eb1354..14e3bafeb9 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -21,15 +21,6 @@ #include - /* Name change compatibility layer no longer needs to be included here */ - -/* - * WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK: - * Disable looking for an authorized responder in the verification path of - * the issuer. This will make the authorized responder only look at the - * OCSP response signer and direct issuer. - */ - /* * OCSP responder missing features: * - Support for multiple requests and responses in a single OCSP exchange @@ -590,80 +581,13 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return ret; } -#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK -static int CheckOcspResponderChain(OcspEntry* single, byte* issuerNameHash, - byte* issuerKeyHash, void* vp, Signer* pendingCAs) { - /* Attempt to build a chain up to cert's issuer */ - WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; - Signer* ca = NULL; - Signer* prev = NULL; - int passed = 0; - - /* - * Relation between certs: - * CA - * / \ - * intermediate(s) cert in OCSP response - * | with OCSP key usage ext - * issuer of cert - * in OCSP request - */ - - if (issuerKeyHash == NULL) - return 0; - - /* Select CertID issuer by key hash so a same-DN / different-key trust - * anchor cannot hijack the starting point. */ - ca = GetCAByKeyHash(cm, single->issuerKeyHash); - if (ca != NULL && XMEMCMP(ca->subjectNameHash, single->issuerHash, - OCSP_DIGEST_SIZE) != 0) { - ca = NULL; - } -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (ca == NULL && pendingCAs != NULL) { - ca = findSignerByKeyHash(pendingCAs, single->issuerKeyHash); - if (ca != NULL && XMEMCMP(ca->subjectNameHash, single->issuerHash, - OCSP_DIGEST_SIZE) != 0) { - ca = NULL; - } - } -#else - (void)pendingCAs; -#endif - for (; ca != NULL && ca != prev; - prev = ca) { - Signer* parent = GetCAByName(cm, ca->issuerNameHash); -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (parent == NULL && pendingCAs != NULL) { - parent = findSignerByName(pendingCAs, ca->issuerNameHash); - } -#endif - if (parent == NULL || parent == ca) - break; - - if (XMEMCMP(parent->subjectNameHash, issuerNameHash, - OCSP_DIGEST_SIZE) == 0 && - XMEMCMP(parent->subjectKeyHash, issuerKeyHash, - KEYID_SIZE) == 0) { - WOLFSSL_MSG("\tOCSP Response signed by authorized " - "responder delegated by issuer " - "(found in chain)"); - passed = 1; - break; - } - ca = parent; - } - return passed; -} -#endif - /* Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2. Both halves * of CertID (issuerNameHash and issuerKeyHash) must match; name-only matching * would authorize a same-DN / different-key CA. issuerKeyHash may be NULL when * unavailable, which disables the delegated branch. */ int CheckOcspResponder(OcspResponse *bs, byte* subjectNameHash, byte* subjectKeyHash, byte extExtKeyUsage, byte* issuerNameHash, - byte* issuerKeyHash, void* vp) + byte* issuerKeyHash) { int ret = 0; OcspEntry* single; @@ -671,8 +595,6 @@ int CheckOcspResponder(OcspResponse *bs, byte* subjectNameHash, /* Both evaluate to enum values so can't use a pre-processor check */ WOLFSSL_ASSERT_EQ(OCSP_DIGEST_SIZE, SIGNER_DIGEST_SIZE); - (void)vp; - WOLFSSL_ENTER("CheckOcspResponder"); /* In the future if this API is used more then it could be beneficial to @@ -702,12 +624,6 @@ int CheckOcspResponder(OcspResponse *bs, byte* subjectNameHash, "delegated by issuer"); passed = 1; } -#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK - else if (vp != NULL) { - passed = CheckOcspResponderChain(single, issuerNameHash, - issuerKeyHash, vp, bs->pendingCAs); - } -#endif } if (!passed) { @@ -1111,8 +1027,7 @@ static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert, if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) { ret = CheckOcspResponder(resp, c->subjectHash, c->subjectKeyHash, c->extExtKeyUsage, c->issuerHash, - (c->ca != NULL) ? c->ca->subjectKeyHash : NULL, - st->cm); + (c->ca != NULL) ? c->ca->subjectKeyHash : NULL); } else { ret = 0; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f4ef7125ef..282e761461 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -33718,7 +33718,7 @@ static int OcspRespIdMatch(OcspResponse *resp, const byte *NameHash, } #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK -static int OcspRespCheck(OcspResponse *resp, Signer *responder, void* vp) +static int OcspRespCheck(OcspResponse *resp, Signer *responder) { OcspEntry *s; int ret; @@ -33733,7 +33733,7 @@ static int OcspRespCheck(OcspResponse *resp, Signer *responder, void* vp) ret = CheckOcspResponder(resp, responder->subjectNameHash, responder->subjectKeyHash, responder->extKeyUsage, - responder->issuerNameHash, responder->issuerKeyHash, vp); + responder->issuerNameHash, responder->issuerKeyHash); if (ret != 0) return -1; @@ -33823,7 +33823,7 @@ static int OcspCheckCert(OcspResponse *resp, int noVerify, if (ret == 0 && !noVerify) { ret = CheckOcspResponder(resp, cert->subjectHash, cert->subjectKeyHash, cert->extExtKeyUsage, cert->issuerHash, - (cert->ca != NULL) ? cert->ca->subjectKeyHash : NULL, cm); + (cert->ca != NULL) ? cert->ca->subjectKeyHash : NULL); if (ret != 0) { WOLFSSL_MSG("\tOCSP Responder certificate issuer check failed"); goto err; @@ -34044,7 +34044,7 @@ static int DecodeBasicOcspResponse(const byte* source, word32* ioIndex, } #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK if (ret == 0 && !noVerifySignature && !sigValid) { - if (OcspRespCheck(resp, ca, cm) != 0) { + if (OcspRespCheck(resp, ca) != 0) { ret = BAD_OCSP_RESPONDER; } } diff --git a/wolfcrypt/src/asn_orig.c b/wolfcrypt/src/asn_orig.c index 7db2a4eed1..156e3c0f3e 100644 --- a/wolfcrypt/src/asn_orig.c +++ b/wolfcrypt/src/asn_orig.c @@ -8905,7 +8905,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, return ASN_NO_SIGNER_E; #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK - if (OcspRespCheck(resp, ca, cm) != 0) + if (OcspRespCheck(resp, ca) != 0) return BAD_OCSP_RESPONDER; #endif InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 8778a144ec..103475c0b8 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -76,7 +76,7 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp WOLFSSL_LOCAL int CheckOcspResponder(OcspResponse *bs, byte* subjectNameHash, byte* subjectKeyHash, byte extExtKeyUsage, byte* issuerNameHash, - byte* issuerKeyHash, void* vp); + byte* issuerKeyHash); /* Allocates and initializes a WOLFSSL_OCSP object */ WOLFSSL_API WOLFSSL_OCSP* wc_NewOCSP(WOLFSSL_CERT_MANAGER* cm);