Skip to content

Commit

Permalink
x509-cert: make Name a new type over RdnSequence
Browse files Browse the repository at this point in the history
This make `FromStr` documented way to build a name.
This also exposes a set of getter methods to get elements from the name
(CN, Org, ...).
  • Loading branch information
baloo committed Sep 6, 2024
1 parent 28dec85 commit 32615dd
Show file tree
Hide file tree
Showing 10 changed files with 648 additions and 438 deletions.
29 changes: 6 additions & 23 deletions cms/tests/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use cms::enveloped_data::RecipientInfo::Ktri;
use cms::enveloped_data::{EnvelopedData, RecipientIdentifier, RecipientInfo};
use cms::signed_data::{EncapsulatedContentInfo, SignedData, SignerIdentifier};
use const_oid::ObjectIdentifier;
use der::asn1::{OctetString, PrintableString, SetOfVec, Utf8StringRef};
use der::asn1::{OctetString, PrintableString, SetOfVec};
use der::{Any, AnyRef, Decode, DecodePem, Encode, Tag, Tagged};
use p256::{pkcs8::DecodePrivateKey, NistP256};
use pem_rfc7468::LineEnding;
Expand All @@ -24,8 +24,7 @@ use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
use sha2::Sha256;
use signature::Verifier;
use spki::AlgorithmIdentifierOwned;
use x509_cert::attr::{Attribute, AttributeTypeAndValue, AttributeValue};
use x509_cert::name::{RdnSequence, RelativeDistinguishedName};
use x509_cert::attr::{Attribute, AttributeValue};
use x509_cert::serial_number::SerialNumber;

// TODO bk replace this by const_oid definitions as soon as released
Expand All @@ -50,34 +49,18 @@ fn ecdsa_signer() -> ecdsa::SigningKey<NistP256> {
}

fn signer_identifier(id: i32) -> SignerIdentifier {
let mut rdn_sequence = RdnSequence::default();
let rdn = &[AttributeTypeAndValue {
oid: const_oid::db::rfc4519::CN,
value: Any::from(Utf8StringRef::new(&format!("test client {id}")).unwrap()),
}];
let set_of_vector = SetOfVec::try_from(rdn.to_vec()).unwrap();
rdn_sequence
.0
.push(RelativeDistinguishedName::from(set_of_vector));
let issuer = format!("CN=test client {id}").parse().unwrap();
SignerIdentifier::IssuerAndSerialNumber(IssuerAndSerialNumber {
issuer: rdn_sequence,
issuer,
serial_number: SerialNumber::new(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
.expect("failed to create a serial number"),
})
}

fn recipient_identifier(id: i32) -> RecipientIdentifier {
let mut rdn_sequence = RdnSequence::default();
let rdn = &[AttributeTypeAndValue {
oid: const_oid::db::rfc4519::CN,
value: Any::from(Utf8StringRef::new(&format!("test client {id}")).unwrap()),
}];
let set_of_vector = SetOfVec::try_from(rdn.to_vec()).unwrap();
rdn_sequence
.0
.push(RelativeDistinguishedName::from(set_of_vector));
let issuer = format!("CN=test client {id}").parse().unwrap();
RecipientIdentifier::IssuerAndSerialNumber(IssuerAndSerialNumber {
issuer: rdn_sequence,
issuer,
serial_number: SerialNumber::new(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
.expect("failed to create a serial number"),
})
Expand Down
12 changes: 5 additions & 7 deletions x509-cert/src/builder/profile/cabf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn check_names_encoding(name: &Name, multiple_allowed: bool) -> Result<()> {

let mut seen = HashSet::new();

for rdn in name.0.iter() {
for rdn in name.iter_rdn() {
if rdn.0.len() != 1 {
return Err(Error::NonUniqueRdn);
}
Expand Down Expand Up @@ -87,13 +87,11 @@ pub fn ca_certificate_naming(subject: &Name) -> Result<()> {

check_names_encoding(subject, false)?;

for rdn in subject.0.iter() {
for atv in rdn.0.iter() {
if !allowed.remove(&atv.oid) {
return Err(Error::InvalidAttribute { oid: atv.oid });
}
required.remove(&atv.oid);
for atv in subject.iter() {
if !allowed.remove(&atv.oid) {
return Err(Error::InvalidAttribute { oid: atv.oid });
}
required.remove(&atv.oid);
}

if !required.is_empty() {
Expand Down
8 changes: 4 additions & 4 deletions x509-cert/src/builder/profile/cabf/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
},
AsExtension, Extension,
},
name::{Name, RelativeDistinguishedName},
name::{Name, RdnSequence, RelativeDistinguishedName},
};
use spki::SubjectPublicKeyInfoRef;

Expand Down Expand Up @@ -145,8 +145,7 @@ impl CertificateType {
// TODO(baloo): not very happy with all that, might as well throw that in a helper
// or something.
let rdns: vec::Vec<RelativeDistinguishedName> = subject
.0
.iter()
.iter_rdn()
.filter_map(|rdn| {
let out = SetOfVec::<AttributeTypeAndValue>::from_iter(
rdn.0
Expand All @@ -161,7 +160,8 @@ impl CertificateType {
.filter(|rdn| !rdn.0.is_empty())
.collect();

let subject: Name = rdns.into();
let subject: RdnSequence = rdns.into();
let subject: Name = subject.into();

Ok(Self::DomainValidated(DomainValidated { subject, names }))
}
Expand Down
44 changes: 42 additions & 2 deletions x509-cert/src/ext/pkix/name/dirstr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use alloc::string::String;
use der::asn1::{PrintableString, TeletexString};
use der::{Choice, ValueOrd};
use der::{
asn1::{Any, PrintableString, TeletexString},
Choice, FixedTag, Header, Reader, ValueOrd,
};

/// DirectoryString as defined in [RFC 5280 Section 4.2.1.4].
///
Expand Down Expand Up @@ -51,3 +53,41 @@ pub enum DirectoryString {
#[asn1(type = "UTF8String")]
Utf8String(String),
}

impl<'a> TryFrom<&'a Any> for DirectoryString {
type Error = der::Error;
fn try_from(any: &'a Any) -> der::Result<Self> {
any.decode_as()
}
}

impl<'a> der::DecodeValue<'a> for DirectoryString {
type Error = der::Error;

fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error> {
match header.tag {
PrintableString::TAG => {
PrintableString::decode_value(reader, header).map(Self::PrintableString)
}
TeletexString::TAG => {
TeletexString::decode_value(reader, header).map(Self::TeletexString)
}
String::TAG => String::decode_value(reader, header).map(Self::Utf8String),
actual => Err(der::ErrorKind::TagUnexpected {
expected: None,
actual,
}
.into()),
}
}
}

impl AsRef<str> for DirectoryString {
fn as_ref(&self) -> &str {
match self {
Self::PrintableString(s) => s.as_ref(),
Self::TeletexString(s) => s.as_ref(),
Self::Utf8String(s) => s.as_ref(),
}
}
}
Loading

0 comments on commit 32615dd

Please sign in to comment.