Thank you for doing that! Since this thread was asking about Openssl specifically, I thought I'd share results from my testing using that. This tests are from AWS's CloudShell, which is basically a VM running Amazon Linux 2 and is very similar to RHEL/CentOS in how it manages packages where security patches (only) are applied but the letter at the end of the OpenSSL version doesn't get incremented.
Openssl 1.0.2k
The setup:
[cloudshell-user@ip-10-0-128-94 ~]$ sudo yum install openssl -y
[…omitting output here…]
[cloudshell-user@ip-10-0-128-94 ~]$ openssl version
OpenSSL 1.0.2k-fips 26 Jan 2017
[cloudshell-user@ip-10-0-128-94 ~]$ curl -s -L -o expired-root-test.pem https://community.letsencrypt.org/uploads/short-url/rfyc7llcf0zuwSLivstXSjbj39K.pem
[cloudshell-user@ip-10-0-128-94 ~]$ curl -s -L -o cross-signed-test.pem https://community.letsencrypt.org/uploads/short-url/2GICqyDLvxNwBeMlexlgQA4nt25.pem
Having just the root in the trust store
[cloudshell-user@ip-10-0-128-94 ~]$ openssl s_client -CAfile expired-root-test.pem -connect expired-root-ca-test.germancoding.com:443 -servername expired-root-ca-test.germancoding.com
CONNECTED(00000003)
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
verify error:num=10:certificate has expired
notAfter=Jan 1 00:00:00 2021 GMT
---
Certificate chain
0 s:/O=GermanCodings Test CA/CN=expired-root-ca-test.germancoding.com
i:/O=GermanCodings Test CA/CN=Intermediate CA - TEST CERTIFICATE
1 s:/O=GermanCodings Test CA/CN=Intermediate CA - TEST CERTIFICATE
i:/O=GermanCodings Test CA/CN=Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
2 s:/O=GermanCodings Test CA/CN=Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
i:/O=GermanCodings Test CA/CN=Expired Root CA - TEST ROOT CERTIFICATE
[…snip…]
Verify return code: 10 (certificate has expired)
Having both root and cross-signed root in trust store
[cloudshell-user@ip-10-0-128-94 ~]$ openssl s_client -CAfile <(cat expired-root-test.pem cross-signed-test.pem) -connect expired-root-ca-test.germancoding.com:443 -servername expired-root-ca-test.germancoding.com
CONNECTED(00000003)
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
verify error:num=10:certificate has expired
notAfter=Jan 1 00:00:00 2021 GMT
---
Certificate chain
0 s:/O=GermanCodings Test CA/CN=expired-root-ca-test.germancoding.com
i:/O=GermanCodings Test CA/CN=Intermediate CA - TEST CERTIFICATE
1 s:/O=GermanCodings Test CA/CN=Intermediate CA - TEST CERTIFICATE
i:/O=GermanCodings Test CA/CN=Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
2 s:/O=GermanCodings Test CA/CN=Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
i:/O=GermanCodings Test CA/CN=Expired Root CA - TEST ROOT CERTIFICATE
[…snip…]
Verify return code: 10 (certificate has expired)
So yes, I think this does confirm the hypothesis that Openssl 1.0 won't trust ISRG Root X1 if a version of it cross-signed to an expired root is presented.
Openssl 1.1.1
Additional setup
[cloudshell-user@ip-10-0-128-94 ~]$ sudo yum install openssl11 -y
[…omitting output…]
[cloudshell-user@ip-10-0-128-94 ~]$ openssl11 version
OpenSSL 1.1.1c FIPS 28 May 2019
Having just the root in the trust store
[cloudshell-user@ip-10-0-128-94 ~]$ openssl11 s_client -CAfile expired-root-test.pem -connect expired-root-ca-test.germancoding.com:443 -servername expired-root-ca-test.germancoding.com
CONNECTED(00000003)
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
verify error:num=10:certificate has expired
notAfter=Jan 1 00:00:00 2021 GMT
verify return:1
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
notAfter=Jan 1 00:00:00 2021 GMT
verify return:1
depth=2 O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
notAfter=Jan 1 00:00:00 2025 GMT
verify return:1
depth=1 O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
notAfter=Jan 2 00:00:00 2022 GMT
verify return:1
depth=0 O = GermanCodings Test CA, CN = expired-root-ca-test.germancoding.com
notAfter=Jan 1 00:00:00 2022 GMT
verify return:1
---
Certificate chain
0 s:O = GermanCodings Test CA, CN = expired-root-ca-test.germancoding.com
i:O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
1 s:O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
i:O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
2 s:O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
i:O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
[…snip…]
Verification error: certificate has expired
Having both root and cross-signed root in trust store
[cloudshell-user@ip-10-0-128-94 ~]$ openssl11 s_client -CAfile <(cat expired-root-test.pem cross-signed-test.pem) -connect expired-root-ca-test.germancoding.com:443 -servername expired-root-ca-test.germancoding.com
CONNECTED(00000003)
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
verify error:num=10:certificate has expired
notAfter=Jan 1 00:00:00 2021 GMT
verify return:1
depth=3 O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
notAfter=Jan 1 00:00:00 2021 GMT
verify return:1
depth=2 O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
notAfter=Jan 1 00:00:00 2025 GMT
verify return:1
depth=1 O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
notAfter=Jan 2 00:00:00 2022 GMT
verify return:1
depth=0 O = GermanCodings Test CA, CN = expired-root-ca-test.germancoding.com
notAfter=Jan 1 00:00:00 2022 GMT
verify return:1
---
Certificate chain
0 s:O = GermanCodings Test CA, CN = expired-root-ca-test.germancoding.com
i:O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
1 s:O = GermanCodings Test CA, CN = Intermediate CA - TEST CERTIFICATE
i:O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
2 s:O = GermanCodings Test CA, CN = Valid Cross-Signed Root CA - TEST ROOT CERTIFICATE
i:O = GermanCodings Test CA, CN = Expired Root CA - TEST ROOT CERTIFICATE
[…snip…]
Verify return code: 10 (certificate has expired)
Which I think means it behaves the same way as 1.0. But I may be misunderstanding the openssl s_client
output and perhaps that specific testing mode doesn't reflect how real-world applications make use of the openssl libraries to do validation?