OpenSSL Blog

Old Let's Encrypt Root Certificate Expiration and OpenSSL 1.0.2


The currently recommended certificate chain as presented to Let’s Encrypt ACME clients when new certificates are issued contains an intermediate certificate (ISRG Root X1) that is signed by an old DST Root CA X3 certificate that expires on 2021-09-30. In some cases the OpenSSL 1.0.2 version will regard the certificates issued by the Let’s Encrypt CA as having an expired trust chain.

See more information about the currently issued trust chains at Let’s Encrypt.

Most up-to-date CA cert trusted bundles, as provided by operating systems, contain this soon-to-be-expired certificate. The current CA cert bundles also contain an ISRG Root X1 self-signed certificate. This means that clients verifying certificate chains can find the alternative non-expired path to the ISRG Root X1 self-signed certificate in their trust store.

Unfortunately this does not apply to OpenSSL 1.0.2 which always prefers the untrusted chain and if that chain contains a path that leads to an expired trusted root certificate (DST Root CA X3), it will be selected for the certificate verification and the expiration will be reported.

These are some possible workarounds to resolve the problem:

Workaround 1 (on clients with OpenSSL 1.0.2)

Just remove the expired root certificate (DST Root CA X3) from the trust store used by the OpenSSL 1.0.2 TLS client to verify the identity of TLS servers. If the new ISRG Root X1 self-signed certificate isn’t already in the trust store, add it.

There is no downside to this workaround apart from the need to modify all the potential OpenSSL 1.0.2 TLS client hosts trust stores.

The removal and addition of certificates from/into the system certificate trust stores is a highly specific operation depending on the operation system. For example, on Linux based systems which manage system certificate trust stores with the ca-certificates tool, a CA certificate can be removed by first copying the certificate into /etc/pki/ca-trust/source/blacklist directory and added by copying into the /etc/pki/ca-trust/source/anchors directory. The trust store is then updated by running the update-ca-trust command.

Workaround 2 (on clients with OpenSSL 1.0.2)

The -trusted_first option support in openssl verify, openssl s_client, and other similar openssl commands when applied, overrides the certificate chain building so it prefers the trust store certificates over the untrusted certificates in the chain provided by the peer. That effectively means that with the option enabled the problem does not happen.

However the option is not enabled by default and third party applications do not usually provide a way to enable this option. The applications would have to call X509_VERIFY_PARAM_set_flags() function with the X509_V_FLAG_TRUSTED_FIRST flag to enable this option.

The next release of OpenSSL 1.0.2 (1.0.2zb - available to premium support customers only) will make it possible to build the release with added -DOPENSSL_TRUSTED_FIRST_DEFAULT on the build configuration command line. That will make the -trusted_first option enabled by default by the OpenSSL library.

Workaround 3 (on the servers that 1.0.2 clients connect to)

Configure the server to use the alternative certificate chain which can be requested from Let’s Encrypt with most up-to-date ACME protocol clients. This chain does not contain the ISRG Root X1 cross-signed by the soon to be expired DST Root CA X3 and thus any OpenSSL 1.0.2 clients will not be misled by this expired path.

The downside is that the servers will be seen as using an untrusted root certificate by some older Android clients because these clients do not contain the self-signed ISRG Root X1 certificate in their trust stores.