@@ -584,8 +584,8 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
584584}
585585
586586#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
587- static int CheckOcspResponderChain (OcspEntry * single , byte * issuerHash ,
588- void * vp , Signer * pendingCAs ) {
587+ static int CheckOcspResponderChain (OcspEntry * single , byte * issuerNameHash ,
588+ byte * issuerKeyHash , void * vp , Signer * pendingCAs ) {
589589 /* Attempt to build a chain up to cert's issuer */
590590 WOLFSSL_CERT_MANAGER * cm = (WOLFSSL_CERT_MANAGER * )vp ;
591591 Signer * ca = NULL ;
@@ -602,54 +602,61 @@ static int CheckOcspResponderChain(OcspEntry* single, byte* issuerHash,
602602 * in OCSP request
603603 */
604604
605- /* Walk up the issuer chain from the responder's direct issuer toward a
606- * self-signed root, capturing prev before reassigning ca so the
607- * (ca == prev) self-signed termination check is meaningful. */
608- ca = GetCAByName (cm , single -> issuerHash );
605+ if (issuerKeyHash == NULL )
606+ return 0 ;
607+
608+ /* Select CertID issuer by key hash so a same-DN / different-key trust
609+ * anchor cannot hijack the starting point. */
610+ ca = GetCAByKeyHash (cm , single -> issuerKeyHash );
611+ if (ca != NULL && XMEMCMP (ca -> subjectNameHash , single -> issuerHash ,
612+ OCSP_DIGEST_SIZE ) != 0 ) {
613+ ca = NULL ;
614+ }
609615#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2 )
610616 if (ca == NULL && pendingCAs != NULL ) {
611- ca = findSignerByName (pendingCAs , single -> issuerHash );
617+ ca = findSignerByKeyHash (pendingCAs , single -> issuerKeyHash );
618+ if (ca != NULL && XMEMCMP (ca -> subjectNameHash , single -> issuerHash ,
619+ OCSP_DIGEST_SIZE ) != 0 ) {
620+ ca = NULL ;
621+ }
612622 }
613623#else
614624 (void )pendingCAs ;
615625#endif
616- while (ca != NULL ) {
617- if (XMEMCMP (issuerHash , ca -> issuerNameHash , OCSP_DIGEST_SIZE ) == 0 ) {
626+ for (; ca != NULL && ca != prev ;
627+ prev = ca ) {
628+ Signer * parent = GetCAByName (cm , ca -> issuerNameHash );
629+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2 )
630+ if (parent == NULL && pendingCAs != NULL ) {
631+ parent = findSignerByName (pendingCAs , ca -> issuerNameHash );
632+ }
633+ #endif
634+ if (parent == NULL || parent == ca )
635+ break ;
636+
637+ if (XMEMCMP (parent -> subjectNameHash , issuerNameHash ,
638+ OCSP_DIGEST_SIZE ) == 0 &&
639+ XMEMCMP (parent -> subjectKeyHash , issuerKeyHash ,
640+ KEYID_SIZE ) == 0 ) {
618641 WOLFSSL_MSG ("\tOCSP Response signed by authorized "
619642 "responder delegated by issuer "
620643 "(found in chain)" );
621644 passed = 1 ;
622645 break ;
623646 }
624- prev = ca ;
625- ca = GetCAByName (cm , prev -> issuerNameHash );
626- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2 )
627- /* Look up by the in-flight name (prev's issuer), not by
628- * single->issuerHash; the latter would re-anchor the pendingCAs
629- * walk to the bottom of the chain on every iteration. */
630- if (ca == NULL && pendingCAs != NULL ) {
631- ca = findSignerByName (pendingCAs , prev -> issuerNameHash );
632- }
633- #endif
634- if (ca == prev ) {
635- break ;
636- }
647+ ca = parent ;
637648 }
638649 return passed ;
639650}
640651#endif
641652
642- /**
643- * Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2
644- * @param bs The basic OCSP response to verify
645- * @param subjectHash The subject key hash of the OCSP responder certificate
646- * @param extExtKeyUsage The extended key usage bits of the responder certificate
647- * @param issuerHash The issuer name hash of the OCSP responder certificate
648- * @param vp Unused (reserved for future use)
649- * @return 1 if the responder is authorized to sign the response, 0 otherwise
650- */
651- int CheckOcspResponder (OcspResponse * bs , byte * subjectHash ,
652- byte extExtKeyUsage , byte * issuerHash , void * vp )
653+ /* Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2. Both halves
654+ * of CertID (issuerNameHash and issuerKeyHash) must match; name-only matching
655+ * would authorize a same-DN / different-key CA. issuerKeyHash may be NULL when
656+ * unavailable, which disables the delegated branch. */
657+ int CheckOcspResponder (OcspResponse * bs , byte * subjectNameHash ,
658+ byte * subjectKeyHash , byte extExtKeyUsage , byte * issuerNameHash ,
659+ byte * issuerKeyHash , void * vp )
653660{
654661 int ret = 0 ;
655662 OcspEntry * single ;
@@ -664,29 +671,34 @@ int CheckOcspResponder(OcspResponse *bs, byte* subjectHash,
664671 /* In the future if this API is used more then it could be beneficial to
665672 * implement calling InitDecodedCert and ParseCertRelative here
666673 * automatically when cert == NULL. */
667- if (bs == NULL || subjectHash == NULL || issuerHash == NULL )
674+ if (bs == NULL || subjectNameHash == NULL || issuerNameHash == NULL )
668675 return BAD_FUNC_ARG ;
669676
670- /* Traverse the list and check that the cert has the authority to provide
671- * an OCSP response for each entry. */
672677 for (single = bs -> single ; single != NULL ; single = single -> next ) {
673678 int passed = 0 ;
674679
675- if (XMEMCMP (subjectHash , single -> issuerHash , OCSP_DIGEST_SIZE ) == 0 ) {
680+ if (subjectKeyHash != NULL &&
681+ XMEMCMP (subjectNameHash , single -> issuerHash ,
682+ OCSP_DIGEST_SIZE ) == 0 &&
683+ XMEMCMP (subjectKeyHash , single -> issuerKeyHash ,
684+ KEYID_SIZE ) == 0 ) {
676685 WOLFSSL_MSG ("\tOCSP Response signed by issuer" );
677686 passed = 1 ;
678687 }
679688 else if ((extExtKeyUsage & EXTKEYUSE_OCSP_SIGN ) != 0 ) {
680- if (XMEMCMP (issuerHash , single -> issuerHash , OCSP_DIGEST_SIZE )
681- == 0 ) {
689+ if (issuerKeyHash != NULL &&
690+ XMEMCMP (issuerNameHash , single -> issuerHash ,
691+ OCSP_DIGEST_SIZE ) == 0 &&
692+ XMEMCMP (issuerKeyHash , single -> issuerKeyHash ,
693+ KEYID_SIZE ) == 0 ) {
682694 WOLFSSL_MSG ("\tOCSP Response signed by authorized responder "
683695 "delegated by issuer" );
684696 passed = 1 ;
685697 }
686698#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
687699 else if (vp != NULL) {
688- passed = CheckOcspResponderChain (single , issuerHash , vp ,
689- bs -> pendingCAs );
700+ passed = CheckOcspResponderChain (single , issuerNameHash ,
701+ issuerKeyHash , vp , bs -> pendingCAs );
690702 }
691703#endif
692704 }
@@ -1090,8 +1102,10 @@ static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
10901102 }
10911103#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
10921104 if ((flags & WOLFSSL_OCSP_NOCHECKS ) == 0 ) {
1093- ret = CheckOcspResponder (resp , c -> subjectHash , c -> extExtKeyUsage ,
1094- c -> issuerHash , st -> cm );
1105+ ret = CheckOcspResponder (resp , c -> subjectHash , c -> subjectKeyHash ,
1106+ c -> extExtKeyUsage , c -> issuerHash ,
1107+ (c -> ca != NULL ) ? c -> ca -> subjectKeyHash : NULL ,
1108+ st -> cm );
10951109 }
10961110 else {
10971111 ret = 0 ;
0 commit comments