From 05db86297d4e098bdab05ed072b49aaebb19c9ea Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Fri, 4 Mar 2022 17:28:06 -0500 Subject: [PATCH] feat(x509): implement RFC 4514 string serialization for x509 names Signed-off-by: Nathaniel McCallum --- x509/src/attr.rs | 169 +++++++++++++++++++++++++++- x509/src/name.rs | 111 ++++++++++++++++++- x509/tests/certificate.rs | 8 +- x509/tests/certreq.rs | 8 +- x509/tests/name.rs | 178 ++++++++++++++++++++++++++++-- x509/tests/pkix_extensions.rs | 18 +-- x509/tests/trust_anchor_format.rs | 24 ++-- 7 files changed, 470 insertions(+), 46 deletions(-) diff --git a/x509/src/attr.rs b/x509/src/attr.rs index ae87e661c..cd706c9ff 100644 --- a/x509/src/attr.rs +++ b/x509/src/attr.rs @@ -1,7 +1,11 @@ //! Attribute-related definitions as defined in X.501 (and updated by RFC 5280). +use alloc::vec::Vec; +use core::fmt::{self, Write}; + +use const_oid::db::DB; use der::asn1::{Any, ObjectIdentifier, SetOfVec}; -use der::{Decodable, Sequence, ValueOrd}; +use der::{Decodable, Encodable, Error, ErrorKind, Sequence, Tag, Tagged, ValueOrd}; /// X.501 `AttributeType` as defined in [RFC 5280 Appendix A.1]. /// @@ -51,7 +55,7 @@ pub struct Attribute<'a> { } impl<'a> TryFrom<&'a [u8]> for Attribute<'a> { - type Error = der::Error; + type Error = Error; fn try_from(bytes: &'a [u8]) -> Result { Self::from_der(bytes) @@ -83,3 +87,164 @@ pub struct AttributeTypeAndValue<'a> { pub oid: AttributeType, pub value: Any<'a>, } + +#[derive(Copy, Clone)] +enum Escape { + None, + Some, + Hex(u8), +} + +struct Parser { + state: Escape, + bytes: Vec, +} + +impl Parser { + pub fn new() -> Self { + Self { + state: Escape::None, + bytes: Vec::new(), + } + } + + fn push(&mut self, c: u8) { + self.state = Escape::None; + self.bytes.push(c); + } + + pub fn add(&mut self, c: u8) -> Result<(), Error> { + match (self.state, c) { + (Escape::Hex(p), b'0'..=b'9') => self.push(p | (c - b'0')), + (Escape::Hex(p), b'a'..=b'f') => self.push(p | (c - b'a' + 10)), + (Escape::Hex(p), b'A'..=b'F') => self.push(p | (c - b'A' + 10)), + + (Escape::Some, b'0'..=b'9') => self.state = Escape::Hex((c - b'0') << 4), + (Escape::Some, b'a'..=b'f') => self.state = Escape::Hex((c - b'a' + 10) << 4), + (Escape::Some, b'A'..=b'F') => self.state = Escape::Hex((c - b'A' + 10) << 4), + + (Escape::Some, b' ' | b'"' | b'#' | b'=' | b'\\') => self.push(c), + (Escape::Some, b'+' | b',' | b';' | b'<' | b'>') => self.push(c), + + (Escape::None, b'\\') => self.state = Escape::Some, + (Escape::None, ..) => self.push(c), + + _ => return Err(ErrorKind::Failed.into()), + } + + Ok(()) + } + + pub fn as_bytes(&self) -> &[u8] { + &self.bytes + } +} + +impl AttributeTypeAndValue<'_> { + /// Parses the hex value in the `OID=#HEX` format. + fn encode_hex(oid: ObjectIdentifier, val: &str) -> Result, Error> { + // Ensure an even number of hex bytes. + let mut iter = match val.len() % 2 { + 0 => [].iter().cloned().chain(val.bytes()), + 1 => [0u8].iter().cloned().chain(val.bytes()), + _ => unreachable!(), + }; + + // Decode der bytes from hex. + let mut bytes = Vec::with_capacity((val.len() + 1) / 2); + while let (Some(h), Some(l)) = (iter.next(), iter.next()) { + let mut byte = 0u8; + + for (half, shift) in [(h, 4), (l, 0)] { + match half { + b'0'..=b'9' => byte |= (half - b'0') << shift, + b'a'..=b'f' => byte |= (half - b'a' + 10) << shift, + b'A'..=b'F' => byte |= (half - b'A' + 10) << shift, + _ => return Err(ErrorKind::Failed.into()), + } + } + + bytes.push(byte); + } + + // Serialize. + let value = Any::from_der(&bytes)?; + let atv = AttributeTypeAndValue { oid, value }; + atv.to_vec() + } + + /// Parses the string value in the `NAME=STRING` format. + fn encode_str(oid: ObjectIdentifier, val: &str) -> Result, Error> { + // Undo escaping. + let mut parser = Parser::new(); + for c in val.bytes() { + parser.add(c)?; + } + + // Serialize. + let value = Any::new(Tag::Utf8String, parser.as_bytes())?; + let atv = AttributeTypeAndValue { oid, value }; + atv.to_vec() + } + + /// Converts an AttributeTypeAndValue string into an encoded AttributeTypeAndValue + /// + /// This function follows the rules in [RFC 4514]. + /// + /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 + pub fn encode_from_string(s: &str) -> Result, Error> { + let idx = s.find('=').ok_or_else(|| Error::from(ErrorKind::Failed))?; + let (key, val) = s.split_at(idx); + let val = &val[1..]; + + // Either decode or lookup the OID for the given key. + let oid = match DB.by_name(key) { + Some(oid) => *oid, + None => ObjectIdentifier::new(key)?, + }; + + // If the value is hex-encoded DER... + match val.strip_prefix('#') { + Some(val) => Self::encode_hex(oid, val), + None => Self::encode_str(oid, val), + } + } +} + +/// Serializes the structure according to the rules in [RFC 4514]. +/// +/// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 +impl fmt::Display for AttributeTypeAndValue<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let val = match self.value.tag() { + Tag::PrintableString => self.value.printable_string().ok().map(|s| s.as_str()), + Tag::Utf8String => self.value.utf8_string().ok().map(|s| s.as_str()), + Tag::Ia5String => self.value.ia5_string().ok().map(|s| s.as_str()), + _ => None, + }; + + if let (Some(key), Some(val)) = (DB.by_oid(&self.oid), val) { + write!(f, "{}=", key.to_ascii_uppercase())?; + + let mut iter = val.char_indices().peekable(); + while let Some((i, c)) = iter.next() { + match c { + '#' if i == 0 => write!(f, "\\#")?, + ' ' if i == 0 || iter.peek().is_none() => write!(f, "\\ ")?, + '"' | '+' | ',' | ';' | '<' | '>' | '\\' => write!(f, "\\{}", c)?, + '\x00'..='\x1f' | '\x7f' => write!(f, "\\{:02x}", c as u8)?, + _ => f.write_char(c)?, + } + } + } else { + let value = self.value.to_vec().or(Err(fmt::Error))?; + + write!(f, "{}=#", self.oid)?; + for c in value { + write!(f, "{:02x}", c)?; + } + } + + Ok(()) + } +} diff --git a/x509/src/name.rs b/x509/src/name.rs index 98a65538c..9c95b73f6 100644 --- a/x509/src/name.rs +++ b/x509/src/name.rs @@ -1,8 +1,10 @@ //! Name-related definitions as defined in X.501 (and updated by RFC 5280). +use alloc::vec::Vec; + use crate::attr::AttributeTypeAndValue; -use der::asn1::SetOfVec; +use der::{asn1::SetOfVec, Decodable, Encodable, Newtype}; /// X.501 Name as defined in [RFC 5280 Section 4.1.2.4]. X.501 Name is used to represent distinguished names. /// @@ -20,7 +22,73 @@ pub type Name<'a> = RdnSequence<'a>; /// ``` /// /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4 -pub type RdnSequence<'a> = alloc::vec::Vec>; +#[derive(Clone, Debug, Default, PartialEq, Eq, Newtype)] +pub struct RdnSequence<'a>(pub Vec>); + +/// Find the indices of all non-escaped separators. +fn find(s: &str, b: u8) -> impl '_ + Iterator { + (0..s.len()) + .filter(move |i| s.as_bytes()[*i] == b) + .filter(|i| { + let x = i + .checked_sub(2) + .map(|i| s.as_bytes()[i]) + .unwrap_or_default(); + + let y = i + .checked_sub(1) + .map(|i| s.as_bytes()[i]) + .unwrap_or_default(); + + y != b'\\' || x == b'\\' + }) +} + +/// Split a string at all non-escaped separators. +fn split(s: &str, b: u8) -> impl '_ + Iterator { + let mut prev = 0; + find(s, b).chain([s.len()].into_iter()).map(move |i| { + let x = &s[prev..i]; + prev = i + 1; + x + }) +} + +impl RdnSequence<'_> { + /// Converts an RDNSequence string into an encoded RDNSequence + /// + /// This function follows the rules in [RFC 4514]. + /// + /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 + pub fn encode_from_string(s: &str) -> Result, der::Error> { + let ders = split(s, b',') + .map(RelativeDistinguishedName::encode_from_string) + .collect::, der::Error>>()?; + + let mut out = Vec::new(); + for der in ders.iter() { + out.push(RelativeDistinguishedName::from_der(der)?); + } + + RdnSequence(out).to_vec() + } +} + +/// Serializes the structure according to the rules in [RFC 4514]. +/// +/// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 +impl core::fmt::Display for RdnSequence<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + for (i, atv) in self.0.iter().enumerate() { + match i { + 0 => write!(f, "{}", atv)?, + _ => write!(f, ",{}", atv)?, + } + } + + Ok(()) + } +} /// X.501 DistinguishedName as defined in [RFC 5280 Section 4.1.2.4]. /// @@ -55,4 +123,41 @@ pub type DistinguishedName<'a> = RdnSequence<'a>; /// ``` /// /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4 -pub type RelativeDistinguishedName<'a> = SetOfVec>; +#[derive(Clone, Debug, Default, PartialEq, Eq, Newtype)] +pub struct RelativeDistinguishedName<'a>(pub SetOfVec>); + +impl RelativeDistinguishedName<'_> { + /// Converts an RelativeDistinguishedName string into an encoded RelativeDistinguishedName + /// + /// This function follows the rules in [RFC 4514]. + /// + /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 + pub fn encode_from_string(s: &str) -> Result, der::Error> { + let ders = split(s, b'+') + .map(AttributeTypeAndValue::encode_from_string) + .collect::, der::Error>>()?; + + let atvs = ders + .iter() + .map(|der| AttributeTypeAndValue::from_der(der)) + .collect::, der::Error>>()?; + + RelativeDistinguishedName(atvs.try_into()?).to_vec() + } +} + +/// Serializes the structure according to the rules in [RFC 4514]. +/// +/// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514 +impl core::fmt::Display for RelativeDistinguishedName<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + for (i, atv) in self.0.iter().enumerate() { + match i { + 0 => write!(f, "{}", atv)?, + _ => write!(f, "+{}", atv)?, + } + } + + Ok(()) + } +} diff --git a/x509/tests/certificate.rs b/x509/tests/certificate.rs index e11c463d2..676460c6b 100644 --- a/x509/tests/certificate.rs +++ b/x509/tests/certificate.rs @@ -218,9 +218,9 @@ fn decode_cert() { ); let mut counter = 0; - let i = cert.tbs_certificate.issuer.iter(); + let i = cert.tbs_certificate.issuer.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -263,9 +263,9 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject.iter(); + let i = cert.tbs_certificate.subject.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { // Yes, this cert features RDNs encoded in reverse order if 0 == counter { diff --git a/x509/tests/certreq.rs b/x509/tests/certreq.rs index 0e504feb8..47df3f599 100644 --- a/x509/tests/certreq.rs +++ b/x509/tests/certreq.rs @@ -34,9 +34,9 @@ fn decode_rsa_2048_der() { assert_eq!(cr.info.version, Version::V1); // Check all the RDNs. - assert_eq!(cr.info.subject.len(), NAMES.len()); - for (name, (oid, val)) in cr.info.subject.iter().zip(NAMES) { - let kind = name.get(0).unwrap(); + assert_eq!(cr.info.subject.0.len(), NAMES.len()); + for (name, (oid, val)) in cr.info.subject.0.iter().zip(NAMES) { + let kind = name.0.get(0).unwrap(); let value = match kind.value.tag() { Tag::Utf8String => kind.value.utf8_string().unwrap().as_str(), Tag::PrintableString => kind.value.printable_string().unwrap().as_str(), @@ -44,7 +44,7 @@ fn decode_rsa_2048_der() { }; assert_eq!(kind.oid, oid.parse().unwrap()); - assert_eq!(name.len(), 1); + assert_eq!(name.0.len(), 1); assert_eq!(value, *val); } diff --git a/x509/tests/name.rs b/x509/tests/name.rs index 8347d916d..d702d5dba 100644 --- a/x509/tests/name.rs +++ b/x509/tests/name.rs @@ -1,8 +1,11 @@ //! Name tests -use der::{Decodable, Encodable, Tag, Tagged}; +use const_oid::ObjectIdentifier; +use der::asn1::{OctetString, SetOfVec, Utf8String}; +use der::{Any, Decodable, Encodable, Tag, Tagged}; use hex_literal::hex; -use x509::name::{Name, RelativeDistinguishedName}; +use x509::attr::AttributeTypeAndValue; +use x509::name::{Name, RdnSequence, RelativeDistinguishedName}; #[test] fn decode_name() { @@ -31,9 +34,9 @@ fn decode_name() { let rdn1a = rdn1.unwrap(); let mut counter = 0; - let i = rdn1a.iter(); + let i = rdn1a.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -66,7 +69,7 @@ fn decode_rdn() { // : } let rdn1 = RelativeDistinguishedName::from_der(&hex!("310B3009060355040613025553")[..]).unwrap(); - let i = rdn1.iter(); + let i = rdn1.0.iter(); for atav in i { let oid = atav.oid; assert_eq!(oid.to_string(), "2.5.4.6"); @@ -92,7 +95,7 @@ fn decode_rdn() { &hex!("311F300A060355040A0C03313233301106035504030C0A4A4F484E20534D495448")[..], ) .unwrap(); - let mut i = rdn2a.iter(); + let mut i = rdn2a.0.iter(); let atav1a = i.next().unwrap(); let oid2 = atav1a.oid; assert_eq!(oid2.to_string(), "2.5.4.10"); @@ -109,19 +112,19 @@ fn decode_rdn() { let utf8a = value1.utf8_string().unwrap(); assert_eq!(utf8a.to_string(), "JOHN SMITH"); - let mut from_scratch = RelativeDistinguishedName::new(); - assert!(from_scratch.add(*atav1a).is_ok()); - assert!(from_scratch.add(*atav2a).is_ok()); + let mut from_scratch = RelativeDistinguishedName::default(); + assert!(from_scratch.0.add(*atav1a).is_ok()); + assert!(from_scratch.0.add(*atav2a).is_ok()); let reencoded = from_scratch.to_vec().unwrap(); assert_eq!( reencoded, &hex!("311F300A060355040A0C03313233301106035504030C0A4A4F484E20534D495448") ); - let mut from_scratch2 = RelativeDistinguishedName::new(); - assert!(from_scratch2.add(*atav2a).is_ok()); + let mut from_scratch2 = RelativeDistinguishedName::default(); + assert!(from_scratch2.0.add(*atav2a).is_ok()); // fails when caller adds items not in DER lexicographical order - assert!(from_scratch2.add(*atav1a).is_err()); + assert!(from_scratch2.0.add(*atav1a).is_err()); //parsing fails due to incorrect order assert!(RelativeDistinguishedName::from_der( @@ -180,3 +183,154 @@ fn decode_rdn() { // let b3 = atav3.to_vec().unwrap(); // assert_eq!(b3, &hex!("3009060355040313025553")[..]); // } + +/// Tests RdnSequence string serialization and deserialization +#[test] +fn rdns_serde() { + #[allow(clippy::type_complexity)] + let values: &[(&[&str], &str, &[&[AttributeTypeAndValue]])] = &[ + ( + &[ + "CN=foo,SN=bar,C=baz+L=bat", + "commonName=foo,sn=bar,COUNTRYNAME=baz+l=bat", + ], + "CN=foo,SN=bar,C=baz+L=bat", + &[ + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::CN, + value: Any::from(Utf8String::new("foo").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::SN, + value: Any::from(Utf8String::new("bar").unwrap()), + }], + &[ + AttributeTypeAndValue { + oid: const_oid::db::rfc4519::C, + value: Any::from(Utf8String::new("baz").unwrap()), + }, + AttributeTypeAndValue { + oid: const_oid::db::rfc4519::L, + value: Any::from(Utf8String::new("bat").unwrap()), + }, + ], + ], + ), + ( + &["UID=jsmith,DC=example,DC=net"], + "UID=jsmith,DC=example,DC=net", + &[ + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::UID, + value: Any::from(Utf8String::new("jsmith").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("example").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("net").unwrap()), + }], + ], + ), + ( + &["OU=Sales+CN=J. Smith,DC=example,DC=net"], + "OU=Sales+CN=J. Smith,DC=example,DC=net", + &[ + &[ + AttributeTypeAndValue { + oid: const_oid::db::rfc4519::OU, + value: Any::from(Utf8String::new("Sales").unwrap()), + }, + AttributeTypeAndValue { + oid: const_oid::db::rfc4519::CN, + value: Any::from(Utf8String::new("J. Smith").unwrap()), + }, + ], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("example").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("net").unwrap()), + }], + ], + ), + ( + &["CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net"], + "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net", + &[ + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::CN, + value: Any::from(Utf8String::new(r#"James "Jim" Smith, III"#).unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("example").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("net").unwrap()), + }], + ], + ), + ( + &["CN=Before\\0dAfter,DC=example,DC=net"], + "CN=Before\\0dAfter,DC=example,DC=net", + &[ + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::CN, + value: Any::from(Utf8String::new("Before\rAfter").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("example").unwrap()), + }], + &[AttributeTypeAndValue { + oid: const_oid::db::rfc4519::DC, + value: Any::from(Utf8String::new("net").unwrap()), + }], + ], + ), + ( + &["1.3.6.1.4.1.1466.0=#04024869"], + "1.3.6.1.4.1.1466.0=#04024869", + &[&[AttributeTypeAndValue { + oid: ObjectIdentifier::new("1.3.6.1.4.1.1466.0").unwrap(), + value: Any::from(OctetString::new(&[b'H', b'i']).unwrap()), + }]], + ), + ]; + + for (inputs, output, rdns) in values { + let mut brdns = RdnSequence::default(); + for rdn in rdns.iter() { + let sofv = SetOfVec::try_from(rdn.to_vec()).unwrap(); + brdns.0.push(RelativeDistinguishedName::from(sofv)); + } + + // Check that serialization matches the expected output. + eprintln!("output: {}", output); + assert_eq!(*output, format!("{}", brdns)); + + // Check that all inputs deserializize as expected. + for input in inputs.iter() { + eprintln!("input: {}", input); + + let der = RdnSequence::encode_from_string(input).unwrap(); + let rdns = RdnSequence::from_der(&der).unwrap(); + + for (l, r) in brdns.0.iter().zip(rdns.0.iter()) { + for (ll, rr) in l.0.iter().zip(r.0.iter()) { + assert_eq!(ll, rr); + } + + assert_eq!(l, r); + } + + assert_eq!(brdns, rdns); + } + } +} diff --git a/x509/tests/pkix_extensions.rs b/x509/tests/pkix_extensions.rs index fe7cb552e..61f534d82 100644 --- a/x509/tests/pkix_extensions.rs +++ b/x509/tests/pkix_extensions.rs @@ -610,9 +610,9 @@ fn decode_cert() { ); let mut counter = 0; - let i = cert.tbs_certificate.issuer.iter(); + let i = cert.tbs_certificate.issuer.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -652,9 +652,9 @@ fn decode_cert() { ); counter = 0; - let i = cert.tbs_certificate.subject.iter(); + let i = cert.tbs_certificate.subject.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -867,13 +867,13 @@ fn decode_idp() { let n = Name::from_der(&hex!("305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap(); - assert_eq!(4, n.len()); + assert_eq!(4, n.0.len()); let gn = GeneralName::from_der(&hex!("A45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap(); match gn { GeneralName::DirectoryName(gn) => { - assert_eq!(4, gn.len()); + assert_eq!(4, gn.0.len()); } _ => {} } @@ -884,7 +884,7 @@ fn decode_idp() { let gn = gns.get(0).unwrap(); match gn { GeneralName::DirectoryName(gn) => { - assert_eq!(4, gn.len()); + assert_eq!(4, gn.0.len()); } _ => {} } @@ -915,7 +915,7 @@ fn decode_idp() { let gn = dpn.get(0).unwrap(); match gn { GeneralName::DirectoryName(gn) => { - assert_eq!(4, gn.len()); + assert_eq!(4, gn.0.len()); } _ => {} } @@ -1096,7 +1096,7 @@ fn decode_idp() { for gn in dp { match gn { GeneralName::DirectoryName(gn) => { - assert_eq!(4, gn.len()); + assert_eq!(4, gn.0.len()); } _ => { panic!("Expected DirectoryName") diff --git a/x509/tests/trust_anchor_format.rs b/x509/tests/trust_anchor_format.rs index 7f873e353..90d7824bd 100644 --- a/x509/tests/trust_anchor_format.rs +++ b/x509/tests/trust_anchor_format.rs @@ -84,9 +84,9 @@ fn decode_ta1() { } counter = 0; - let i = cert_path.ta_name.iter(); + let i = cert_path.ta_name.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -147,9 +147,9 @@ fn decode_ta2() { let cert_path = tai.cert_path.as_ref().unwrap(); let mut counter = 0; - let i = cert_path.ta_name.iter(); + let i = cert_path.ta_name.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -183,9 +183,9 @@ fn decode_ta2() { for gs in gsi { match &gs.base { GeneralName::DirectoryName(dn) => { - let i = dn.iter(); + let i = dn.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -257,9 +257,9 @@ fn decode_ta3() { ); let mut counter = 0; - let i = cert_path.ta_name.iter(); + let i = cert_path.ta_name.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -293,9 +293,9 @@ fn decode_ta3() { for gs in gsi { match &gs.base { GeneralName::DirectoryName(dn) => { - let i = dn.iter(); + let i = dn.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "2.5.4.6"); @@ -360,9 +360,9 @@ fn decode_ta4() { let cert_path = tai.cert_path.as_ref().unwrap(); let mut counter = 0; - let i = cert_path.ta_name.iter(); + let i = cert_path.ta_name.0.iter(); for rdn in i { - let i1 = rdn.iter(); + let i1 = rdn.0.iter(); for atav in i1 { if 0 == counter { assert_eq!(atav.oid.to_string(), "0.9.2342.19200300.100.1.25");