Skip to content

Instantly share code, notes, and snippets.

@vanbroup
Last active January 20, 2024 10:54
Show Gist options
  • Save vanbroup/84859cd10479ed95c64abe6fcdbdf83d to your computer and use it in GitHub Desktop.
Save vanbroup/84859cd10479ed95c64abe6fcdbdf83d to your computer and use it in GitHub Desktop.
Script to create a CA hierarchy with delegated OCSP responder certificates to test the effects on different combinations of OCSP Signing EKU settings
// certutil -urlcache * delete
// certutil -verify -user -urlfetch "Server Certificate.cer"
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"log"
"math/big"
"net/http"
"net/url"
"path"
"time"
"golang.org/x/crypto/ocsp"
)
func main() {
// Self signed root CA
rootCATemplate := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().UnixNano()),
Subject: pkix.Name{
CommonName: "Root",
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(25, 0, 0),
IsCA: true,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
}
rootKey, rootCert, err := createAndIssue(rootCATemplate, nil, nil)
if err != nil {
panic(err)
}
// ICA
iCATemplate := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().UnixNano()),
Subject: pkix.Name{
CommonName: "ICA",
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
IsCA: true,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
OCSPServer: []string{"http://localhost:8080"},
}
icaKey, icaCert, err := createAndIssue(iCATemplate, rootCert, rootKey)
if err != nil {
panic(err)
}
icaOCSPResponse, err := createOCSP(rootKey, rootCert, icaCert)
if err != nil {
panic(err)
}
// ICA2
iCA2Template := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().UnixNano()),
Subject: pkix.Name{
CommonName: "ICA 2",
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
IsCA: true,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageOCSPSigning},
OCSPServer: []string{"http://localhost:8080"},
}
ica2Key, ica2Cert, err := createAndIssue(iCA2Template, rootCert, rootKey)
if err != nil {
panic(err)
}
ica2OCSPResponse, err := createOCSP(rootKey, rootCert, ica2Cert)
if err != nil {
panic(err)
}
// overrull the OCSP response
icaOCSPResponse, err = ocsp.CreateResponse(rootCert, ica2Cert, ocsp.Response{
Status: ocsp.Revoked,
SerialNumber: icaCert.SerialNumber,
ThisUpdate: time.Now(),
NextUpdate: time.Now().AddDate(1, 0, 0),
RevokedAt: time.Now(),
RevocationReason: ocsp.KeyCompromise,
Certificate: ica2Cert,
}, ica2Key)
if err != nil {
panic(err)
}
// Server certificate
serverTemplate := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().UnixNano()),
Subject: pkix.Name{
CommonName: "Server Certificate",
},
DNSNames: []string{"localhost"},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(0, 3, 0),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
OCSPServer: []string{"http://localhost:8080"},
}
serverKey, serverCert, err := createAndIssue(serverTemplate, icaCert, icaKey)
if err != nil {
panic(err)
}
serverOCSPResponse, err := createOCSP(icaKey, icaCert, serverCert)
if err != nil {
panic(err)
}
ocspResponses := make(map[string][]byte)
ocspResponses[icaCert.SerialNumber.String()] = icaOCSPResponse
ocspResponses[ica2Cert.SerialNumber.String()] = ica2OCSPResponse
ocspResponses[serverCert.SerialNumber.String()] = serverOCSPResponse
// Verify
rootPool := x509.NewCertPool()
rootPool.AddCert(rootCert)
icaPool := x509.NewCertPool()
icaPool.AddCert(icaCert)
_, err = icaCert.Verify(x509.VerifyOptions{
Roots: rootPool,
Intermediates: icaPool,
CurrentTime: time.Now(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning},
})
if err != nil {
log.Println("Verify error:", err)
} else {
log.Println("Verify OK")
}
go startWebserver(serverKey, serverCert, icaCert)
startOCSPServer(ocspResponses)
}
func createOCSP(icaKey crypto.Signer, icaCert, cert *x509.Certificate) ([]byte, error) {
// OCSP Signing Certificate
ocspTemplate := &x509.Certificate{
SerialNumber: big.NewInt(3),
Subject: pkix.Name{
CommonName: "Delegated OCSP signing certificate for " + icaCert.Subject.CommonName,
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(0, 3, 0),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning},
}
ocspTemplate.ExtraExtensions = append(ocspTemplate.ExtraExtensions, pkix.Extension{
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5},
Value: []byte{asn1.TagNull, 0},
Critical: false,
})
ocspKey, ocspCert, err := createAndIssue(ocspTemplate, icaCert, icaKey)
if err != nil {
return nil, err
}
// Create OCSP response
ocspResponse, err := ocsp.CreateResponse(icaCert, ocspCert, ocsp.Response{
Status: ocsp.Good,
SerialNumber: cert.SerialNumber,
ThisUpdate: time.Now(),
NextUpdate: time.Now().AddDate(1, 0, 0),
Certificate: ocspCert,
}, ocspKey)
if err != nil {
return nil, err
}
return ocspResponse, nil
}
func startWebserver(key crypto.PrivateKey, cert, issuer *x509.Certificate) {
serverHandler := func(w http.ResponseWriter, req *http.Request) {
log.Printf("HTTPS | %s [%s] %s\n", req.UserAgent(), req.Method, req.RequestURI)
io.WriteString(w, "Hello, world!\n")
}
mux := http.NewServeMux()
mux.HandleFunc("/", serverHandler)
cfg := &tls.Config{Certificates: []tls.Certificate{{
Certificate: [][]byte{cert.Raw, issuer.Raw},
PrivateKey: key,
}}}
srv := &http.Server{
Addr: ":8443",
TLSConfig: cfg,
ReadTimeout: time.Minute,
WriteTimeout: time.Minute,
Handler: mux,
}
log.Println("Starting webserver on port 8443")
log.Fatal(srv.ListenAndServeTLS("", ""))
}
func startOCSPServer(response map[string][]byte) {
ocspHandler := func(w http.ResponseWriter, req *http.Request) {
log.Printf("OCSP | %s [%s] %s\n", req.UserAgent(), req.Method, req.RequestURI)
var err error
var request []byte
switch req.Method {
case http.MethodPost:
request, err = ioutil.ReadAll(req.Body)
if err != nil {
log.Println(err)
return
}
case http.MethodGet:
requestBase64, err := url.QueryUnescape(path.Base(req.URL.RawPath))
if err != nil {
log.Println(err)
return
}
request, err = base64.StdEncoding.DecodeString(requestBase64)
if err != nil {
log.Println(err)
return
}
}
or, err := ocsp.ParseRequest(request)
if err != nil {
log.Println(err)
return
}
if _, ok := response[or.SerialNumber.String()]; !ok {
log.Println("OCSP | Unkown serial number:", or.SerialNumber)
return
}
w.Header().Set("Content-Type", "application/ocsp-response")
w.Write(response[or.SerialNumber.String()])
log.Println("OCSP | Request served for serial number:", or.SerialNumber.String())
}
mux := http.NewServeMux()
mux.HandleFunc("/", ocspHandler)
srv := &http.Server{
Addr: ":8080",
ReadTimeout: time.Minute,
WriteTimeout: time.Minute,
Handler: mux,
}
log.Fatal(srv.ListenAndServe())
}
func createAndIssue(template, issuerCert *x509.Certificate, issuerKey crypto.Signer) (crypto.Signer, *x509.Certificate, error) {
private, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
if issuerKey == nil {
issuerKey = private
issuerCert = template
}
rawCert, err := x509.CreateCertificate(rand.Reader, template, issuerCert, private.Public(), issuerKey)
if err != nil {
fmt.Println(err)
return nil, nil, err
}
cert, err := x509.ParseCertificate(rawCert)
if err != nil {
return nil, nil, err
}
ioutil.WriteFile(cert.Subject.CommonName+".cer", rawCert, 0644)
fmt.Printf("Issued certificate:\n\tSubject: %s\n\tIssuer: %s\n\n", cert.Subject, cert.Issuer)
return private, cert, nil
}
@vanbroup
Copy link
Author

vanbroup commented Jul 3, 2020

With the EKU OCSP signing set in the delegated signing certificate but not in the EKU constraints of the issuing CA's, both golang Certificate.Verify (with KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning}) and Microsoft PowerShell Test-Certificate (with -EKU "1.3.6.1.5.5.7.3.4") return an invalid key usage.

See also the relevant discussions:

The script above is used to test if Windows would actually check the Extended Key Usage of the OCSP signing certificate and if it's checking the whole chain or only the certificate.

Where the Test-Certificate fails, certutil doesn't complain about the 'missing' (for the good) EKU in the issuing CA.

certutil -verify -user -urlfetch "Server Certificate.cer"
Issuer:
    CN=ICA
  Name Hash(sha1): 92cb937fa99276c33facb345474ceb9e86f63b08
  Name Hash(md5): c465a79093cbd3e975969d831c8f5055
Subject:
    CN=Server Certificate
  Name Hash(sha1): d159230ee68ebd9e7798ab9e88f310dad4e325bd
  Name Hash(md5): 66e4582482b2c4b078f6ee7bc528e01a
Cert Serial Number: 161e362b1b68dc5b

dwFlags = CA_VERIFY_FLAGS_CONSOLE_TRACE (0x20000000)
dwFlags = CA_VERIFY_FLAGS_DUMP_CHAIN (0x40000000)
ChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT (0x40000000)
HCCE_CURRENT_USER
CERT_CHAIN_POLICY_BASE
-------- CERT_CHAIN_CONTEXT --------
ChainContext.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
ChainContext.dwErrorStatus = CERT_TRUST_IS_UNTRUSTED_ROOT (0x20)
ChainContext.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
ChainContext.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

SimpleChain.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
SimpleChain.dwErrorStatus = CERT_TRUST_IS_UNTRUSTED_ROOT (0x20)
SimpleChain.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
SimpleChain.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

CertContext[0][0]: dwInfoStatus=104 dwErrorStatus=1000040
  Issuer: CN=ICA
  NotBefore: 7/3/2020 12:07 PM
  NotAfter: 10/3/2020 12:07 PM
  Subject: CN=Server Certificate
  Serial: 161e362b1b68dc5b
  SubjectAltName: DNS Name=localhost
  Cert: 8eaf79833d0c5fd641f068650e52fdb68f4ac5e1
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  OK "OCSP" Time: 0 57e99ac8360c31c50a2d972694bc5753e63d48c8
    [0.0] http://localhost:8080

  --------------------------------
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][1]: dwInfoStatus=104 dwErrorStatus=1000040
  Issuer: CN=Root
  NotBefore: 7/3/2020 12:07 PM
  NotAfter: 7/3/2030 12:07 PM
  Subject: CN=ICA
  Serial: 161e362b06e40f6f
  Cert: 5f8df874684c8ec7c43803234f5629aabfeb5d14
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  OK "OCSP" Time: 0 90559a1f55cfb873bac63902db4a327da688e7d6
    [0.0] http://localhost:8080

  --------------------------------
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][2]: dwInfoStatus=10c dwErrorStatus=20
  Issuer: CN=Root
  NotBefore: 7/3/2020 12:07 PM
  NotAfter: 7/3/2045 1:07 PM
  Subject: CN=Root
  Serial: 161e362afc62bc14
  Cert: 9cfd9fafb0bafe3e02cc168cfefc14d4ee12cdaf
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_IS_SELF_SIGNED (0x8)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_IS_UNTRUSTED_ROOT (0x20)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0 (null)
  --------------------------------

Exclude leaf cert:
  Chain: 48985ec17717946344dd1f6b2de2b50222a0bce4
Full chain:
  Chain: d9c286f8490d0b90576a9e0ce93998b714bb16fe
  Issuer: CN=ICA
  NotBefore: 7/3/2020 12:07 PM
  NotAfter: 10/3/2020 12:07 PM
  Subject: CN=Server Certificate
  Serial: 161e362b1b68dc5b
  SubjectAltName: DNS Name=localhost
  Cert: 8eaf79833d0c5fd641f068650e52fdb68f4ac5e1
A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. 0x800b0109 (-2146762487 CERT_E_UNTRUSTEDROOT)
------------------------------------
Verifies against UNTRUSTED root
Leaf certificate revocation check passed
CertUtil: -verify command completed successfully.

If we leave out the OCSP signing EKU from the delegated signing certificate and the chain, certutil does complain that that the server would be offline (it's not, and it did process the request).

certutil -verify -user -urlfetch "Server Certificate.cer"
Issuer:
    CN=ICA
  Name Hash(sha1): 92cb937fa99276c33facb345474ceb9e86f63b08
  Name Hash(md5): c465a79093cbd3e975969d831c8f5055
Subject:
    CN=Server Certificate
  Name Hash(sha1): d159230ee68ebd9e7798ab9e88f310dad4e325bd
  Name Hash(md5): 66e4582482b2c4b078f6ee7bc528e01a
Cert Serial Number: 161e35b2e7908758

dwFlags = CA_VERIFY_FLAGS_CONSOLE_TRACE (0x20000000)
dwFlags = CA_VERIFY_FLAGS_DUMP_CHAIN (0x40000000)
ChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT (0x40000000)
HCCE_CURRENT_USER
CERT_CHAIN_POLICY_BASE
-------- CERT_CHAIN_CONTEXT --------
ChainContext.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
ChainContext.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
ChainContext.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

SimpleChain.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
SimpleChain.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
SimpleChain.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

CertContext[0][0]: dwInfoStatus=104 dwErrorStatus=1000040
  Issuer: CN=ICA
  NotBefore: 7/3/2020 11:59 AM
  NotAfter: 10/3/2020 11:59 AM
  Subject: CN=Server Certificate
  Serial: 161e35b2e7908758
  SubjectAltName: DNS Name=localhost
  Cert: 482219ba272766cf597bb826c2435a1638a7dbf0
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  ??? "OCSP" Time: 0 0c7a1b14c66cda51ceeff7ee9a47b0dd8cc49456
    [0.0] http://localhost:8080

  --------------------------------
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][1]: dwInfoStatus=104 dwErrorStatus=1000040
  Issuer: CN=Root
  NotBefore: 7/3/2020 11:59 AM
  NotAfter: 7/3/2030 11:59 AM
  Subject: CN=ICA
  Serial: 161e35b2c77f4d92
  Cert: db80d8fe54546478e96c1dea6135746b49f72771
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  OK "OCSP" Time: 0 d7ab7cc27a1ad870436f31a483c0609a135492ee
    [0.0] http://localhost:8080

  --------------------------------
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][2]: dwInfoStatus=10c dwErrorStatus=0
  Issuer: CN=Root
  NotBefore: 7/3/2020 11:59 AM
  NotAfter: 7/3/2045 12:59 PM
  Subject: CN=Root
  Serial: 161e35b2c4db4153
  Cert: 55c85bfdbb6a4ff5724020ea7e1f6d7dfdc0d27b
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_IS_SELF_SIGNED (0x8)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0 (null)
  --------------------------------

Exclude leaf cert:
  Chain: 08274b8d32d704d568c1f31e88590099efb06e1c
Full chain:
  Chain: b2478a4c8805817ea1c10a3d1c01054955d84bf1
  Issuer: CN=ICA
  NotBefore: 7/3/2020 11:59 AM
  NotAfter: 10/3/2020 11:59 AM
  Subject: CN=Server Certificate
  Serial: 161e35b2e7908758
  SubjectAltName: DNS Name=localhost
  Cert: 482219ba272766cf597bb826c2435a1638a7dbf0
The revocation function was unable to check revocation because the revocation server was offline. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)
------------------------------------
Revocation check skipped -- server offline

ERROR: Verifying leaf certificate revocation status returned The revocation function was unable to check revocation because the revocation server was offline. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)
CertUtil: The revocation function was unable to check revocation because the revocation server was offline.

CertUtil: -verify command completed successfully.

@vanbroup
Copy link
Author

vanbroup commented Jul 6, 2020

To check the abuse case of this scenario I have added a second issuing CA ICA 2 with the EKU OCSP signing and used that to sign a revoked OCSP response for a certificate under ICA

[ROOT] 
          -> [ICA] -> [SERVER]
          -> [ICA 2] (used to revoke ICA)

In this case certutil fails to validate the OCSP response as the server would be offline?

certutil -verify -user -urlfetch "Server Certificate.cer"
Issuer:
    CN=ICA
  Name Hash(sha1): 92cb937fa99276c33facb345474ceb9e86f63b08
  Name Hash(md5): c465a79093cbd3e975969d831c8f5055
Subject:
    CN=Server Certificate
  Name Hash(sha1): d159230ee68ebd9e7798ab9e88f310dad4e325bd
  Name Hash(md5): 66e4582482b2c4b078f6ee7bc528e01a
Cert Serial Number: 161f21536499d05b

dwFlags = CA_VERIFY_FLAGS_CONSOLE_TRACE (0x20000000)
dwFlags = CA_VERIFY_FLAGS_DUMP_CHAIN (0x40000000)
ChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT (0x40000000)
HCCE_CURRENT_USER
CERT_CHAIN_POLICY_BASE
-------- CERT_CHAIN_CONTEXT --------
ChainContext.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
ChainContext.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
ChainContext.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

SimpleChain.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
SimpleChain.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
SimpleChain.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)

CertContext[0][0]: dwInfoStatus=104 dwErrorStatus=0
  Issuer: CN=ICA
  NotBefore: 7/6/2020 11:57 AM
  NotAfter: 10/6/2020 11:57 AM
  Subject: CN=Server Certificate
  Serial: 161f21536499d05b
  SubjectAltName: DNS Name=localhost
  Cert: dc34ec50e313073cf75b1e65514704a0f2d5b35b
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Base CRL CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  ??? "OCSP" Time: 0 9a55d3d43974980d9c9bc1695bad112e720c987d
    [0.0] http://localhost:8080

  --------------------------------
    CRL (null):
    Issuer: CN=Delegated OCSP signing certificate for ICA
    ThisUpdate: 7/6/2020 11:57 AM
    NextUpdate: 10/6/2020 11:57 AM
    CRL: fee8cd211d9b26cb125fb39a64d1ce8a39c976aa
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][1]: dwInfoStatus=104 dwErrorStatus=1000040
  Issuer: CN=Root
  NotBefore: 7/6/2020 11:57 AM
  NotAfter: 7/6/2030 11:57 AM
  Subject: CN=ICA
  Serial: 161f21532ea4bedb
  Cert: 655d5ca33709c31191487bc551d854784d6891b7
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  Element.dwErrorStatus = CERT_TRUST_REVOCATION_STATUS_UNKNOWN (0x40)
  Element.dwErrorStatus = CERT_TRUST_IS_OFFLINE_REVOCATION (0x1000000)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
Verified Issuance Policies: None
Verified Application Policies:
    1.3.6.1.5.5.7.3.2 Client Authentication
    1.3.6.1.5.5.7.3.1 Server Authentication
    1.3.6.1.5.5.7.3.9 OCSP Signing
  Revoked "OCSP" Time: 0 a37e2883d6836f9b9605a4d81ffcb7c3e679d7ef
    [0.0] http://localhost:8080

  --------------------------------
  Application[0] = 1.3.6.1.5.5.7.3.2 Client Authentication
  Application[1] = 1.3.6.1.5.5.7.3.1 Server Authentication

CertContext[0][2]: dwInfoStatus=10c dwErrorStatus=0
  Issuer: CN=Root
  NotBefore: 7/6/2020 11:57 AM
  NotAfter: 7/6/2045 12:57 PM
  Subject: CN=Root
  Serial: 161f21531553a359
  Cert: 427022afdb29e3b6b4a7d87021e42f891f4dd964
  Element.dwInfoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER (0x4)
  Element.dwInfoStatus = CERT_TRUST_IS_SELF_SIGNED (0x8)
  Element.dwInfoStatus = CERT_TRUST_HAS_PREFERRED_ISSUER (0x100)
  ----------------  Certificate AIA  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate CDP  ----------------
  No URLs "None" Time: 0 (null)
  ----------------  Certificate OCSP  ----------------
  No URLs "None" Time: 0 (null)
  --------------------------------

Exclude leaf cert:
  Chain: 110cf6bee64d0ce53a50796c5d65ada554cc5feb
Full chain:
  Chain: 1036b8c5b37fb12818bcdd9cdf82a77324fef1f1
  Issuer: CN=ICA
  NotBefore: 7/6/2020 11:57 AM
  NotAfter: 10/6/2020 11:57 AM
  Subject: CN=Server Certificate
  Serial: 161f21536499d05b
  SubjectAltName: DNS Name=localhost
  Cert: dc34ec50e313073cf75b1e65514704a0f2d5b35b
The revocation function was unable to check revocation because the revocation server was offline. 0x80092013 (-2146885613 CRYPT_E_REVOCATION_OFFLINE)
------------------------------------
Revocation check skipped -- server offline
Leaf certificate revocation check passed
CertUtil: -verify command completed successfully.

@vanbroup
Copy link
Author

vanbroup commented Jul 6, 2020

OpenSSL accepts the response:

openssl ocsp -CAfile root.pem -issuer root.pem -cert ca.pem -no_nonce -text -url http://localhost:8080
OCSP Request Data:
    Version: 1 (0x0)
    Requestor List:
        Certificate ID:
          Hash Algorithm: sha1
          Issuer Name Hash: BB14FA9683082119DC1C1FBE0D6D312AD95A7D65
          Issuer Key Hash: 99334693D848FE1E0F93B80EB31A15068A388874
          Serial Number: 161F21532EA4BEDB
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: CN = ICA 2
    Produced At: Jul  6 09:57:00 2020 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: BB14FA9683082119DC1C1FBE0D6D312AD95A7D65
      Issuer Key Hash: 99334693D848FE1E0F93B80EB31A15068A388874
      Serial Number: 161F21532EA4BEDB
    Cert Status: revoked
    Revocation Time: Jul  6 09:57:15 2020 GMT
    Revocation Reason: keyCompromise (0x1)
    This Update: Jul  6 09:57:15 2020 GMT
    Next Update: Jul  6 09:57:15 2021 GMT

    Signature Algorithm: sha256WithRSAEncryption
         72:91:eb:d0:4b:1b:82:34:b9:8b:23:e1:0f:38:b4:ea:4b:3c:
         68:6a:ac:08:08:1b:6e:9b:ff:46:c2:9d:98:42:43:d0:16:b4:
         a6:04:57:02:6d:d7:c5:38:4c:d2:4b:07:89:25:18:11:84:01:
         ad:f9:ff:05:9a:cc:91:ce:f0:03:bc:8f:ec:b7:09:fd:b6:d5:
         8a:a8:bd:07:5d:df:24:ae:0f:2e:05:1d:4a:ab:de:62:14:b0:
         98:a7:8b:06:17:c9:5b:a7:79:2a:57:ce:f1:8c:90:df:54:82:
         46:24:22:8d:94:ac:ce:03:e2:08:d5:58:de:b9:68:ca:ed:d1:
         74:21:35:eb:8a:4f:d0:54:9f:c7:7e:32:e9:97:9e:54:01:9a:
         e3:cc:06:a2:4b:55:84:93:74:5c:c8:bf:3f:12:e2:b8:08:46:
         11:6b:86:90:87:e8:41:fe:44:3e:13:6f:2a:f9:4f:f5:ca:7a:
         54:56:8a:77:75:c6:fc:c1:5c:84:95:c2:0e:d6:a8:56:af:1a:
         bc:91:73:67:b9:97:61:2e:59:df:41:61:9f:5e:2e:25:d2:95:
         2b:1a:3d:0f:13:1f:58:27:e5:68:15:ff:bc:f6:ea:08:49:e8:
         cb:e7:3f:5d:e0:ef:25:3b:36:c0:e7:31:ca:79:13:f8:e8:38:
         6e:af:1a:0e
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1594029434537339075 (0x161f21533f1d68c3)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Root
        Validity
            Not Before: Jul  6 09:57:14 2020 GMT
            Not After : Jul  6 09:57:14 2030 GMT
        Subject: CN=ICA 2
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:98:c1:2c:70:a8:70:0b:5b:dd:5d:45:d3:9a:de:
                    c8:b3:11:b2:5d:7a:69:0e:c9:44:58:5d:64:9f:c0:
                    6a:23:64:e9:f4:ce:11:db:4e:0f:02:5f:f7:35:90:
                    e2:96:31:ce:5b:c4:d9:b7:b2:5c:57:2e:91:19:00:
                    af:f5:17:e5:27:1c:80:98:46:20:ee:5b:3d:82:3d:
                    f9:e5:50:ce:91:45:45:ae:25:1d:0f:ef:8e:d8:14:
                    7d:6d:cd:95:56:1f:d9:9b:98:17:29:b2:17:2d:36:
                    95:d3:dd:2f:21:a8:b5:be:ec:70:a4:09:31:cb:f1:
                    16:a3:62:84:4c:c0:90:37:6b:af:14:15:cd:45:2e:
                    26:63:2a:2c:53:72:af:a1:c6:b9:00:b3:99:61:bb:
                    26:25:aa:b8:d8:78:fe:89:d8:53:65:0f:02:66:87:
                    89:2a:03:31:e6:99:24:ed:c4:d7:04:11:f8:60:d1:
                    31:18:96:3f:a0:ad:fa:f1:a5:bb:16:5c:5f:e2:3f:
                    6a:e0:58:4a:d4:45:d2:a4:88:ff:f3:32:7e:85:84:
                    73:7a:ca:cd:22:bc:4d:33:4c:6d:08:01:18:df:8f:
                    b3:1a:3e:f0:e0:d2:bd:45:03:62:98:7f:99:fe:be:
                    eb:3d:88:2c:f3:36:8f:86:0b:e3:b3:d7:83:52:fa:
                    b2:49
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, TLS Web Server Authentication, OCSP Signing
            X509v3 Basic Constraints: critical
                CA:TRUE
            Authority Information Access: 
                OCSP - URI:http://localhost:8080

    Signature Algorithm: sha256WithRSAEncryption
         2f:f7:4b:ed:38:0f:64:c0:34:87:88:a0:9c:55:98:9d:26:67:
         5b:1d:1c:f6:ba:9c:2c:85:95:4d:81:9d:74:aa:50:d4:55:e9:
         5e:90:c5:55:dc:63:e9:d0:56:56:22:b2:54:83:95:b8:5e:f5:
         f6:00:5f:80:db:fd:b7:d0:d5:e4:1e:ff:81:f9:55:ee:3c:71:
         12:c1:d7:4d:aa:c6:4d:59:56:38:76:8b:08:0b:cf:60:2c:3d:
         c4:38:ba:f8:b1:66:99:36:d6:b9:26:f7:0f:4e:de:1a:eb:e2:
         1e:98:38:9b:e4:d4:c9:c6:37:79:f8:50:ea:0d:17:e1:e9:f5:
         da:d7:1f:79:c4:c0:22:9f:eb:74:71:de:5b:82:83:7b:7e:43:
         98:fc:f9:65:b2:7f:fe:fe:47:0c:d4:b8:05:73:7a:c1:6b:4a:
         60:35:de:56:41:8b:f6:be:0c:a4:98:af:50:be:7f:da:1b:e2:
         2a:9f:4f:10:10:64:cf:83:92:21:65:5c:0b:d5:bd:24:35:e1:
         9b:0d:7b:de:98:91:35:c4:7c:fb:04:aa:f2:ae:01:57:1f:62:
         67:6f:92:7a:88:95:73:76:c3:a7:d9:17:b2:6c:26:b5:a4:43:
         18:56:51:12:fe:4f:b4:ad:86:be:85:da:76:91:4c:2d:f9:dd:
         20:f1:c2:0c
-----BEGIN CERTIFICATE-----
MIIDIDCCAgigAwIBAgIIFh8hUz8daMMwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UE
AxMEUm9vdDAeFw0yMDA3MDYwOTU3MTRaFw0zMDA3MDYwOTU3MTRaMBAxDjAMBgNV
BAMTBUlDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmMEscKhw
C1vdXUXTmt7IsxGyXXppDslEWF1kn8BqI2Tp9M4R204PAl/3NZDiljHOW8TZt7Jc
Vy6RGQCv9RflJxyAmEYg7ls9gj355VDOkUVFriUdD++O2BR9bc2VVh/Zm5gXKbIX
LTaV090vIai1vuxwpAkxy/EWo2KETMCQN2uvFBXNRS4mYyosU3Kvoca5ALOZYbsm
Jaq42Hj+idhTZQ8CZoeJKgMx5pkk7cTXBBH4YNExGJY/oK368aW7Flxf4j9q4FhK
1EXSpIj/8zJ+hYRzesrNIrxNM0xtCAEY34+zGj7w4NK9RQNimH+Z/r7rPYgs8zaP
hgvjs9eDUvqySQIDAQABo38wfTAOBgNVHQ8BAf8EBAMCAQYwJwYDVR0lBCAwHgYI
KwYBBQUHAwIGCCsGAQUFBwMBBggrBgEFBQcDCTAPBgNVHRMBAf8EBTADAQH/MDEG
CCsGAQUFBwEBBCUwIzAhBggrBgEFBQcwAYYVaHR0cDovL2xvY2FsaG9zdDo4MDgw
MA0GCSqGSIb3DQEBCwUAA4IBAQAv90vtOA9kwDSHiKCcVZidJmdbHRz2upwshZVN
gZ10qlDUVelekMVV3GPp0FZWIrJUg5W4XvX2AF+A2/230NXkHv+B+VXuPHESwddN
qsZNWVY4dosIC89gLD3EOLr4sWaZNta5JvcPTt4a6+IemDib5NTJxjd5+FDqDRfh
6fXa1x95xMAin+t0cd5bgoN7fkOY/Pllsn/+/kcM1LgFc3rBa0pgNd5WQYv2vgyk
mK9Qvn/aG+Iqn08QEGTPg5IhZVwL1b0kNeGbDXvemJE1xHz7BKryrgFXH2Jnb5J6
iJVzdsOn2ReybCa1pEMYVlES/k+0rYa+hdp2kUwt+d0g8cIM
-----END CERTIFICATE-----
Response verify OK
ca.pem: revoked
        This Update: Jul  6 09:57:15 2020 GMT
        Next Update: Jul  6 09:57:15 2021 GMT
        Reason: keyCompromise
        Revocation Time: Jul  6 09:57:15 2020 GMT

@vanbroup
Copy link
Author

vanbroup commented Jul 6, 2020

Like OpenSSL, ocspcheck on MacOS accepts the OCSP response issued by the ICA 2 sibling CA.

ocspcheck -vvvvvvvv -N -C root.pem chain.pem ; echo $?
Built an 75 byte ocsp request
Using http to host localhost, port 80, path /
DNS returns ::1 for localhost
Server at localhost returns:
	  [Body]=[1289 bytes]
OCSP response signature validated from localhost
OCSP response status 0 from host localhost
ocspcheck: Invalid OCSP reply: certificate is revoked
ocspcheck: Certificate revoked at: Mon Jul  6 13:02:49 2020

1

@egberts
Copy link

egberts commented Apr 11, 2022

Using your Digitorus TLS Connection online tester, I just noticed that LetsEncrypt R3 OSCP Responder is not responding (in a positive way) to the third unknown HTTP method (in 5-byte DER format, as opposed to HTTP GET or POST method).

Digitorus reported to that OSCP Responder unknown HTTP method as “unauthorized”.

Is this more a legacy issue and can be safely ignored, or not?

@vanbroup
Copy link
Author

unauthorized is a server status that is used instead of unknown, mostly for pre-produced responses as an unknown response is signed and an unauthorized status not.

@egberts
Copy link

egberts commented Apr 11, 2022

This is good to know. Thank you and keep up the good work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment