While debugging a problem with OCSP, I had to sit down and understand what it really does and why. So What is OCSP, and why do we use it?
What is OCSP
When we establish a secure connection using the standard SSL mechanism, we trust digital certificates. How can we trust them? Our vendor, for example Microsoft or Red Hat or Mozilla with the Firefox web browser, has a list of certificate authorities (CA) that it trusts, and provides a bundle of these certificates with the software. So when we surf to our online bank, and receive a certificate that is signed by a listed CA, the web browser can check that the signature matches. So far, so good.
From time to time, a certificate might be revoked. Reasons for this could span from security breaches to simply organizational changes. But a certificate that is already signed and delivered to us, is still valid until we are told about the revocation. And there is no automation here. So there is need for a mechanism where we can ask the CA if the certificate is still valid. This is what OCSP does. The CA provides a web service where a user (like a web browser) can look up given certificate, and check that it is not revoked. The response is signed by the CA, and is valid for a few days, to avoid hammering the service for each and every request.
Most web browsers do this automatically, so for your day to day online banking and webmail cruising, you may feel quite sure that you will be warned if a certificate is revoked.
OCSP Stapling
To offload the OCSP service on a CA, there is another mechanism, OCSP Stapling. A web server might download and cache the OCSP information from the CA, and serve this directly to the user at the same time as serving the certificate, thus both offloading the upstream CA OCSP service, and probably saving load time for the user. Modern web/TLS servers like Hitch, Apache, Nginx, and IIS, all have support for OCSP stapling.
You can test if a server has OCSP stapling switched on with the OpenSSL CLI tool:
openssl s_client -connect ialta.no:443 -status < /dev/null \
| grep 'OCSP Response'
The answer should be along the lines of
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Checking for OCSP by hand
The more programmatically inclined of us might want to know how to check the OCSP information by hand, to make sure our scripts and programs trust certificates that are still valid.
OCSP, the Online Certificate Status Protocol is described in RFC 6960, but the approach is more or less like the following:
- Get the certificate that we want to check and its intermediate certificate chain up to the CA
- The certificate should include an URL to a web service that does OCSP checking
- Send a formatted request to that URL
- Check that the answer to the request is signed and valid
OpenSSL has tools to do all this, so let’s have a go.
We’ll use redpill-linpro.com as an example. First we download the certificate and the intermediate certificate chain in one go:
openssl s_client \
-servername redpill-linpro.com \
-host redpill-linpro.com \
-port 443 \
-showcerts < /dev/null > chain.pem
Next, we split the chain in its separate certificates
n=0
while read i; do
if [ "$i" = "-----END CERTIFICATE-----" ]; then
echo $i >> chain-$n.pem
((n++))
continue
else
echo $i >> chain-$n.pem
fi
done < chain.pem
The first certificate in the chain is for the server that we want to check. The second is the first in the intermediate chain, that is, the CA that issued the certificate that we want to check.
mv chain-0.pem cert.pem
mv chain-1.pem issuer.pem
We need to trust the issuer certificate, so we check that it is valid
$ openssl verify issuer.pem
issuer.pem: OK
We need the OCSP check URL, so we extract it from the server certificate.
openssl x509 -noout -ocsp_uri -in cert.pem
http://ocsp.int-x3.letsencrypt.org/
Finally, we can request a signed OCSP response, and verify it.
$ openssl ocsp \
-url http://ocsp.int-x3.letsencrypt.org/ \
-header Host ocsp.int-x3.letsencrypt.org \
-no_nonce \
-VAfile issuer.pem \
-issuer issuer.pem \
-resp_text \
-cert cert.pem
Response verify OK
cert.pem: good
This Update: Dec 13 11:00:00 2016 GMT
Next Update: Dec 20 11:00:00 2016 GMT
So we have checked the certificate. It is still valid, and it should not be necessary to check this again until next week.
For the option details, have a look at the man-page ocsp(1).
But wait, we did not check if the issuer intermediate certificate was still valid. While this should seldom be necessary, let’s check all the way back to the CA bundle, to make our exercise complete.
First find who issued the intermediate certificate:
openssl x509 -in issuer.pem -text -noout | grep 'Issuer:'
Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
This looks like a root CA that should be in the trusted CA bundle that was provided by your OS vendor.
Note that if there are more than one certificate in the intermediate chain, you will have to loop over the algorithm below using the next certificate in the chain, before ending up at the trusted certificates in the ca bundle.
Extract all the trusted certificates from the CA bundle. On Fedora,
you may find the bundle in
/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
(Homework: Do this more effectively in Perl).
$ n=0;
$ while read i; do
if [ "$i" = "-----END CERTIFICATE-----" ]; then
echo -n '#'
echo $i >> trust-$n.pem
((n++)); continue
else
echo $i >> trust-$n.pem
fi
done < /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
$ ls trust*.pem | wc -l
155
155 trusted certificates, what a bundle! Which of these provides the signature we are looking for?
$ for i in trust-*.pem; do
echo -n '.'
openssl x509 -in $i -text -noout |\
grep -q 'Subject: O=Digital Signature Trust Co., CN=DST Root CA X3$' && \
echo && echo $i && break
done
trust-47.pem
Finally, we can do the OCSP check also on the issuer certificate
$ openssl x509 -noout -ocsp_uri -in issuer.pem
http://isrg.trustid.ocsp.identrust.com
$ openssl ocsp
-url http://isrg.trustid.ocsp.identrust.com \
-header Host isrg.trustid.ocsp.identrust.com \
-no_nonce \
-VAfile trust-47.pem \
-issuer trust-47.pem \
-resp_text \
-cert issuer.pem
Response verify OK
issuer.pem: good
This Update: Dec 15 11:28:59 2016 GMT
Next Update: Dec 16 11:28:59 2016 GMT
Conclusion: While a bit cumbersome, it is possible to verify that a certificate and its intermediate chain are both valid and not revoked, by issuing OCSP requests using the OpenSSL command line toolkit.
A script automating this, except checking the issuer certificate, may be found at https://ingvar.fedorapeople.org/varnish/check_ocsp.sh.txt.