Relentless Coding

A Developer’s Blog

Remove All CAs From Linux Trust Store

On Security Now! podcast #951, Steve told us that 7 organizations in the PKI are responsible for minting upwards of 99% of all existing certificates. (Possible original source.)

His suggestion was that we can remove all CAs except for those 7 and still be able to browse the web normally. I wanted to try that, so I disabled almost all CAs in Firefox by hand (about:preferences#privacy and then “View Certificates…”). After allowing some other CAs that I encountered on web sites and that I thought were trustworthy, it worked beautifully.

I wanted to do the same for curl, wget and other programs.

First I read the Arch Linux Wiki article on TLS certificates. Apparently, libraries can make use of the PKCS #11 interface exposed by Arch. I searched for it, but could not readily find any programs that use this interface. From experimenting, I found that curl, wget, openssl and docker all obtain their root store from files in /etc/ca-certificates/.

My tactic is: disallow all CAs, then go about my day, and enable those that I encounter and that seem trustworthy.

1. Check if you can securely connect to a remote host

$ H=nos.nl; echo Q | \
>   openssl s_client -verify_return_error -servername $H $H:443
Connecting to 23.50.131.144
CONNECTED(00000003)
depth=2 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
verify return:1
depth=1 C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C=BE, L=Antwerpen, O=DPG Media Services NV, CN=*.nu.nl
verify return:1
... snip ...

2. Disable All CAs

$ sudo ln /etc/ca-certificates/extracted/cadir/*.pem \
>   /etc/ca-certificates/trust-source/blocklist/
$ sudo /usr/bin/update-ca-trust

3. Verify that remote host is now untrusted

$ H=nu.nl; echo Q | \
>   openssl s_client -verify_return_error -servername $H $H:443
Connecting to 23.50.131.156
CONNECTED(00000003)
depth=1 C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
verify error:num=20:unable to get local issuer certificate
40575E1A63700000:error:0A000086:SSL
routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2091:
---
Certificate chain
 0 s:C=BE, L=Antwerpen, O=DPG Media Services NV, CN=*.nu.nl
   i:C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
   a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
   v:NotBefore: Jun  2 00:00:00 2024 GMT; NotAfter: Jun  4 23:59:59 2025 GMT
 1 s:C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
   i:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Apr 14 00:00:00 2021 GMT; NotAfter: Apr 13 23:59:59 2031 GMT
... snip ...

4. Allow CA if deemed trustworthy

If we look at the output under 3., we see that the issuer of the intermediate certificate (s:C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1) is DigiCert. To trust this root again:

$ find /etc/ca-certificates/trust-source/blocklist/ \
>   -iname '*digicert*' -print -delete
./DigiCert_High_Assurance_EV_Root_CA.pem
./DigiCert_Global_Root_G2.pem
./DigiCert_TLS_RSA4096_Root_G5.pem
./DigiCert_Trusted_Root_G4.pem
./DigiCert_Assured_ID_Root_G2.pem
./DigiCert_Assured_ID_Root_G3.pem
./DigiCert_Global_Root_G3.pem
./DigiCert_TLS_ECC_P384_Root_G5.pem
./DigiCert_Assured_ID_Root_CA.pem
./DigiCert_Global_Root_CA.pem
$ /usr/bin/update-ca-trust

Sometimes, an application caches the blocklisted certs. In that case, you need to restart the application. Notably, the Docker daemon needs to be restarted whenever a change to the certificate store was made.

5. Check if domain gets validated again

$ H=nu.nl; echo Q | openssl s_client -verify_return_error -servername $H $H:443
Connecting to 23.50.131.156
CONNECTED(00000003)
depth=2 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
verify return:1
depth=1 C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C=BE, L=Antwerpen, O=DPG Media Services NV, CN=*.nu.nl
verify return:1
... snip ...