Revoking client SSL certificates

Following on from last weeks post, this post is going to look at revoking client SSL certificates to invalidate them.

Why revoke certificates?

When certificates are used for client authentication, the private key is kept on the users device to decrypt messages and the public key is sent to the server. So if Alice wants to connect to Bob's server she will send her X.509 certificate as part of the TLS handshake:

Diagram showing a user, Alice, talking to a server run by Bob with a
  certificate.

It is important that the private key remains confidential. If the key is compromised, the third party will be able to use the key to impersonate the user. For example if Mallory made a copy of Alice's private key she could use this to authenticate with Bob's server:

Diagram showing an attacker, Mallory using Alice's key.

Once a private key is compromised any certificates associated with that key should be revoked to ensure they can no longer be used to authenticate. In the example above Bob could revoke Alice's original certificate, and then issue a new certificate to Alice. This will prevent Mallory using the original certificate to authenticate as Alice.

Creating a Certificate Revocation List (CRL)

Start by creating a clrnumber file. Like the serial file, this file is used to add a monotonically increasing sequence number to CRL certificates as they are generated:

echo 1000 > /etc/httpd/conf/ca/crlnumber

A CRL certificate can then be generated using the following command:

openssl ca \
  -config /etc/httpd/conf/ca/openssl.cnf \
  -gencrl \
  -out /etc/httpd/conf/ca/crl.pem

The new certificate file will initially state that no certificates have been revoked:

$ openssl crl -in /etc/httpd/conf/ca/crl.pem -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: /C=GB/ST=England/O=Alice Ltd/OU=Alice Ltd Certificate Authority/CN=Alice Ltd Root CA
        Last Update: Oct  8 17:27:12 2017 GMT
        Next Update: Nov  7 17:27:12 2017 GMT
        CRL extensions:
            X509v3 CRL Number:
                4096
No Revoked Certificates.

To revoke a certificate, a command similar to the following can be used:

openssl ca \
  -config /etc/httpd/conf/ca/openssl.cnf \
  -revoke /etc/httpd/conf/ca/newcerts/1000.pem

Finally a new CRL certificate can be generated:

openssl ca \
  -config /etc/httpd/conf/ca/openssl.cnf \
  -gencrl \
  -out /etc/httpd/conf/ca/crl.pem

The certificate will now be listed as revoked:

$ openssl crl -in /etc/httpd/conf/ca/crl.pem -noout -text
...
Revoked Certificates:
    Serial Number: 1000
        Revocation Date: Oct  8 17:36:38 2017 GMT

Updating Apache

By default Apache will not look at the CRL certificate. As a result revoked certificates can still be used to authenticate! To correct this add the SSLCARevocationFile and SSLCARevocationCheck directives to /etc/httpd/conf.d/ssl.conf:

SSLCARevocationFile /etc/httpd/conf/ca/crl.pem
SSLCARevocationCheck chain

Then restart Apache to pick up the configuration change:

systemctl restart httpd.service

Apache should now reject authentication attempts which are made using revoked certificates:

$ curl  \
  --insecure \
  --cert /etc/httpd/conf/users/alice/cert.pem \
  --key /e tc/httpd/conf/users/alice/key.pem \
  https://localhost/test.txt
curl: (58) SSL peer rejected your certificate as revoked.

Note: if a new CRL certificate is issued, Apache needs to be restarted to pick up the change!

Other security measures

As well as checking for revoked certificates, below are a few security related points you should consider when using client certificate authentication:

  • The certificate authority should ideally be hosted on a different server. This prevents the CA being compromised if the server running Apache is compromised.

  • Add a passphrase to both client and CA private keys. This can be done with the following command:

    openssl rsa -aes256 -in key.pem -out key_encrypted.pem
    
  • Consider using an intermediate CA and storing the private key for the root CA offline. For more information on setting up an OpenSSL CA have a look at the OpenSSL certificate authority guide by Jamie Nguyen.