Re: “if you download the full chain it will work” - I know, but that’s not an option as it would require manual intervention. My proposed workaround of adding the AAA cert is effectively the same thing. Sectigo’s ACME protocol only gives you what I provided. And it turns out, they are right; the chain doesn’t need to include the self-signed root (and in the case of cross-signing, it shouldn’t).
I take back what I said earlier about ignoring the local keystore being a good decision. It’s a violation of RFC 5246. Maybe allow this behavior to be turned on or off with a command line switch would help?
RFC 5246 explicitly states “the self-signed certificate that specifies the root certificate authority MAY be omitted from the chain, under the assumption that the remote end must already possess it in order to validate it in any case” In fact, I just checked community.theforeman.org, and the cert chain also does not include the self-signed root cert.
So the Sectigo cert chain is absolutely RFC 5246-compliant and should validate. What’s more, including the self-signed roots would actually break some scenarios and could even cause a cert to validate when it should be untrusted. So even my proposed workaround of adding the AAA certificate is actually not a good idea.
Here’s what’s happening. The second of these certs is actually the root certificate. Well, it kinda is and kinda is not. It’s not because it’s not self signed, but it kinda is because it (or rather a “clone”) is generally included in system trust stores.
With this chain, there are really two self-signed certs, either of which would fully validate the chain. That would break if one or both of hte self-signed certs were included in the chain.
Here is a link with more information about the cross-signing and multiple roots:
The reason the second cert (USERTrust RSA Certification Authority) kinda is the root certificate is that it has a clone. The same cert (i.e., same CN, same public key, same expiration date, same extensions etc) exists twice. One is self-signed (https://crt.sh/?id=1199354), the other signed by AAA (crt.sh | 1282303295)
This cross-signing is done to support modern browsers/clients (which do have the USERTrust RSA Certification Authority in their trust store) as well as older browsers/clients (which only have the AAA CA).
A modern client will try to validate the first cert against the USERtrust in its own keystore, and disregard the one in the chain. The chain cannot include the self-signed USERtrust because having two certs with the same CN would be a conflict. And including the AAA may cause the client to validate against AAA instead of against USERtrust.
An old client will validate the first cert against the USERTrust, and then the USERtrust against AAA in the key store.
Obviously, both break when you are not consulting a keystore at all.
So;
- The Sectigo chain is perfectly legit as-is according to RFCs
- The Sectigo chain is cross-signed, and can’t properly include a self-signed root
I don’t know what the issue with cert pinning is, but would love to help figure out a solution for these conflicting requirements.