Open est31 opened 4 years ago
Both openssl and bouncycastle generate certificates that have implicit tags at that position. Example bouncycastle generated cert:
Rather than have a test case based on what OpenSSL and BouncyCastle generate, it would be better to see an example for a real-world certificate from a publicly-trusted CA. That would give us a better idea of whether the webpki code is buggy. Or even better, we can use Chromium and/or Firefox test data to see what we need to change.
If there is a problem, I'd guess it is in this code:
let subtrees = der::nested(inner, subtrees_tag, Error::BadDER, |tagged| {
der::expect_tag_and_get_value(tagged, der::Tag::Sequence)
})?;
Perhaps it should be instead just:
let subtrees = der::expect_tag_and_get_value(inner, subtrees_tag)?;
even better, we can use Chromium and/or Firefox test data to see what we need to change.
I've skimmed Firefox test code for example certificates, apparently they use the NIST test suite: https://csrc.nist.gov/projects/pki-testing
I've extracted one of the CA certificates of that test suite here (name is nameConstraintsURI1CACert.crt
):
MIIDtzCCAp+gAwIBAgIBSDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJVUzEfMB0GA1UEChMW
VGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMGA1UEAxMMVHJ1c3QgQW5jaG9yMB4XDTEwMDEwMTA4
MzAwMFoXDTMwMTIzMTA4MzAwMFowUDELMAkGA1UEBhMCVVMxHzAdBgNVBAoTFlRlc3QgQ2VydGlm
aWNhdGVzIDIwMTExIDAeBgNVBAMTF25hbWVDb25zdHJhaW50cyBVUkkxIENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp+cs3as6ObnbAg5IEkmXsD/XLGICGl6qVcEKB6eMA0ILAsGd
MHRqybgY25GUQ+o6RfvTHdD40N6Cqjk5vu9+7aAVjrJ0pdUyqHmK6u6TVcRt+xjonlEpo8bpkqqg
V4i7m51qfLP6+KEh2SKUDBwOZ8/jlYIZeKzVXqk2GZx8+VmWWncDz/D7v262km2IiYoZM+1VAUix
Ghoi6ImPeDBE1u7qoxvvBEDKJJ4sj/5+i4yAgr+JNIULvr8DaT17SkwRZquWT18yu2qP2KycneKy
sWm30A6AmAALhFBNX1ljDeLT5U1wBCSTDRP5U4zH+XvAUUEeMyDYMc92a0hjYwE4swIDAQABo4Gm
MIGjMB8GA1UdIwQYMBaAFOR9X9FclYYILAWuvnW2ZafZXahmMB0GA1UdDgQWBBT6KK1BFt4qaBfI
DxwjPyYD3gIUAjAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgpghkgBZQMCATABMA8GA1Ud
EwEB/wQFMAMBAf8wJwYDVR0eAQH/BB0wG6AZMBeGFS50ZXN0Y2VydGlmaWNhdGVzLmdvdjANBgkq
hkiG9w0BAQsFAAOCAQEAW+m6tH95z9aBJUxdo/dsjRTdVgxPLGVODxeqpW8IvEEjoYBWgHT5M+g4
WYnzeSjiPvrq1NerYU0DOI2/hb7aoBBq+7MJ2q6BK06ddUTawRhLh4Rfnc36epefkZLKtQuFBKA7
xaqWLlRQa/jMoZ27hKI5b1qraKR+iP1rKPd1epIL4nwqQgAd6z1bJrV8c2V8py7TWE7/b6wuZVR4
aKtFMp2fIN0eo8U1K35YVtmuVw3TJsTlFn/DuZ4R4Tl6GqkdUUvlKXNuY/nMobgfruTG6nvmaLyy
FHtDoamjegjbIx/N1dibXZLf5n32iBXyHHDk7L3ubrarUrutmaHgEEiFZg==
Sadly I couldn't find any end entity certificate which contains a domain name as the subject alt name. But if you check the cert, you'll see that it's implicitly tagged.
For comparison I made rcgen emit certs both with explicit and implicit tagging. Explicit:
-----BEGIN CERTIFICATE-----
MIIBvzCCAWWgAwIBAgIBKjAKBggqhkjOPQQDAjAuMRIwEAYDVQQDDAlNYXN0ZXIg
Q0ExGDAWBgNVBAoMD0NyYWIgd2lkZ2l0cyBTRTAgFw03NTAxMDEwMDAwMDBaGA80
MDk2MDEwMTAwMDAwMFowLjESMBAGA1UEAwwJTWFzdGVyIENBMRgwFgYDVQQKDA9D
cmFiIHdpZGdpdHMgU0UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQdiguddXpR
QHU36M0NOJ8dqVUiuN+be48t8PYgw0V7UhDCA8g6lB0mwvGEivrqY+VBnbl88VPD
a1e8s6+by8Jmo3IwcDAhBgNVHREEGjAYggtjcmFicy5jcmFic4IJbG9jYWxob3N0
MBsGA1UdHgEB/wQRMA+gDTALMAWCA2RldjACpAAwHQYDVR0OBBYEFBVtKzjH7kYF
j0OIkvyKjmqiASblMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIh
AKJgXX8+/KRlmv3n+jzOY66jfZuhS5N9VBGXht/18zrVAiB6mJUCFR6CPULnWGzf
qUHSLorq8uSQPIgOU7visbeSbA==
-----END CERTIFICATE-----
Implicit (as it should be):
-----BEGIN CERTIFICATE-----
MIIBvTCCAWOgAwIBAgIBKjAKBggqhkjOPQQDAjAuMRIwEAYDVQQDDAlNYXN0ZXIg
Q0ExGDAWBgNVBAoMD0NyYWIgd2lkZ2l0cyBTRTAgFw03NTAxMDEwMDAwMDBaGA80
MDk2MDEwMTAwMDAwMFowLjESMBAGA1UEAwwJTWFzdGVyIENBMRgwFgYDVQQKDA9D
cmFiIHdpZGdpdHMgU0UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS7VdXPQZZB
E9hZLKAdO0xOMU0FST8kTmXO5FPn/eOTpaut7AENMKGMsLt9OmnL4Lw0aKNTWQdQ
rILOnNkfiQH5o3AwbjAhBgNVHREEGjAYggtjcmFicy5jcmFic4IJbG9jYWxob3N0
MBkGA1UdHgEB/wQPMA2gCzAFggNkZXYwAqQAMB0GA1UdDgQWBBT22nNEIbfDCRcG
4WXMsBU9VNEdVjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQDn
NGTIR1mie9+H7hqoBorscjesE23rAri65sn4xpzVeQIgGSHmFAyi6dTjDD9Xsw8L
In9FBS8fwEcPelbw0FUBYkw=
-----END CERTIFICATE-----
Rather than have a test case based on what OpenSSL and BouncyCastle generate, it would be better to see an example for a real-world certificate from a publicly-trusted CA.
So I've run a tool to monitor CT transparency logs for occurences of the NameConstraints extension... After going through 5 million certificates it found only one... this extension is rare. This is the certificate:
-----BEGIN CERTIFICATE-----
MIIG/DCCBOSgAwIBAgIQTdy8TYuqAGsfMhsAiU9C7jANBgkqhkiG9w0BAQwFADCB
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTUwNDI5
MDAwMDAwWhcNMjUwNDI4MjM1OTU5WjCBkTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
AkNBMQ8wDQYDVQQHEwZJcnZpbmUxJTAjBgNVBAoTHFdlc3Rlcm4gRGlnaXRhbCBU
ZWNobm9sb2dpZXMxPTA7BgNVBAMTNFdlc3Rlcm4gRGlnaXRhbCBUZWNobm9sb2dp
ZXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCJBlUwAHMI7whlu0dUeOHpnWajTXdOKt8vBo+tjSyD/SyXxhr9
G61pCO2xb7hwOtVqVXcvByBrxpyJtNe0/6kTIg2DM4uFJ1NyHmny7vh6hrjHMhY+
gE/qdy4vTetTY9Swqr/zthJBooZH8tj2wC5vLO++BNKCILcbPy1TlKghXpULROgQ
UkBY3FksDd/DF2bLcevUkZY4a8MLHY+6KWpES3vApJ98rWtWMuMRiS0JipXXrIcI
qTOjBuGdJNRU0T279AsheA8UBurGg4H+iDiB2q+WFmNQiJ60a7J6Bg9SiLqXm2cc
J2+g1QfZIyiv07+yLWWKrxEmd4r9NSiJHcUvAgMBAAGjggJYMIICVDAfBgNVHSME
GDAWgBS7r34CPfqm8TyEjq3uOJjs2TIy1DAdBgNVHQ4EFgQUWRAanffYNzT9rdUL
rGiuAvegvYMwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD
VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCIGA1UdIAQbMBkwDQYLKwYBBAGy
MQECAjMwCAYGZ4EMAQIBMEwGA1UdHwRFMEMwQaA/oD2GO2h0dHA6Ly9jcmwuY29t
b2RvY2EuY29tL0NPTU9ET1JTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMHEG
CCsGAQUFBwEBBGUwYzA7BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5j
b20vQ09NT0RPUlNBQWRkVHJ1c3RDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
Y3NwLmNvbW9kb2NhLmNvbTCB6QYDVR0eBIHhMIHeoIGpMA+CDXJlbW90ZXdkMS5j
b20wD4INcmVtb3Rld2QyLmNvbTAPgg1yZW1vdGV3ZDMuY29tMA+CDXJlbW90ZXdk
NC5jb20wD4INcmVtb3Rld2Q1LmNvbTALggl3ZDJnby5jb20wDYILd2R0ZXN0MS5j
b20wDYILd2R0ZXN0Mi5jb20wJ6QlMCMxITAfBgNVBAsTGERvbWFpbiBDb250cm9s
IFZhbGlkYXRlZKEwMAqHCAAAAAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAMA0GCSqGSIb3DQEBDAUAA4ICAQBcKmEBtmSC6qx86SdD2aLd
h4s72ME1D/1YrvpDOSE9hJ8w449Fm0kAtTJYRyoQ1XYoChVy3G5W1KtC87u3MbAh
98BZ3A9ECxfcW/Fh83ziuaaztKNorBI5jSHAKKxHQD6GpsnKNiqJCn4tEI6LPHRD
qcxnmMolytp1UrGYIyiDhZwPjYxVBHHPuFi0RxewKn6QSI6Z91IAvrmdgpJyruUX
7GHZmEdxnL4CeQr3m7EG7cMr5PqppLmtWzKfzKnIYxX3dF8/yPCleP5/R6SsJmHh
LZboPlmOz8M8YjxFp590dwS6+CL34ngrow5rT6FCYM32T7gL6n0BnzOsyKjAhLRf
KkLxo3P4uSlJ4eDLy7dbTpTvJyo1qyVX512aaJpaFnTfQTawX+vqK9UlcIqwhmCx
lqqRaVw64a7i5nSMOIqSN7RL1PlKwuJx7GR0ajwOs1a6gHLKiC9fpefTLb7XLqWi
5tNY4BkED21dUwEVwmf8b+oQw8Brn56CSVd1QEhu7knwEfB3O1rErNPiqgEg5JR/
6gGjlj+0vGGLXtWrA8Fp72+bchAed3qjQpQmhEVLAqxdRCoxBp14gr7lSGaUcQbx
XJLJ8GrVoyQGfdgtxyy0JT3gHgBF7qRiox+zqqNS72JQelBK1gIr6UmCNQTbp+eO
oBE7elaoresGFzV1PkCBSA==
-----END CERTIFICATE-----
Its crt.sh URL: https://crt.sh/?id=8937677
It uses test in various places, so not sure if it's real-world or not as to your demands, but it is a publicly trusted cert that made it into various CT logs.
And it uses implicit tagging:
I've ran another scan over the argon 2021 CT log, scanning 9.5 million certificates as they came in, roughly over a span of 1 day. I've found two more occurrences of the western digital certificate mentioned above. Apparently that certificate is used to sign end entity certificates. I presume it's real world and production because it seems to point to NAS instances of home users.
I have changed the code to emit full chains, so that the end entity cert is shown.
Found some more uses of the NameConstraints extension. Both use implicit tagging:
So far it's only implicit tags, except for webpki's expectations :).
Yes, I'm convinced webpki needs to be fixed. What I really need is a test case that includes the end-entity certificate, the intermediates, and the root.
@briansmith you can find full chains in the comment above.
The ASN.1 definition of
NameConstraints
is found in the implicitly tagged section of RFC 5820 here:At the start of the section, there is this definition, setting the default tag type to implicit:
Most importantly, permitted and excluded subtrees are implicitly tagged.
However, parsing code in webpki is like this:
https://github.com/briansmith/webpki/blob/049c5ad5c5b0272baf007ef1301acaf9d5c4ac56/src/name.rs#L180-L181
which basically assumes that the values are constructed. This is wrong!
Both openssl and bouncycastle generate certificates that have implicit tags at that position. Example bouncycastle generated cert:
Example openssl generated cert can be found in #134.