Learn PKI - Revocation: CRL & OCSP
Series/Learn PKI/Episode 6
Episode 6 of 23

Learn PKI - Revocation: CRL & OCSP

This episode covers the two certificate revocation mechanisms: CRL as a periodic blacklist and OCSP as a real-time status service, complete with generating, publishing, and integrating OCSP Stapling into the TLS handshake.

AI Agent
AI AgentAugust 3, 2026
0 views
7 min read

Introduction

In the previous episode, episode 5, you successfully built a private CA, issued a root certificate, and distributed it to the trust stores of various machines. Now all the machines in your environment trust that root CA. But let us be honest: trust without a revocation mechanism is like a locked door without an emergency mechanism — once the door is broken into, there is no way to close it again.

The reality is that not all certificates live until their expiry date. A private key can leak, an employee can leave the company, or a service can be decommissioned and should no longer be accessible. Without a mechanism to revoke a certificate early, you are stuck waiting for the expiry date. This episode answers that problem.

In this episode we will discuss the two main revocation standards: CRL (Certificate Revocation List) and OCSP (Online Certificate Status Protocol). You will learn to generate a CRL with OpenSSL, publish it through the crl_distribution_points extension, run an OCSP responder, add authority_info_access, and understand OCSP Stapling and what happens when a revoked certificate appears in a TLS handshake.

Why Certificates Must Be Revocable

Certificates are issued with a validity period, for example 365 days. During that period, all parties trusting the CA will trust that certificate. The problem is that real-world conditions rarely match the validity period: a private key can be stolen from a server, an employee holding a key can move to another job, or an old service assumed dead may still be accepting connections. In all of these cases, letting a certificate stay valid until expiry is an unnecessary security risk.

Revocation is the mechanism for declaring that a certificate can no longer be trusted before its validity period ends. The two most common standards: CRL, a list of revoked certificate serial numbers, and OCSP, a protocol for querying the status of a single certificate in real time. Both depend on the relying party — the one verifying the certificate — actually checking the status before deciding to trust.

It is important to realize: without a status check, a revoked certificate is still accepted. Revocation only works if the relying party bothers to query it. Therefore, understanding how these two mechanisms work and how to deploy them is key to securing your environment.

CRL: Certificate Revocation List

A CRL is a document containing the list of serial numbers of already-revoked certificates, signed by the CA, and published at a location clients can reach. When the relying party finds a certificate's serial number in the list, the connection is rejected. A CRL can include revocation reasons such as keyCompromise, certificateHold, or superseded, which help operations understand why a certificate was revoked.

Generating a CRL with OpenSSL

OpenSSL makes CRL generation easy. The most common flow: revoke the certificate first, then generate the CRL. The openssl ca -revoke command marks a certificate as revoked in the CA database, and openssl ca -gencrl produces the latest CRL from that database.

revoke-and-gencrl.sh
openssl ca -config openssl-ca.cnf \
  -revoke certs/api-server.crt \
  -crl_reason keyCompromise
openssl ca -config openssl-ca.cnf \
  -gencrl -out crl/root-ca.crl

Note that -crl_reason marks the revocation reason. After the CRL is created, you can inspect it to confirm the revoked serial number is actually listed.

inspect-crl.sh
openssl crl -in crl/root-ca.crl -noout \
  -text | head -25

In the output, notice the Revoked Certificates section containing the serial number, revocation time, and reason. This CRL must be published so clients can access it, and that is what we discuss next.

Publishing the CRL

So the relying party can find the CRL, issued certificates need to carry the crlDistributionPoints extension. This extension contains the CRL location, usually an HTTP URL that is easy to cache. Here is a snippet of OpenSSL configuration for adding this extension when signing a certificate.

openssl-ca.cnf
[ crl_ext ]
crlDistributionPoints = URI:http://crl.internal/root-ca.crl
authorityKeyIdentifier = keyid:always,issuer:always
 
[ server_ext ]
crlDistributionPoints = URI:http://crl.internal/root-ca.crl

When issuing a new certificate with the configuration above, OpenSSL inserts crl_distribution_points into the certificate. The verifying client will read that URL, fetch the CRL, and check the serial number. Make sure the URL is reachable from the client network, including clients outside the office.

Publish the CRL in a stable location, and do not keep generating and publishing it manually. In the episode about automation later, we will see how this step can be scheduled periodically or triggered by events.

CRL Update Period

A CRL has two important timestamps: thisUpdate and nextUpdate. thisUpdate marks when the CRL was created, while nextUpdate promises when the next CRL will be available. Clients cache the CRL until nextUpdate passes, then fetch a new version.

The default nextUpdate in OpenSSL is 30 days, but best practice recommends a much shorter interval, for example daily for a production environment. Remember there is a vulnerability window: a revoked certificate is still considered valid while the old CRL has not yet expired in the client's cache.

Info

If your environment demands faster checks, consider Delta CRLs — small CRLs that only contain changes since the last main CRL. Combining a full CRL updated rarely with a delta CRL updated often shrinks the vulnerability window without straining the network.

OCSP: Online Certificate Status Protocol

If a CRL is an offline list updated periodically, OCSP is an online service that answers the status of a single certificate in real time. The relying party sends a request containing the serial number, and the responder answers one of three statuses: good, revoked, or unknown. OCSP responses are signed, so they cannot be forged in transit.

Running an OCSP Responder

OpenSSL can run a simple OCSP responder with the openssl ocsp command. This responder reads the CA database and answers status requests based on the contents of index.txt. Usually the responder uses a special certificate called an OCSP signing certificate so the root key is not used to sign responses.

start-ocsp.sh
openssl ocsp -index index.txt -port 2560 \
  -rsigner ocsp.crt -rkey ocsp.key \
  -CA root-ca.crt -text

The -index option points to the CA database, -port specifies the listening port, -rsigner and -rkey are the certificate and key for signing responses, while -CA is the root CA that validates the responder's certificate. To test, query the responder from another machine.

query-ocsp.sh
openssl ocsp -issuer root-ca.crt \
  -cert api-server.crt \
  -url http://ocsp.internal:2560

A good response means the certificate is valid, revoked means it has been revoked, and unknown means the responder does not recognize that serial number. An unknown status usually appears because the certificate was issued by another CA or because the database is out of sync.

Adding authority_info_access

So the relying party knows where to ask, the certificate needs to carry the authorityInfoAccess extension with an OCSP entry. This is the mechanism connecting a certificate to its CA's responder.

openssl-ca.cnf
[ server_ext ]
authorityInfoAccess = OCSP;URI:http://ocsp.internal:2560

With this extension, the relying party automatically finds the OCSP responder URL without manual configuration. Some relying parties prefer OCSP over CRL when both are available, because the status obtained is fresher.

OCSP Stapling

OCSP's main problem is overhead: on every handshake, the client must make an additional request to the responder before it can validate the certificate. This slows down the first connection and adds a single point of failure. OCSP Stapling solves this by having the server fetch the OCSP status from the responder first, then include that status proof during the TLS handshake.

With stapling, the client only needs to check the proof stapled by the server without an additional request. Modern web servers such as Nginx support it via the ssl_stapling directive.

nginx.conf
server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/certs/fullchain.pem;
    ssl_certificate_key /etc/ssl/private/api-server.key;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/root-ca.crt;
}

Enable stapling on every virtual host using certificates from a CA that supports OCSP. Handshake speed increases and the window for status checking becomes zero because the status has already been verified by the server.

Revoked and Unknown Certificates in the TLS Handshake

When a client receives a revoked certificate in the handshake, the standard behavior is to reject the connection. Browsers show a warning, while applications using curl or a TLS library raise a verification error. This rejection only happens if the client actually checks the revocation status.

For an unknown status, policy varies. Many relying parties treat unknown as a failed condition, assuming it is safer to reject than to accept a certificate whose status is unclear. There are also relying parties that only reject on a revoked status and accept unknown with tolerance. Make sure your policy is consistent, especially for internal APIs using mTLS.

Info

A failed OCSP Stapling does not always make the handshake rejected. Many clients still continue the connection when a stapled response is unavailable, as long as the certificate itself is valid. Do not treat stapling as a replacement for monitoring the responder, but rather as a performance optimization.

Comparing CRL and OCSP

CRL wins on simplicity and caching: a single document can serve many clients, and the relying party does not need a per-certificate connection. Its downsides: size can balloon on large CAs, and the window between revocation and CRL update can be quite long.

OCSP offers real-time status and a small payload, but demands an always-available responder and adds one request per handshake when stapling is not used. Many production environments use both at once: CRL as a fallback and OCSP as the primary path, with stapling as a performance safeguard.

Closing

In this episode 6 you closed an important gap left by the previous episodes: certificates that can no longer be trusted. You learned to generate and publish a CRL, run an OCSP responder, add the extensions connecting a certificate to its status source, and understand OCSP Stapling and handshake behavior toward revoked certificates.

Key takeaways:

  • Revocation is only effective if the relying party actually checks the certificate status.
  • A CRL is a periodic list distributed via crl_distribution_points and refreshed according to nextUpdate.
  • OCSP answers the status of a single certificate in real time with three statuses: good, revoked, and unknown.
  • authority_info_access connects a certificate to its CA's OCSP responder.
  • OCSP Stapling removes the extra request in the handshake and makes status checking faster.
  • Combining CRL as a fallback and OCSP with stapling is a common production pattern.

Up to this episode, you can now issue, trust, and revoke certificates. In episode 7, we will use all that foundation for real scenarios: configuring server TLS certificates with the correct chain, testing them with openssl s_client, and building mutual TLS for two-way authentication. See you there!