Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x509-cert: make name an owned type #771

Merged
merged 9 commits into from
Dec 13, 2022
Merged
80 changes: 46 additions & 34 deletions der/src/asn1/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
use core::cmp::Ordering;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use crate::Bytes;

#[cfg(feature = "oid")]
use crate::asn1::ObjectIdentifier;
Expand Down Expand Up @@ -94,11 +94,6 @@ impl<'a> AnyRef<'a> {
self.try_into()
}

/// Attempt to decode an ASN.1 `IA5String`.
pub fn ia5_string(self) -> Result<Ia5StringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `OCTET STRING`.
pub fn octet_string(self) -> Result<OctetStringRef<'a>> {
self.try_into()
Expand All @@ -123,21 +118,6 @@ impl<'a> AnyRef<'a> {
}
}

/// Attempt to decode an ASN.1 `PrintableString`.
pub fn printable_string(self) -> Result<PrintableStringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `TeletexString`.
pub fn teletex_string(self) -> Result<TeletexStringRef<'a>> {
self.try_into()
}

/// Attempt to decode an ASN.1 `VideotexString`.
pub fn videotex_string(self) -> Result<VideotexStringRef<'a>> {
self.try_into()
}

/// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new
/// nested reader and calling the provided argument with it.
pub fn sequence<F, T>(self, f: F) -> Result<T>
Expand All @@ -154,11 +134,6 @@ impl<'a> AnyRef<'a> {
pub fn utc_time(self) -> Result<UtcTime> {
self.try_into()
}

/// Attempt to decode an ASN.1 `UTF8String`.
pub fn utf8_string(self) -> Result<Utf8StringRef<'a>> {
self.try_into()
}
}

impl<'a> Choice<'a> for AnyRef<'a> {
Expand Down Expand Up @@ -194,6 +169,13 @@ impl Tagged for AnyRef<'_> {
}
}

#[cfg(feature = "alloc")]
impl ValueOrd for Any {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
}
}

impl ValueOrd for AnyRef<'_> {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
Expand Down Expand Up @@ -226,19 +208,35 @@ pub struct Any {
tag: Tag,

/// Inner value encoded as bytes.
value: Vec<u8>,
value: Bytes,
}

#[cfg(feature = "alloc")]
impl Any {
/// Create a new [`Any`] from the provided [`Tag`] and DER bytes.
pub fn new(tag: Tag, bytes: impl Into<Vec<u8>>) -> Result<Self> {
let value = bytes.into();
pub fn new(tag: Tag, bytes: &[u8]) -> Result<Self> {
let value = Bytes::new(bytes)?;

// Ensure the tag and value are a valid `AnyRef`.
AnyRef::new(tag, &value)?;
AnyRef::new(tag, value.as_slice())?;
Ok(Self { tag, value })
}

/// Attempt to decode this [`Any`] type into the inner value.
pub fn decode_into<'a, T>(&'a self) -> Result<T>
where
T: DecodeValue<'a> + FixedTag,
{
self.tag.assert_eq(T::TAG)?;
let header = Header {
tag: self.tag,
length: self.value.len(),
};

let mut decoder = SliceReader::new(self.value.as_slice())?;
let result = T::decode_value(&mut decoder, header)?;
decoder.finish(result)
}
}

#[cfg(feature = "alloc")]
Expand All @@ -253,26 +251,26 @@ impl<'a> Decode<'a> for Any {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
let header = Header::decode(reader)?;
let value = reader.read_vec(header.length)?;
Self::new(header.tag, value)
Self::new(header.tag, &value)
}
}

#[cfg(feature = "alloc")]
impl EncodeValue for Any {
fn value_len(&self) -> Result<Length> {
self.value.len().try_into()
Ok(self.value.len())
}

fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
writer.write(&self.value)
writer.write(self.value.as_slice())
}
}

#[cfg(feature = "alloc")]
impl<'a> From<&'a Any> for AnyRef<'a> {
fn from(any: &'a Any) -> AnyRef<'a> {
// Ensured to parse successfully in constructor
AnyRef::new(any.tag, &any.value).expect("invalid ANY")
AnyRef::new(any.tag, any.value.as_slice()).expect("invalid ANY")
}
}

Expand All @@ -282,3 +280,17 @@ impl Tagged for Any {
self.tag
}
}

#[cfg(feature = "alloc")]
impl<'a, T> From<T> for Any
where
T: Into<AnyRef<'a>>,
{
fn from(input: T) -> Any {
let anyref: AnyRef<'a> = input.into();
Self {
tag: anyref.tag(),
value: Bytes::new(anyref.value()).expect("invalid ANY"),
}
}
}
12 changes: 12 additions & 0 deletions der/src/asn1/ia5_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `IA5String` type.
///
/// Supports the [International Alphabet No. 5 (IA5)] character encoding, i.e.
Expand Down Expand Up @@ -99,6 +102,15 @@ impl<'a> TryFrom<AnyRef<'a>> for Ia5StringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for Ia5StringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<Ia5StringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> {
fn from(printable_string: Ia5StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Ia5String, printable_string.inner.into())
Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/printable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `PrintableString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -133,6 +136,15 @@ impl<'a> TryFrom<AnyRef<'a>> for PrintableStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for PrintableStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<PrintableStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> {
fn from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::PrintableString, printable_string.inner.into())
Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/teletex_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `TeletexString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -103,6 +106,15 @@ impl<'a> TryFrom<AnyRef<'a>> for TeletexStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for TeletexStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<TeletexStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> {
fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into())
Expand Down
18 changes: 15 additions & 3 deletions der/src/asn1/utf8_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use crate::{
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use alloc::{borrow::ToOwned, string::String};
use {
crate::asn1::Any,
alloc::{borrow::ToOwned, string::String},
};

/// ASN.1 `UTF8String` type.
///
Expand Down Expand Up @@ -95,9 +98,18 @@ impl<'a> TryFrom<AnyRef<'a>> for Utf8StringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for Utf8StringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<Utf8StringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> {
fn from(printable_string: Utf8StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Utf8String, printable_string.inner.into())
fn from(utf_string: Utf8StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Utf8String, utf_string.inner.into())
}
}

Expand Down
12 changes: 12 additions & 0 deletions der/src/asn1/videotex_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use crate::{
};
use core::{fmt, ops::Deref, str};

#[cfg(feature = "alloc")]
use crate::asn1::Any;

/// ASN.1 `VideotexString` type.
///
/// Supports a subset the ASCII character set (described below).
Expand Down Expand Up @@ -102,6 +105,15 @@ impl<'a> TryFrom<AnyRef<'a>> for VideotexStringRef<'a> {
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<&'a Any> for VideotexStringRef<'a> {
type Error = Error;

fn try_from(any: &'a Any) -> Result<VideotexStringRef<'a>> {
any.decode_into()
}
}

impl<'a> From<VideotexStringRef<'a>> for AnyRef<'a> {
fn from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::VideotexString, printable_string.inner.into())
Expand Down
Loading