Skip to content

Commit

Permalink
lib: support x509-parser Ia5String DistinguishedNames
Browse files Browse the repository at this point in the history
This commit updates the logic for converting from the x509-parser
distinguished name types into the rcgen equivalent in order to support
`Ia5String` values.

A small unit test is added that shows round-tripping a certificate with
a subject containing an `Ia5String`, serializing it, parsing with
x509-parser, and then recreating `CertificateParams` from the DER using
`from_ca_cert_der`.
  • Loading branch information
cpu committed Oct 27, 2023
1 parent cf255c8 commit 8891a8c
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 10 deletions.
15 changes: 5 additions & 10 deletions rcgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,20 +473,15 @@ impl DistinguishedName {
.ok_or(Error::CouldNotParseCertificate)?;
let dn_type = DnType::from_oid(&attr_type_oid.collect::<Vec<_>>());
let data = attr.attr_value().data;
let try_str =
|data| std::str::from_utf8(data).map_err(|_| Error::CouldNotParseCertificate);
let dn_value = match attr.attr_value().header.tag() {
Tag::BmpString => DnValue::BmpString(data.into()),

Check warning on line 479 in rcgen/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

rcgen/src/lib.rs#L479

Added line #L479 was not covered by tests
Tag::PrintableString => {
let data =
std::str::from_utf8(data).map_err(|_| Error::CouldNotParseCertificate)?;
DnValue::PrintableString(data.to_owned())
},
Tag::Ia5String => DnValue::Ia5String(try_str(data)?.to_owned()),
Tag::PrintableString => DnValue::PrintableString(try_str(data)?.to_owned()),
Tag::T61String => DnValue::TeletexString(data.into()),
Tag::UniversalString => DnValue::UniversalString(data.into()),
Tag::Utf8String => {
let data =
std::str::from_utf8(data).map_err(|_| Error::CouldNotParseCertificate)?;
DnValue::Utf8String(data.to_owned())
},
Tag::Utf8String => DnValue::Utf8String(try_str(data)?.to_owned()),
_ => return Err(Error::CouldNotParseCertificate),
};

Expand Down
37 changes: 37 additions & 0 deletions rcgen/tests/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,40 @@ mod test_parse_crl_dps {
);
}
}

#[cfg(feature = "x509-parser")]
mod test_parse_ia5string_subject {
use crate::util;
use rcgen::DnType::CustomDnType;
use rcgen::{Certificate, CertificateParams, DistinguishedName, DnValue, KeyPair};

#[test]
fn parse_ia5string_subject() {
// Create and serialize a certificate with a subject containing an IA5String email address.
let email_address_dn_type = CustomDnType(vec![1, 2, 840, 113549, 1, 9, 1]); // id-emailAddress
let email_address_dn_value = DnValue::Ia5String("[email protected]".into());
let mut params = util::default_params();
params.distinguished_name = DistinguishedName::new();
params.distinguished_name.push(
email_address_dn_type.clone(),
email_address_dn_value.clone(),
);
let cert = Certificate::from_params(params).unwrap();
let cert_der = cert.serialize_der().unwrap();

// We should be able to parse the certificate with x509-parser.
assert!(x509_parser::parse_x509_certificate(&cert_der).is_ok());

// We should be able to reconstitute params from the DER using x509-parser.
let key_pair = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256).unwrap();
let params_from_cert = CertificateParams::from_ca_cert_der(&cert_der, key_pair).unwrap();

// We should find the expected distinguished name in the reconstituted params.
let expected_names = &[(&email_address_dn_type, &email_address_dn_value)];
let names = params_from_cert
.distinguished_name
.iter()
.collect::<Vec<(_, _)>>();
assert_eq!(names, expected_names);
}
}

0 comments on commit 8891a8c

Please sign in to comment.