blob: 017a90908229bd7a42b1c4f03f30ac110f6acc38 [file] [log] [blame]
//! ASN.1 `ANY` type.
#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))]
use crate::{
BytesRef, Choice, Decode, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, Header, Length,
Reader, Result, SliceReader, Tag, Tagged, ValueOrd, Writer,
};
use core::cmp::Ordering;
#[cfg(feature = "alloc")]
use crate::SliceWriter;
/// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value.
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// Technically `ANY` hasn't been a recommended part of ASN.1 since the X.209
/// revision from 1988. It was deprecated and replaced by Information Object
/// Classes in X.680 in 1994, and X.690 no longer refers to it whatsoever.
///
/// Nevertheless, this crate defines an `ANY` type as it remains a familiar
/// and useful concept which is still extensively used in things like
/// PKI-related RFCs.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct AnyRef<'a> {
/// Tag representing the type of the encoded value.
tag: Tag,
/// Inner value encoded as bytes.
value: BytesRef<'a>,
}
impl<'a> AnyRef<'a> {
/// [`AnyRef`] representation of the ASN.1 `NULL` type.
pub const NULL: Self = Self {
tag: Tag::Null,
value: BytesRef::EMPTY,
};
/// Create a new [`AnyRef`] from the provided [`Tag`] and DER bytes.
pub fn new(tag: Tag, bytes: &'a [u8]) -> Result<Self> {
let value = BytesRef::new(bytes).map_err(|_| ErrorKind::Length { tag })?;
Ok(Self { tag, value })
}
/// Infallible creation of an [`AnyRef`] from a [`BytesRef`].
pub(crate) fn from_tag_and_value(tag: Tag, value: BytesRef<'a>) -> Self {
Self { tag, value }
}
/// Get the raw value for this [`AnyRef`] type as a byte slice.
pub fn value(self) -> &'a [u8] {
self.value.as_slice()
}
/// Attempt to decode this [`AnyRef`] type into the inner value.
pub fn decode_as<T>(self) -> Result<T>
where
T: Choice<'a> + DecodeValue<'a>,
{
if !T::can_decode(self.tag) {
return Err(self.tag.unexpected_error(None));
}
let header = Header {
tag: self.tag,
length: self.value.len(),
};
let mut decoder = SliceReader::new(self.value())?;
let result = T::decode_value(&mut decoder, header)?;
decoder.finish(result)
}
/// Is this value an ASN.1 `NULL` value?
pub fn is_null(self) -> bool {
self == Self::NULL
}
/// 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>
where
F: FnOnce(&mut SliceReader<'a>) -> Result<T>,
{
self.tag.assert_eq(Tag::Sequence)?;
let mut reader = SliceReader::new(self.value.as_slice())?;
let result = f(&mut reader)?;
reader.finish(result)
}
}
impl<'a> Choice<'a> for AnyRef<'a> {
fn can_decode(_: Tag) -> bool {
true
}
}
impl<'a> Decode<'a> for AnyRef<'a> {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<AnyRef<'a>> {
let header = Header::decode(reader)?;
Self::decode_value(reader, header)
}
}
impl<'a> DecodeValue<'a> for AnyRef<'a> {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
Ok(Self {
tag: header.tag,
value: BytesRef::decode_value(reader, header)?,
})
}
}
impl EncodeValue for AnyRef<'_> {
fn value_len(&self) -> Result<Length> {
Ok(self.value.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.value())
}
}
impl Tagged for AnyRef<'_> {
fn tag(&self) -> Tag {
self.tag
}
}
impl ValueOrd for AnyRef<'_> {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
}
}
impl<'a> From<AnyRef<'a>> for BytesRef<'a> {
fn from(any: AnyRef<'a>) -> BytesRef<'a> {
any.value
}
}
impl<'a> TryFrom<&'a [u8]> for AnyRef<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<AnyRef<'a>> {
AnyRef::from_der(bytes)
}
}
#[cfg(feature = "alloc")]
pub use self::allocating::Any;
#[cfg(feature = "alloc")]
mod allocating {
use super::*;
use crate::{referenced::*, BytesOwned};
use alloc::boxed::Box;
/// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value.
///
/// This type provides the same functionality as [`AnyRef`] but owns the
/// backing data.
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Any {
/// Tag representing the type of the encoded value.
tag: Tag,
/// Inner value encoded as bytes.
value: BytesOwned,
}
impl Any {
/// Create a new [`Any`] from the provided [`Tag`] and DER bytes.
pub fn new(tag: Tag, bytes: impl Into<Box<[u8]>>) -> Result<Self> {
let value = BytesOwned::new(bytes)?;
// Ensure the tag and value are a valid `AnyRef`.
AnyRef::new(tag, value.as_slice())?;
Ok(Self { tag, value })
}
/// Allow access to value
pub fn value(&self) -> &[u8] {
self.value.as_slice()
}
/// Attempt to decode this [`Any`] type into the inner value.
pub fn decode_as<'a, T>(&'a self) -> Result<T>
where
T: Choice<'a> + DecodeValue<'a>,
{
AnyRef::from(self).decode_as()
}
/// Encode the provided type as an [`Any`] value.
pub fn encode_from<T>(msg: &T) -> Result<Self>
where
T: Tagged + EncodeValue,
{
let encoded_len = usize::try_from(msg.value_len()?)?;
let mut buf = vec![0u8; encoded_len];
let mut writer = SliceWriter::new(&mut buf);
msg.encode_value(&mut writer)?;
writer.finish()?;
Any::new(msg.tag(), buf)
}
/// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new
/// nested reader and calling the provided argument with it.
pub fn sequence<'a, F, T>(&'a self, f: F) -> Result<T>
where
F: FnOnce(&mut SliceReader<'a>) -> Result<T>,
{
AnyRef::from(self).sequence(f)
}
/// [`Any`] representation of the ASN.1 `NULL` type.
pub fn null() -> Self {
Self {
tag: Tag::Null,
value: BytesOwned::default(),
}
}
}
impl Choice<'_> for Any {
fn can_decode(_: Tag) -> bool {
true
}
}
impl<'a> Decode<'a> for Any {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
let header = Header::decode(reader)?;
Self::decode_value(reader, header)
}
}
impl<'a> DecodeValue<'a> for Any {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
let value = reader.read_vec(header.length)?;
Self::new(header.tag, value)
}
}
impl EncodeValue for Any {
fn value_len(&self) -> Result<Length> {
Ok(self.value.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.value.as_slice())
}
}
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.as_slice()).expect("invalid ANY")
}
}
impl Tagged for Any {
fn tag(&self) -> Tag {
self.tag
}
}
impl ValueOrd for Any {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
}
}
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: BytesOwned::from(anyref.value),
}
}
}
impl<'a> RefToOwned<'a> for AnyRef<'a> {
type Owned = Any;
fn ref_to_owned(&self) -> Self::Owned {
Any {
tag: self.tag(),
value: BytesOwned::from(self.value),
}
}
}
impl OwnedToRef for Any {
type Borrowed<'a> = AnyRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
self.into()
}
}
impl Any {
/// Is this value an ASN.1 `NULL` value?
pub fn is_null(&self) -> bool {
self.owned_to_ref() == AnyRef::NULL
}
}
}