Validating a certificate chain against a CAA record

The primary purpose of CAA records is to put certificate issuers on notice that only a particular CA (or list of CAs) is supposed to issue certificates for a particular domain. However, it seems like it would also be useful for software that relies on certificates to be able to verify that the certificate chain they just received was legitimately issued, according to the CAA records for the domain. I can't figure out how to do this.

Let's have a concrete example: suppose this CAA record exists in the DNS (it doesn't right now)

www.owlfolio.org.    IN CAA 0 issue "letsencrypt.org"

The web server at www.owlfolio.org does in fact have a certificate issued by LE, as we can see by running a command like this...

openssl s_client -showcerts -verify 4 -no-interactive -connect www.owlfolio.org:443 < /dev/null
verify depth is 4
Connecting to 2a00:1098:88:ea::1
CONNECTED(00000003)
depth=2 C=US, O=Internet Security Research Group, CN=ISRG Root X1
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=E8
verify return:1
depth=0 CN=www.owlfolio.org
verify return:1
---
Certificate chain
 0 s:CN=www.owlfolio.org
   i:C=US, O=Let's Encrypt, CN=E8
   a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA384
   v:NotBefore: Oct  1 17:52:34 2025 GMT; NotAfter: Dec 30 17:52:33 2025 GMT
-----BEGIN CERTIFICATE-----
MIIDijCCAxGgAwIBAgISBj5egdR0GJN2r/rEbQJonJdBMAoGCCqGSM49BAMDMDIx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
ODAeFw0yNTEwMDExNzUyMzRaFw0yNTEyMzAxNzUyMzNaMBsxGTAXBgNVBAMTEHd3
dy5vd2xmb2xpby5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARejTKeFoRm
Wuo4epvmQ+lkMiSDSNmf5Vz0lCQTdSGYhqd/ohZoL8euWjqZ22WfJ2aBolrx5p8i
TZH4z0FdMvZ/o4ICHDCCAhgwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTPOhspRzr9
v79d2HGxKieNewRYnzAfBgNVHSMEGDAWgBSPDROi9i5+0VBsMxg4XVmOI3KRyjAy
BggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lOC5pLmxlbmNyLm9y
Zy8wGwYDVR0RBBQwEoIQd3d3Lm93bGZvbGlvLm9yZzATBgNVHSAEDDAKMAgGBmeB
DAECATAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8vZTguYy5sZW5jci5vcmcvNjYu
Y3JsMIIBAgYKKwYBBAHWeQIEAgSB8wSB8ADuAHQApELFBklgYVSPD9TqnPt6LSZF
TYepfy/fRVn2J086hFQAAAGZoR0hIwAABAMARTBDAiBuA+3NiIiec4lg8K0U0LSk
UqVYCchg8RyZkyzsz763wQIfelLCc69PVB+Cu04vBJ8fUJV6+8bSLczvLwwh0xV9
pAB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1wQS0lTMfUAAABmaEdIgYAAAQD
AEcwRQIgXU5fjYcBX7j/XIpOzya6cobJGM1FBUWo+/dQq6AR+5ICIQCGGBtia/zD
c2RB8MIvyrX+PMJMA8V2w/dAk/NfzeuZZjAKBggqhkjOPQQDAwNnADBkAjBt7SHc
qooq4hstNyEQCqxjPyyyZaFZLaRSzvxh9lmPg4M1al70CMFZ+mYd76PKlhwCMDBX
XG+HzjAJQo9QV9kYZsUOzjrpP+NmUslvePmw9kCUkRK3w7RnlYbAvc9LVarzBg==
-----END CERTIFICATE-----
 1 s:C=US, O=Let's Encrypt, CN=E8
   i:C=US, O=Internet Security Research Group, CN=ISRG Root X1
   a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA256
   v:NotBefore: Mar 13 00:00:00 2024 GMT; NotAfter: Mar 12 23:59:59 2027 GMT
-----BEGIN CERTIFICATE-----
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
u1igv3OefnWjSQ==
-----END CERTIFICATE-----
---
Server certificate
subject=CN=www.owlfolio.org
issuer=C=US, O=Let's Encrypt, CN=E8
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2384 bytes and written 391 bytes
Verification: OK
---
[further chatter elided]

But neither the intermediate nor the root certificate contains the string letsencrypt.org anywhere, as far as I can tell. The Subject tag for the intermediate is "C=US, O=Let's Encrypt, CN=E8", the Subject tag for the root is "C=US, O=Internet Security Research Group, CN=ISRG Root X1", and the various URLs embedded in the certificates all point into the ancillary domain lencr.org.

So I'm stumped. Is there a way for a program to verify that issue "letsencrypt.org" in the CAA record licenses a signature by C=US, O=Let's Encrypt in an intermediate certificate? And the same for other issuers.

Well, maybe. Just because a certificate being hosted now doesn't match the CAA record being published now, doesn't mean that the certificate is misissued. Some systems have very restrictive CAA records, and automatically publish a new one as part of renewing a certificate (and then put back the more restrictive one afterward), just like one might do for a DNS-01 challenge only having a token in there for the time needed. And when transitioning from one CA to another, one might very well change the CAA record to the new provider, even though one is still using the old CA's certificate until it's closer to expiration.

But I could see that it might be useful input to a more general "scoring" mechanism, as one signal among others, or might be useful for connecting to specific systems (maybe internal to one's network) where one knows that the CAA record should be consistent even after issuance.

Correct, there isn't any direct link between the allowed CAA names and what's written in the certificate. I think one would need to look at each CA in one's trust store, look at the corresponding CA's CPS, and build out one's own table from what that says about allowed CAA records. (Like, Let's Encrypt's has it documented in their CP/CPS section 4.2.1 that they check letsencrypt.org, whereas Sectigo's CP/CPS has several names that are acceptable in their section 4.2.4.)

For better or worse, CAA is really designed entirely around the issuance process, and not for end user relying parties.

If you're looking for something more sophisticated, where the client can validate that the certificate matches what the domain name controller is publishing in DNS, then you're really just looking for DANE/TLSA records.

5 Likes

Validating CAA as anyone but the issuing CA doesn’t work in practice as said above.

Nonetheless, all the information you need is in CCADB. See Common CA Database by the Linux Foundation

4 Likes

For context, I'm working on a tool that reads a zone file and does a configurable series of automated checks against the hosts with addresses in the zone. One potential check is that TLS services in the zone have certificates matching any CAA records that are present; another is that all certificates in CT logs agree with the CAA records up to some time horizon. People whose CAA records are not stable indicators of which CA should have issued the current set of certificates can simply not use these checks. Or they can feed my tool a zone file that differs from what they have in the DNS.

... you're really just looking for DANE/TLSA records.

It's my intention to use those also, but I was under the impression that TLSA records were a poor fit with short-lived certificates and frequent key rotation, and so less useful nowadays than when originally specified; is that incorrect?

Perfect, thank you.

1 Like

Yeah, a tool to validate configs is totally a valid use case here.

Note that CCADB reports changes semi-routinely, so you may want to avoid relying on their CSVs directly, unless you can guarantee your users are updating the tool promptly.

5 Likes

Short-lived certificates and frequent key rotation can be different things, as one can still use short-lived certificates with keeping the same key for some time. There are a lot of ways of defining one's TLSA records, and some would allow for them to be more long-lived than your end certificate's key (if they're based on the root, or based on listing all the possible intermediates). But even with frequent key rotation and doing frequent TLSA changes, one should be able to automate updating the TLSA records (and keeping the previous and/or next keys there as part of the process) as part of the key rotation. There may not be a lot of tooling for that around yet, but I don't know why there couldn't be. (TLSA has a bit of a chicken-and-egg problem with getting adopted, like many new technologies, since it's not likely to get used without a lot of software/tooling support, but there isn't likely to be a lot of support without much usage.)

3 Likes

That depends on the type of record (3 1 1, or 2 1 1 mainly)

and so less useful nowadays than when originally specified; is that incorrect?

They're used almost exclusively for email.

SSHFP RRs are interesting too. I don't know how widespread their usage is, but they sound neat and convenient.

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.