Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 53 additions & 31 deletions src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,

#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
static int CheckOcspResponderChain(OcspEntry* single, byte* issuerHash,
void* vp, Signer* pendingCAs) {
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;
Expand All @@ -602,47 +602,62 @@ static int CheckOcspResponderChain(OcspEntry* single, byte* issuerHash,
* in OCSP request
*/

/* End loop if no more issuers found or if we have found a self
* signed cert (ca == prev) */
ca = GetCAByName(cm, single->issuerHash);
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 = findSignerByName(pendingCAs, single->issuerHash);
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) {
if (XMEMCMP(issuerHash, ca->issuerNameHash, OCSP_DIGEST_SIZE) == 0) {
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, issuerHash,
OCSP_DIGEST_SIZE) == 0 &&
XMEMCMP(parent->subjectKeyHash, issuerKeyHash,
OCSP_DIGEST_SIZE) == 0) {
Comment thread
julek-wolfssl marked this conversation as resolved.
Outdated
WOLFSSL_MSG("\tOCSP Response signed by authorized "
"responder delegated by issuer "
"(found in chain)");
passed = 1;
break;
}
ca = GetCAByName(cm, ca->issuerNameHash);
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
if (ca == NULL && pendingCAs != NULL) {
ca = findSignerByName(pendingCAs, single->issuerHash);
}
#endif

ca = parent;
}
return passed;
}
#endif

/**
* Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2
* @param bs The basic OCSP response to verify
* @param subjectHash The subject key hash of the OCSP responder certificate
* @param extExtKeyUsage The extended key usage bits of the responder certificate
* @param issuerHash The issuer name hash of the OCSP responder certificate
* @param vp Unused (reserved for future use)
* @return 1 if the responder is authorized to sign the response, 0 otherwise
*/
/* 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* subjectHash,
byte extExtKeyUsage, byte* issuerHash, void* vp)
byte* subjectKeyHash, byte extExtKeyUsage, byte* issuerHash,
byte* issuerKeyHash, void* vp)
{
int ret = 0;
OcspEntry* single;
Expand All @@ -660,26 +675,31 @@ int CheckOcspResponder(OcspResponse *bs, byte* subjectHash,
if (bs == NULL || subjectHash == NULL || issuerHash == NULL)
return BAD_FUNC_ARG;

/* Traverse the list and check that the cert has the authority to provide
* an OCSP response for each entry. */
for (single = bs->single; single != NULL; single = single->next) {
int passed = 0;

if (XMEMCMP(subjectHash, single->issuerHash, OCSP_DIGEST_SIZE) == 0) {
if (subjectKeyHash != NULL &&
XMEMCMP(subjectHash, single->issuerHash,
OCSP_DIGEST_SIZE) == 0 &&
XMEMCMP(subjectKeyHash, single->issuerKeyHash,
OCSP_DIGEST_SIZE) == 0) {
Comment thread
julek-wolfssl marked this conversation as resolved.
Outdated
WOLFSSL_MSG("\tOCSP Response signed by issuer");
passed = 1;
}
else if ((extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) != 0) {
if (XMEMCMP(issuerHash, single->issuerHash, OCSP_DIGEST_SIZE)
== 0) {
if (issuerKeyHash != NULL &&
XMEMCMP(issuerHash, single->issuerHash,
OCSP_DIGEST_SIZE) == 0 &&
XMEMCMP(issuerKeyHash, single->issuerKeyHash,
OCSP_DIGEST_SIZE) == 0) {
WOLFSSL_MSG("\tOCSP Response signed by authorized responder "
"delegated by issuer");
passed = 1;
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
else if (vp != NULL) {
passed = CheckOcspResponderChain(single, issuerHash, vp,
bs->pendingCAs);
passed = CheckOcspResponderChain(single, issuerHash,
issuerKeyHash, vp, bs->pendingCAs);
}
#endif
}
Expand Down Expand Up @@ -1083,8 +1103,10 @@ static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) {
ret = CheckOcspResponder(resp, c->subjectHash, c->extExtKeyUsage,
c->issuerHash, st->cm);
ret = CheckOcspResponder(resp, c->subjectHash, c->subjectKeyHash,
c->extExtKeyUsage, c->issuerHash,
(c->ca != NULL) ? c->ca->subjectKeyHash : NULL,
st->cm);
}
else {
ret = 0;
Expand Down
30 changes: 16 additions & 14 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -22546,17 +22546,15 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm,
}

#ifdef HAVE_OCSP
if (type != CA_TYPE &&
type != TRUSTED_PEER_TYPE) {
/* Need the CA's public key hash for OCSP */
if (cert->ca) {
XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
KEYID_SIZE);
}
else if (cert->selfSigned) {
XMEMCPY(cert->issuerKeyHash, cert->subjectKeyHash,
KEYID_SIZE);
}
/* Needed for OCSP requests, and for binding responder authorization
* to CertID's issuerKeyHash when this cert becomes a Signer. */
if (cert->ca) {
XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
KEYID_SIZE);
}
else if (cert->selfSigned) {
XMEMCPY(cert->issuerKeyHash, cert->subjectKeyHash,
KEYID_SIZE);
}
#endif /* HAVE_OCSP */
}
Expand Down Expand Up @@ -22859,6 +22857,8 @@ int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der)
#ifdef HAVE_OCSP
XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
KEYID_SIZE);
XMEMCPY(signer->issuerKeyHash, cert->issuerKeyHash,
KEYID_SIZE);
#endif
signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
: 0xFFFF;
Expand Down Expand Up @@ -32876,7 +32876,8 @@ static int OcspRespCheck(OcspResponse *resp, Signer *responder, void* vp)
return -1;

ret = CheckOcspResponder(resp, responder->subjectNameHash,
responder->extKeyUsage, responder->issuerNameHash, vp);
responder->subjectKeyHash, responder->extKeyUsage,
responder->issuerNameHash, responder->issuerKeyHash, vp);
if (ret != 0)
return -1;

Expand Down Expand Up @@ -32964,8 +32965,9 @@ static int OcspCheckCert(OcspResponse *resp, int noVerify,

#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
if (ret == 0 && !noVerify) {
ret = CheckOcspResponder(resp, cert->subjectHash, cert->extExtKeyUsage,
cert->issuerHash, cm);
ret = CheckOcspResponder(resp, cert->subjectHash, cert->subjectKeyHash,
cert->extExtKeyUsage, cert->issuerHash,
(cert->ca != NULL) ? cert->ca->subjectKeyHash : NULL, cm);
if (ret != 0) {
WOLFSSL_MSG("\tOCSP Responder certificate issuer check failed");
goto err;
Expand Down
3 changes: 2 additions & 1 deletion wolfssl/ocsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int resp
void* heap);

WOLFSSL_LOCAL int CheckOcspResponder(OcspResponse *bs, byte* subjectHash,
byte extExtKeyUsage, byte* issuerHash, void* vp);
byte* subjectKeyHash, byte extExtKeyUsage, byte* issuerHash,
byte* issuerKeyHash, void* vp);
Comment thread
julek-wolfssl marked this conversation as resolved.
Outdated

/* Allocates and initializes a WOLFSSL_OCSP object */
WOLFSSL_API WOLFSSL_OCSP* wc_NewOCSP(WOLFSSL_CERT_MANAGER* cm);
Expand Down
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/asn.h
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,7 @@ struct Signer {
#endif
#ifdef HAVE_OCSP
byte subjectKeyHash[KEYID_SIZE];
byte issuerKeyHash[KEYID_SIZE]; /* key hash of verifying parent CA */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the issuer of the cert we are verifying? is this the root CA of the chain whose leaf certificate we are verifying?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified comment.

#endif
#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL)
byte serialHash[SIGNER_DIGEST_SIZE]; /* serial number hash */
Expand Down
Loading