StreamSec Home  Forum Home 
 
Welcome, Guest.
Your IP: 216.73.216.150
2026-09-25 20:23:50 
 Announcements
 StreamSec Tools 4.1.1.349 - 4.1.3.357 - manual fix P01 An OCSP response is accepted from a responder the CA never authorized.
Bottom
 
Total posts: 1
 Author StreamSec Tools 4.1.1.349 - 4.1.3.357 - manual fix P01 An OCSP response is accepted from a responder the CA never authorized.
Henrick Wibell Hellström

2026-09-25 18:32:32
Registered user
WHAT GOES WRONG
A CA can let another certificate sign OCSP responses on its behalf: a
delegated responder. RFC 6960 section 4.2.2.2 allows that only for a
certificate the CA issued that INCLUDES id-kp-OCSPSigning in an
extendedKeyUsage extension. TstAbstractOcsp.VerifyResponseSignature tests
the usage with iCertificate.CheckExtKeyUsage, which answers True for a
certificate that has no extendedKeyUsage extension at all. So any
certificate the CA issued without one is accepted as a responder for that
CA, and whoever holds its key can sign OCSP responses the library accepts:
"good" for a certificate that has been revoked, or "revoked" for one that
has not. Public TLS certificates carry an extendedKeyUsage extension; many
certificates from private CAs do not. The responder certificate's validity
period is not checked either, so an expired delegate is accepted too.

The response, and the certificates in it, come from whoever sends it: the
responder, anyone who can intercept the plain-HTTP request to it, or, for a
response stapled to a TLS handshake, the server itself. From 4.1.1.350 the
TLS client checks a stapled response first, and one that verifies as
"good" ends the revocation check before a live query is made or a CRL is
consulted.

WHAT THE FIX DOES
A delegated responder is accepted only when its certificate was issued by
the CA, carries an extendedKeyUsage extension that names id-kp-OCSPSigning,
and is within its validity period. A response signed by the CA itself is
accepted as before. Where RequireSignatureCheck has been set to False, no
response signature is required at all, with or without the fix.

WHO NEEDS IT
Applications that check certificate revocation with OCSP: a TsmOcsp
assigned to the Ocsp property of the TLS components, or any other use of
TsmOcsp, TstOcsp or another TstAbstractOcsp descendant. OCSP is used only
when an application sets it up; without it this code does not run.

APPLIES TO
StreamSec Tools 4.1.1.349 through 4.1.3.357, in the unit
StreamSec.DSI.AbstractOcsp.pas. The function is the same in all of them.
4.1.3.358 and later carry the fix.

HOW TO APPLY
1. Open StreamSec.DSI.AbstractOcsp.pas.
2. Find the implementation of
       function TstAbstractOcsp.VerifyResponseSignature
   and replace it, from "function" to its final "end;", with the function
   below.
3. Rebuild the packages, and every application that uses OCSP.
The fix is pure Pascal; no assembler is involved.

-- replacement -----------------------------------------------------------------

function TstAbstractOcsp.VerifyResponseSignature(const aBasic: iBasicOCSPResponse;
                                                 const aIssuer: iCertificate): Boolean;
var
  lRID: iResponderID;
  lSigner: iCertificate;
  lCand: iCertificate;
  lMPKey: iMPPublicKey;
  i: Integer;

  function Matches(const aCert: iCertificate): Boolean;
  begin
    Result := False;
    if not Assigned(aCert) then
      Exit;
    case lRID.Choice of
      ridByName:
        Result := aCert.tbsCertificate.subject.GetStruct.Compare(lRID.AsByName.GetStruct);
      ridByKey:
        if Supports(aCert.subjectPublicKeyInfo,iMPPublicKey,lMPKey) then
          Result := lMPKey.PublicKeyIdentifier = lRID.AsByKey;
    end;
  end;

  // RFC 6960 4.2.2.2: a delegated responder's certificate must INCLUDE
  // id-kp-OCSPSigning in an extendedKeyUsage extension. CheckExtKeyUsage alone
  // answers True for a certificate with no such extension at all, so the
  // extension's presence is tested first.
  function AuthorizedToSignOCSP(const aCert: iCertificate): Boolean;
  begin
    Result := Assigned(aCert.tbsCertificate.extensions.FindExtension(evCeExtKeyUsage)) and
              aCert.CheckExtKeyUsage(id_kp_OCSPSigning);
  end;

begin
  Result := False;
  lRID := aBasic.tbsResponseData.responderID;
  if not Assigned(lRID) then
    Exit;

  // Identify the signer certificate. The issuer itself is always a candidate;
  // additional candidates are carried inside the response (a delegated, CA
  // authorized OCSP responder).
  lSigner := nil;
  if Matches(aIssuer) then
    lSigner := aIssuer
  else
    for i := 0 to aBasic.certificateCount - 1 do begin
      lCand := aBasic.certificates[i];
      if Matches(lCand) then begin
        // A delegated responder must be issued by the same CA and carry the
        // id-kp-OCSPSigning extended key usage (RFC 6960 4.2.2.2).
        if lCand.CheckSignature(aIssuer) and
           AuthorizedToSignOCSP(lCand) then begin
          lSigner := lCand;
          Break;
        end;
      end;
    end;

  if not Assigned(lSigner) then begin
    FLastError := 'OCSP response signer is not authorized by the certificate issuer';
    Exit;
  end;

  // Defend against a self referential keyHash claim: a delegated signer must
  // really be issued by the CA, hold the OCSP signing usage, and be within its
  // validity period.
  if lSigner <> aIssuer then begin
    if not (lSigner.CheckSignature(aIssuer) and
            AuthorizedToSignOCSP(lSigner)) then begin
      FLastError := 'OCSP responder certificate is not delegated by the issuer';
      Exit;
    end;
    if not lSigner.CheckValidity then begin
      FLastError := 'OCSP responder certificate is outside its validity period';
      Exit;
    end;
  end;

  Result := aBasic.CheckSignature(lSigner);
  if not Result then
    FLastError := 'OCSP response signature verification failed';
end;

--------------------------------------------------------------------------------

TESTED
A test builds OCSP responses for one certificate, signed by its CA, by a
delegate carrying id-kp-OCSPSigning, by an expired such delegate, by a
certificate the CA issued with no extendedKeyUsage, by one it issued for
serverAuth only, and by a certificate of another CA. Unpatched, 4.1.1.349
and 4.1.3.357 accept the responses signed by the certificate without
extendedKeyUsage and by the expired delegate - 4.1.3.357 also as a stapled
TLS response, "good" and "revoked" alike. Patched, both refuse them and
still accept the responses of the CA and of the proper delegate, on Win32
and Win64.
Top

:: Written with and Powered by StreamSec Tools 4.1 ::
Copyright © 2000-2026 StreamSec Handelsbolag
Forum data layer and page templates derived from the RealThinClient SDK web-forum example, Copyright © 2004-2022 Teppi Technology (MIT)