Home > Blockchain >  OpenSSL verify fails unexpectedly with "permitted subtree violation" for certificate with
OpenSSL verify fails unexpectedly with "permitted subtree violation" for certificate with

Time:11-13

I am trying to verify a PIV certificate from a smart card using a certificate that includes a Name Constraints extension. If I inspect the -text output everything looks like it should be fine but the two values have different case. Is it possible that OpenSSL is doing a case-sensitive comparison even though rfc5280 indicates that it should be case-insensitive? Here are the relevant text outputs:

Root CA (changed actual values to example but preserved casing:

            X509v3 Name Constraints: critical
                Permitted:
                  email:example.com
                  email:.example.com
                  DNS:example.com
                  DirName:C = US, O = Example

PIV Certificate (again, changed actual values to example)

       Subject: C = us, O = example, OU = people, CN = john.j.doe.123456

Here the Subject C and O values have a different case than those in the DirName constraint.

Here is the full output I'm getting from the openssl verify

$ openssl verify -noCAfile -CAfile root.crt -untrusted intermediate.crt piv-cert.crt
C = us, O = example, OU = people, CN = john.j.doe.123456
error 47 at 0 depth lookup: permitted subtree violation
error piv-cert.crt: verification failed

CodePudding user response:

No, it's not due to case; nc_dn in v3_ncons.c calls the i2d routine which calls x509_name_canon in x_name.c which calls asn1_string_canon which drops unnecessary spaces and converts to lowercase, before comparing.

It's (probably, given your redaction) due to an additional check that CommonName in the leaf cert if it 'looks like' a DNS name must satisfy the DNS constraints, which your example respectively does and doesn't.

Specifically, NAME_CONSTRAINTS_check_CN in v3_ncons.c is called for the leaf/EE cert, and (now) calls cn2dnsid to check for DNS syntax (post-punycoding if applicable): all ASCII letters, digits, plus nonstandard underscore, plus dot not at beginning or end or consecutive (i.e. all DNS labels must be nonempty) plus hyphen not at beginning or end or adjacent to dot. If this passes it applies any DNS constraints.

This looks like it is intended for SSL/TLS server certificates -- and the commit that added an earlier version to 1.1.0 acknowledged 5280 doesn't call for CN check, while this refactoring for 1.1.1 briefly modified it to apply only if no SAN DNS was present (and thus checked), but immediately thereafter that SAN bypass was removed from the code at the same time the documentation was changed to describe it as happening, which looks like a mistake to me -- but the code doesn't attempt to limit it to such server certs (and probably can't, because EKU is optional).

  • Related