Skip to content

rcgen incorrectly encodes directoryName constraints #428

@sfackler

Description

@sfackler

Here's a simple program that generates a CA certificate with a directoryName constraint:

use std::fs;

use rcgen::{
    date_time_ymd, BasicConstraints, CertificateParams, DistinguishedName, DnType, GeneralSubtree,
    IsCa, KeyPair, NameConstraints,
};

fn main() {
    let ca_key = KeyPair::generate().unwrap();
    let mut ca_params = CertificateParams::new(Vec::<String>::new()).unwrap();
    ca_params
        .distinguished_name
        .push(DnType::CommonName, "Test Root CA");
    ca_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
    ca_params.not_before = date_time_ymd(2024, 1, 1);
    ca_params.not_after = date_time_ymd(2050, 1, 1);

    let mut permitted = DistinguishedName::new();
    permitted.push(DnType::CommonName, "leaf.example.com");
    ca_params.name_constraints = Some(NameConstraints {
        permitted_subtrees: vec![GeneralSubtree::DirectoryName(permitted)],
        excluded_subtrees: vec![],
    });

    let ca_cert = ca_params.self_signed(&ca_key).unwrap();
    fs::write("ca.pem", ca_cert.pem()).unwrap();
}

OpenSSL is unable to parse the constraint:

$ openssl x509 -text -in ca.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3b:4a:80:3f:dd:07:4b:96:de:c9:1d:ad:49:47:de:ff:ef:ca:7c:9d
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN=Test Root CA
        Validity
            Not Before: Jan  1 00:00:00 2024 GMT
            Not After : Jan  1 00:00:00 2050 GMT
        Subject: CN=Test Root CA
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:10:df:f4:bf:ea:83:90:22:c5:b4:45:20:83:25:
                    57:a5:f0:04:da:ca:ee:c4:55:7d:b9:52:ca:33:12:
                    f1:aa:76:6d:d5:21:69:40:85:18:08:bc:69:8e:48:
                    a6:8b:2d:42:f3:8f:b0:11:42:9b:e3:48:f4:bd:46:
                    1c:f3:a8:ab:48
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Name Constraints: critical
                0!..0...1.0...U....leaf.example.com
            X509v3 Subject Key Identifier:
                B3:45:BD:60:C1:FB:A7:BE:73:D9:23:6C:EB:31:43:6C:EF:E4:3C:4A
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:44:02:20:24:43:f9:bd:35:b9:66:93:1a:b2:40:95:7a:22:
        93:59:d4:78:8e:09:dd:4f:3c:af:17:84:79:7d:b3:a4:45:5b:
        02:20:58:83:13:b7:5a:a2:96:ce:60:59:9b:5c:db:a0:a0:5c:
        b9:bc:08:2f:71:b8:d5:27:3e:bd:1f:3c:0a:69:5f:7a
-----BEGIN CERTIFICATE-----
MIIBkjCCATmgAwIBAgIUO0qAP90HS5beyR2tSUfe/+/KfJ0wCgYIKoZIzj0EAwIw
FzEVMBMGA1UEAwwMVGVzdCBSb290IENBMCAXDTI0MDEwMTAwMDAwMFoYDzIwNTAw
MTAxMDAwMDAwWjAXMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwWTATBgcqhkjOPQIB
BggqhkjOPQMBBwNCAAQQ3/S/6oOQIsW0RSCDJVel8ATayu7EVX25UsozEvGqdm3V
IWlAhRgIvGmOSKaLLULzj7ARQpvjSPS9RhzzqKtIo2EwXzAtBgNVHR4BAf8EIzAh
oB8wHaQbMRkwFwYDVQQDDBBsZWFmLmV4YW1wbGUuY29tMB0GA1UdDgQWBBSzRb1g
wfunvnPZI2zrMUNs7+Q8SjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cA
MEQCICRD+b01uWaTGrJAlXoik1nUeI4J3U88rxeEeX2zpEVbAiBYgxO3WqKWzmBZ
m1zboKBcubwIL3G41Sc+vR88Cmlfeg==
-----END CERTIFICATE-----

(notably)

        X509v3 extensions:
            X509v3 Name Constraints: critical
                0!..0...1.0...U....leaf.example.com

As a result, it will also fail to verify certificate chains containing one of these misformatted constraints.

The issue appears to be that rcgen serializes it as implicit while it is supposed to be explicit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions