2

tl;dr

For buypass DV certs fetched by certbot I need to explicitly tell NGINX to trust buypass root cert to enable OCSP stapling. This is not the case for Let's Encrypt certificates and I cannot figure out why. I have found a way (see bellow) which seems more like a workaround than a solid solution. So I'm wondering if I'm doing anything wrong here?


Details

I have noticed that for buypass.com DV certificates (GO SSL) fetched through the ACME protocol (by certbot) NGINX fail to provide OCSP out of the box, even if such configuration works flawlessly with Let's Encrypt certs:

ssl_stapling on;
ssl_stapling_verify on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot

I need to generate a new chain which includes the root certificate (Buypass_Class_2_Root_CA.pem):

cp /etc/letsencrypt/live/example.com/
cat /etc/ssl/certs/Buypass_Class_2_Root_CA.pem fullchain.pem > ocsp-chain.pem

and explicitly direct NGINX to trust this chain:

ssl_trusted_certificate /etc/letsencrypt/live/example.com/ocsp-chain.pem;

what is more than confusing to me, is that I don't have to do this for Let's Encrypt certs and NGINX manages to provide stapled OCSP without having to generate an extra ocsp-chain.pem.


More details (update)

Just some clarifications on generated trust chains by certbot:

For Buypass:

/--------- fullchain.pem ---------\    /--- /etc/ssl/certs --\
example.com -> Buypass_Class_2_CA_5 -> Buypass_Class_2_Root_CA
               \---- chain.pem ---/

For Let's Encrypt:

/--------- fullchain.pem --------\    / /etc/ssl/certs \
example.com -> Lets_Encrypt_R3.pem -> DST_Root_CA_X3.pem
               \---- chain.pem ---/

If I run the following:

cd /etc/letsencrypt/live/example.com
# $OSCP_URL is:
#   * Let's Encrypt: http://r3.o.lencr.org
#   * Buypass:       http://ocsp.buypass.com
openssl ocsp -issuer chain.pem -cert fullchain.pem -url "${OCSP_URL}"

I get Response verify OK. Nonetheless, although nginx uses openssl under the hood which trusts all anchors under /etc/ssl/certs (in my case /usr/lib/ssl/certs -> /etc/ssl/certs), it fails to verify OCSP without the aforementioned workaround:

2611#2611: OCSP_basic_verify() failed (SSL: error:27069065:OCSP routines:OCSP_basic_verify:certificate verify error:Verify error:unable to get issuer certificate) while requesting certificate status, responder: ocsp.buypass.com, peer: 23.55.161.57:80, certificate: "/etc/letsencrypt/live/example.com/fullchain.pem"
Yan Foto
  • 131
  • 6
  • 1
    OPs examples: [working](https://crt.sh/?id=3754640697), issued by *Let's Encrypt* - [need extra configuration](https://crt.sh/?id=3829754500) , issued by *Buypass* – anx Dec 28 '20 at 17:44
  • 1
    You can pass `-text` to the `openssl ocsp` utility and it will tell you the certificate that signed the ocsp response (which is different from the certificate, for good reasons). I suspect the key to answering this is in *that* chain (ocsp response -> ocsp response -> root) – anx Dec 28 '20 at 19:02
  • @anx right to the point! Buypass uses a dedicated intermediate cert to sign OCSP **but** in my `ocsp-chain.pem` I still only include buypass root anchor and nginx manages to verify correctly! – Yan Foto Dec 28 '20 at 20:08
  • @anx btw, for some reasons unknown to me, `-text` shows no cert for Lets Encrypt :-/ Does it mean that it's equal to what I pass in `-issuer`? – Yan Foto Dec 28 '20 at 21:10

1 Answers1

1

Update

It turns out that OpenSSL does not correctly handle OCSP responses signed by a designated authority (not the issuer). Although RFC 6960 explicitly denotes that an OCSP response should be verified using only the issuer cert (which also certifies the designated authority), OpenSSL does not abide by this and requires you to explicitly include the root certificate. If you use the CLI this happens automatically (use a combination of -CAfile and -noCApath to verify this!).

Original answer

It took me a fairly long time to figure this out! The problem is not NGINX but OpenSSL. I have found out that if the the OCSP is signed by a designated responder (see RFC 6960), whose certificate is included in the OCSP response, OpenSSL fails to regard this additional certificate when verifying the response. I cannot exactly say why this problem does not arise when using the OpenSSL OCSP CLI (i.e., openssl ocsp -issuer x -cert y -url z).

Yan Foto
  • 131
  • 6