@@ -585,7 +585,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
585585
586586#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
587587static int CheckOcspResponderChain (OcspEntry * single , byte * issuerHash ,
588- void * vp , Signer * pendingCAs ) {
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,47 +602,62 @@ static int CheckOcspResponderChain(OcspEntry* single, byte* issuerHash,
602602 * in OCSP request
603603 */
604604
605- /* End loop if no more issuers found or if we have found a self
606- * signed cert (ca == prev) */
607- 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+ }
608615#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2 )
609616 if (ca == NULL && pendingCAs != NULL ) {
610- 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+ }
611622 }
612623#else
613624 (void )pendingCAs ;
614625#endif
615626 for (; ca != NULL && ca != prev ;
616627 prev = ca ) {
617- if (XMEMCMP (issuerHash , ca -> issuerNameHash , OCSP_DIGEST_SIZE ) == 0 ) {
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 , issuerHash ,
638+ OCSP_DIGEST_SIZE ) == 0 &&
639+ XMEMCMP (parent -> subjectKeyHash , issuerKeyHash ,
640+ OCSP_DIGEST_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- ca = GetCAByName (cm , ca -> issuerNameHash );
625- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2 )
626- if (ca == NULL && pendingCAs != NULL ) {
627- ca = findSignerByName (pendingCAs , single -> issuerHash );
628- }
629- #endif
647+
648+ ca = parent ;
630649 }
631650 return passed ;
632651}
633652#endif
634653
635- /**
636- * Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2
637- * @param bs The basic OCSP response to verify
638- * @param subjectHash The subject key hash of the OCSP responder certificate
639- * @param extExtKeyUsage The extended key usage bits of the responder certificate
640- * @param issuerHash The issuer name hash of the OCSP responder certificate
641- * @param vp Unused (reserved for future use)
642- * @return 1 if the responder is authorized to sign the response, 0 otherwise
643- */
654+ /* Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2. Both halves
655+ * of CertID (issuerNameHash and issuerKeyHash) must match; name-only matching
656+ * would authorize a same-DN / different-key CA. issuerKeyHash may be NULL when
657+ * unavailable, which disables the delegated branch. */
644658int CheckOcspResponder (OcspResponse * bs , byte * subjectHash ,
645- byte extExtKeyUsage , byte * issuerHash , void * vp )
659+ byte * subjectKeyHash , byte extExtKeyUsage , byte * issuerHash ,
660+ byte * issuerKeyHash , void * vp )
646661{
647662 int ret = 0 ;
648663 OcspEntry * single ;
@@ -660,26 +675,31 @@ int CheckOcspResponder(OcspResponse *bs, byte* subjectHash,
660675 if (bs == NULL || subjectHash == NULL || issuerHash == NULL )
661676 return BAD_FUNC_ARG ;
662677
663- /* Traverse the list and check that the cert has the authority to provide
664- * an OCSP response for each entry. */
665678 for (single = bs -> single ; single != NULL ; single = single -> next ) {
666679 int passed = 0 ;
667680
668- if (XMEMCMP (subjectHash , single -> issuerHash , OCSP_DIGEST_SIZE ) == 0 ) {
681+ if (subjectKeyHash != NULL &&
682+ XMEMCMP (subjectHash , single -> issuerHash ,
683+ OCSP_DIGEST_SIZE ) == 0 &&
684+ XMEMCMP (subjectKeyHash , single -> issuerKeyHash ,
685+ OCSP_DIGEST_SIZE ) == 0 ) {
669686 WOLFSSL_MSG ("\tOCSP Response signed by issuer" );
670687 passed = 1 ;
671688 }
672689 else if ((extExtKeyUsage & EXTKEYUSE_OCSP_SIGN ) != 0 ) {
673- if (XMEMCMP (issuerHash , single -> issuerHash , OCSP_DIGEST_SIZE )
674- == 0 ) {
690+ if (issuerKeyHash != NULL &&
691+ XMEMCMP (issuerHash , single -> issuerHash ,
692+ OCSP_DIGEST_SIZE ) == 0 &&
693+ XMEMCMP (issuerKeyHash , single -> issuerKeyHash ,
694+ OCSP_DIGEST_SIZE ) == 0 ) {
675695 WOLFSSL_MSG ("\tOCSP Response signed by authorized responder "
676696 "delegated by issuer" );
677697 passed = 1 ;
678698 }
679699#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
680700 else if (vp != NULL) {
681- passed = CheckOcspResponderChain (single , issuerHash , vp ,
682- bs -> pendingCAs );
701+ passed = CheckOcspResponderChain (single , issuerHash ,
702+ issuerKeyHash , vp , bs -> pendingCAs );
683703 }
684704#endif
685705 }
@@ -1083,8 +1103,10 @@ static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
10831103 }
10841104#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
10851105 if ((flags & WOLFSSL_OCSP_NOCHECKS ) == 0 ) {
1086- ret = CheckOcspResponder (resp , c -> subjectHash , c -> extExtKeyUsage ,
1087- c -> issuerHash , st -> cm );
1106+ ret = CheckOcspResponder (resp , c -> subjectHash , c -> subjectKeyHash ,
1107+ c -> extExtKeyUsage , c -> issuerHash ,
1108+ (c -> ca != NULL ) ? c -> ca -> subjectKeyHash : NULL ,
1109+ st -> cm );
10881110 }
10891111 else {
10901112 ret = 0 ;
0 commit comments