X.509 CA:FALSE Testing

Kenji YoshinoCertifications, Common Criteria

Many modern Common Criteria Protection Profiles include X.509 requirements requiring the evaluator to construct a series of certificates designed to verify that a system under test is correctly parsing and validating them. X.509 certificates appear relatively simple on the surface, but digging into the details uncovers a wealth of complexity and nuance in RFC5280, ASN.1, DER, and BER. We’ll explore this testing using a specific example of the basicConstraints:CA flag and show how common X.509 tools can represent — and potentially obscure — some of the requirements as it pertains to Common Criteria conformance testing.

Several test cases exercise modifications to various X.509 extensions and one of these is to create a CA certificate with the basicConstraints extensions CA flag set to “false”.

Using OpenSSL or XCA to create a non-CA cert creates a certificate that can look correct on the surface.

XCA showing the basicConstraints extension illustrating a “False” CA flag
# openssl x509 -in int-ca-false.cert.pem -text -noout
<...truncated...>
            X509v3 Basic Constraints:
                CA:FALSE
<...truncated...>

However, while various tools might indicate that a CA flag is being set to False, when it is examined more closely, we can see that often the basicConstraints extension is simply devoid of any data. For example, when viewing a certificate being used to establish a TLS channel, we can see the following decomposition:

Wireshark view of an X.509 certificate in which the CA flag has been identified to be “False”, but is actually missing.

What happened?

RFC 5280 Section 4.2.1.9 specifies the default value of the CA flag is FALSE.

   BasicConstraints ::= SEQUENCE {
        cA                      BOOLEAN DEFAULT FALSE,
        pathLenConstraint       INTEGER (0..MAX) OPTIONAL }

RFC 5280 Appendix B says:

Implementers should note that the DER encoding of SET or SEQUENCE components whose value is the DEFAULT omit the component from the encoded certificate or CRL.  For example, a BasicConstraints extension whose cA value is FALSE would omit the cA boolean from the encoded certificate.

RFC 5280 Appendix B

This is confirmed by A Warm Welcome to ASN.1 and DER – Let’s Encrypt (letsencrypt.org) which clarifies that omitting default values is part of the DER specification.

OpenSSL and XCA are interpreting the certificate (not printing the raw certificate) and following the DER encoding rules.

The CA flag not being set can be seen in the raw ASN.1:

root# openssl asn1parse -in int-ca-false.cert.pem
<...truncated...>
  356:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
  361:d=5  hl=2 l=   2 prim: OCTET STRING      [HEX DUMP]:3000
<...truncated...>

The basic constraint hex Dump decodes as follows:

Type Sequence
|  Length 0
30 00

For comparison, when the CA flag is set to true:

root# openssl asn1parse -in int.cert.pem
<...truncated...>
  356:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
  361:d=5  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:30030101FF
<...truncated...>

The basic constraint hex Dump decodes as follows:

Type Sequence
|  Length 3
|  |  Type Boolean (i.e., the CA Flag)
|  |  |  Length 1
|  |  |  |  Value TRUE
30 03 01 01 FF

Since explicitly setting the CA flag to false would result in a non-compliant certificate, can the tests be interpreted to mean compliant parsers interpret a non-existent CA flag to be False? Unfortunately, the answer appears to be no. Tests cases in many Protection Profiles discuss all possible non-CA states, so CA:false is clearly different. For example, the Protection Profile for Application Software v1.4 (PP_APP_v1.4) requires the following invalid X.509 certificates be generated and tested:

  1. by omitting the basicConstraints field in one of the issuing certificates
  2. by setting the basicConstraints field in an issuing certificate to have CA=False
  3. one of the CAs in the chain has the CA flag in the basicConstraints extension not set (or set to FALSE)

When we construct certificates which actually force the basicConstraints CA flag ASN.1 value to be an explicit “False” value, we can see the difference:

root# openssl asn1parse -in int-explicit-false.cert.pem
<...truncated...>
  356:d=5  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
  361:d=5  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:3003010100
  368:d=4  hl=2 l=  14 cons: SEQUENCE
<...truncated...>

The basic constraint hex Dump decodes as follows:

Type Sequence
|  Length 3
|  |  Type Boolean (i.e., the CA Flag)
|  |  |  Length 1
|  |  |  |  Value FALSE
30 03 01 01 00
Wireshark view of an X.509 certificate in which the CA flag has been explicitly set to an ASN.1 “False” boolean value.

There is a minor, but distinct, difference between the CA flag not being set and the CA flag being set to false. The difference only becomes apparent when viewing the raw certificate.

Why do the tests require testing with non-compliant certificates? I speculate that this test is designed to ensure implementations do not solely look for the presence (or lack thereof) of the CA flag when determining if a certificate is a CA. That would be a reasonable shortcut if the developer assumes the input data follows the DER encoding specification.

 

Lightship’s technical and testing experts strive to mitigate risk in meeting conformance claims. Let us help you meet your certification goals. Contact us today!

Kenji Yoshino

Kenji has been performing Common Criteria evaluations since 2008. He has experience performing Operating System, Network Device, Application Software, and Full Drive Encryption evaluations. He also has experience with cryptography and entropy from a past life performing FIPS 140-2 validations.