• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! ASN.1 `ANY` type.
2 
3 use crate::{
4     asn1::*, ByteSlice, Choice, Decode, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind,
5     FixedTag, Header, Length, Reader, Result, SliceReader, Tag, Tagged, ValueOrd, Writer,
6 };
7 use core::cmp::Ordering;
8 
9 #[cfg(feature = "alloc")]
10 use alloc::vec::Vec;
11 
12 #[cfg(feature = "oid")]
13 use crate::asn1::ObjectIdentifier;
14 
15 /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value.
16 ///
17 /// This is a zero-copy reference type which borrows from the input data.
18 ///
19 /// Technically `ANY` hasn't been a recommended part of ASN.1 since the X.209
20 /// revision from 1988. It was deprecated and replaced by Information Object
21 /// Classes in X.680 in 1994, and X.690 no longer refers to it whatsoever.
22 ///
23 /// Nevertheless, this crate defines an `ANY` type as it remains a familiar
24 /// and useful concept which is still extensively used in things like
25 /// PKI-related RFCs.
26 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
27 pub struct AnyRef<'a> {
28     /// Tag representing the type of the encoded value.
29     tag: Tag,
30 
31     /// Inner value encoded as bytes.
32     value: ByteSlice<'a>,
33 }
34 
35 impl<'a> AnyRef<'a> {
36     /// [`AnyRef`] representation of the ASN.1 `NULL` type.
37     pub const NULL: Self = Self {
38         tag: Tag::Null,
39         value: ByteSlice::EMPTY,
40     };
41 
42     /// Create a new [`AnyRef`] from the provided [`Tag`] and DER bytes.
new(tag: Tag, bytes: &'a [u8]) -> Result<Self>43     pub fn new(tag: Tag, bytes: &'a [u8]) -> Result<Self> {
44         let value = ByteSlice::new(bytes).map_err(|_| ErrorKind::Length { tag })?;
45         Ok(Self { tag, value })
46     }
47 
48     /// Infallible creation of an [`AnyRef`] from a [`ByteSlice`].
from_tag_and_value(tag: Tag, value: ByteSlice<'a>) -> Self49     pub(crate) fn from_tag_and_value(tag: Tag, value: ByteSlice<'a>) -> Self {
50         Self { tag, value }
51     }
52 
53     /// Get the raw value for this [`AnyRef`] type as a byte slice.
value(self) -> &'a [u8]54     pub fn value(self) -> &'a [u8] {
55         self.value.as_slice()
56     }
57 
58     /// Attempt to decode this [`AnyRef`] type into the inner value.
decode_into<T>(self) -> Result<T> where T: DecodeValue<'a> + FixedTag,59     pub fn decode_into<T>(self) -> Result<T>
60     where
61         T: DecodeValue<'a> + FixedTag,
62     {
63         self.tag.assert_eq(T::TAG)?;
64         let header = Header {
65             tag: self.tag,
66             length: self.value.len(),
67         };
68 
69         let mut decoder = SliceReader::new(self.value())?;
70         let result = T::decode_value(&mut decoder, header)?;
71         decoder.finish(result)
72     }
73 
74     /// Is this value an ASN.1 `NULL` value?
is_null(self) -> bool75     pub fn is_null(self) -> bool {
76         self == Self::NULL
77     }
78 
79     /// Attempt to decode an ASN.1 `BIT STRING`.
bit_string(self) -> Result<BitStringRef<'a>>80     pub fn bit_string(self) -> Result<BitStringRef<'a>> {
81         self.try_into()
82     }
83 
84     /// Attempt to decode an ASN.1 `CONTEXT-SPECIFIC` field.
context_specific<T>(self) -> Result<ContextSpecific<T>> where T: Decode<'a>,85     pub fn context_specific<T>(self) -> Result<ContextSpecific<T>>
86     where
87         T: Decode<'a>,
88     {
89         self.try_into()
90     }
91 
92     /// Attempt to decode an ASN.1 `GeneralizedTime`.
generalized_time(self) -> Result<GeneralizedTime>93     pub fn generalized_time(self) -> Result<GeneralizedTime> {
94         self.try_into()
95     }
96 
97     /// Attempt to decode an ASN.1 `IA5String`.
ia5_string(self) -> Result<Ia5StringRef<'a>>98     pub fn ia5_string(self) -> Result<Ia5StringRef<'a>> {
99         self.try_into()
100     }
101 
102     /// Attempt to decode an ASN.1 `OCTET STRING`.
octet_string(self) -> Result<OctetStringRef<'a>>103     pub fn octet_string(self) -> Result<OctetStringRef<'a>> {
104         self.try_into()
105     }
106 
107     /// Attempt to decode an ASN.1 `OBJECT IDENTIFIER`.
108     #[cfg(feature = "oid")]
109     #[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
oid(self) -> Result<ObjectIdentifier>110     pub fn oid(self) -> Result<ObjectIdentifier> {
111         self.try_into()
112     }
113 
114     /// Attempt to decode an ASN.1 `OPTIONAL` value.
optional<T>(self) -> Result<Option<T>> where T: Choice<'a> + TryFrom<Self, Error = Error>,115     pub fn optional<T>(self) -> Result<Option<T>>
116     where
117         T: Choice<'a> + TryFrom<Self, Error = Error>,
118     {
119         if T::can_decode(self.tag) {
120             T::try_from(self).map(Some)
121         } else {
122             Ok(None)
123         }
124     }
125 
126     /// Attempt to decode an ASN.1 `PrintableString`.
printable_string(self) -> Result<PrintableStringRef<'a>>127     pub fn printable_string(self) -> Result<PrintableStringRef<'a>> {
128         self.try_into()
129     }
130 
131     /// Attempt to decode an ASN.1 `TeletexString`.
teletex_string(self) -> Result<TeletexStringRef<'a>>132     pub fn teletex_string(self) -> Result<TeletexStringRef<'a>> {
133         self.try_into()
134     }
135 
136     /// Attempt to decode an ASN.1 `VideotexString`.
videotex_string(self) -> Result<VideotexStringRef<'a>>137     pub fn videotex_string(self) -> Result<VideotexStringRef<'a>> {
138         self.try_into()
139     }
140 
141     /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new
142     /// nested reader and calling the provided argument with it.
sequence<F, T>(self, f: F) -> Result<T> where F: FnOnce(&mut SliceReader<'a>) -> Result<T>,143     pub fn sequence<F, T>(self, f: F) -> Result<T>
144     where
145         F: FnOnce(&mut SliceReader<'a>) -> Result<T>,
146     {
147         self.tag.assert_eq(Tag::Sequence)?;
148         let mut reader = SliceReader::new(self.value.as_slice())?;
149         let result = f(&mut reader)?;
150         reader.finish(result)
151     }
152 
153     /// Attempt to decode an ASN.1 `UTCTime`.
utc_time(self) -> Result<UtcTime>154     pub fn utc_time(self) -> Result<UtcTime> {
155         self.try_into()
156     }
157 
158     /// Attempt to decode an ASN.1 `UTF8String`.
utf8_string(self) -> Result<Utf8StringRef<'a>>159     pub fn utf8_string(self) -> Result<Utf8StringRef<'a>> {
160         self.try_into()
161     }
162 }
163 
164 impl<'a> Choice<'a> for AnyRef<'a> {
can_decode(_: Tag) -> bool165     fn can_decode(_: Tag) -> bool {
166         true
167     }
168 }
169 
170 impl<'a> Decode<'a> for AnyRef<'a> {
decode<R: Reader<'a>>(reader: &mut R) -> Result<AnyRef<'a>>171     fn decode<R: Reader<'a>>(reader: &mut R) -> Result<AnyRef<'a>> {
172         let header = Header::decode(reader)?;
173 
174         Ok(Self {
175             tag: header.tag,
176             value: ByteSlice::decode_value(reader, header)?,
177         })
178     }
179 }
180 
181 impl EncodeValue for AnyRef<'_> {
value_len(&self) -> Result<Length>182     fn value_len(&self) -> Result<Length> {
183         Ok(self.value.len())
184     }
185 
encode_value(&self, writer: &mut dyn Writer) -> Result<()>186     fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
187         writer.write(self.value())
188     }
189 }
190 
191 impl Tagged for AnyRef<'_> {
tag(&self) -> Tag192     fn tag(&self) -> Tag {
193         self.tag
194     }
195 }
196 
197 impl ValueOrd for AnyRef<'_> {
value_cmp(&self, other: &Self) -> Result<Ordering>198     fn value_cmp(&self, other: &Self) -> Result<Ordering> {
199         self.value.der_cmp(&other.value)
200     }
201 }
202 
203 impl<'a> From<AnyRef<'a>> for ByteSlice<'a> {
from(any: AnyRef<'a>) -> ByteSlice<'a>204     fn from(any: AnyRef<'a>) -> ByteSlice<'a> {
205         any.value
206     }
207 }
208 
209 impl<'a> TryFrom<&'a [u8]> for AnyRef<'a> {
210     type Error = Error;
211 
try_from(bytes: &'a [u8]) -> Result<AnyRef<'a>>212     fn try_from(bytes: &'a [u8]) -> Result<AnyRef<'a>> {
213         AnyRef::from_der(bytes)
214     }
215 }
216 
217 /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value.
218 ///
219 /// This type provides the same functionality as [`AnyRef`] but owns the
220 /// backing data.
221 #[cfg(feature = "alloc")]
222 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
223 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
224 pub struct Any {
225     /// Tag representing the type of the encoded value.
226     tag: Tag,
227 
228     /// Inner value encoded as bytes.
229     value: Vec<u8>,
230 }
231 
232 #[cfg(feature = "alloc")]
233 impl Any {
234     /// Create a new [`Any`] from the provided [`Tag`] and DER bytes.
new(tag: Tag, bytes: impl Into<Vec<u8>>) -> Result<Self>235     pub fn new(tag: Tag, bytes: impl Into<Vec<u8>>) -> Result<Self> {
236         let value = bytes.into();
237 
238         // Ensure the tag and value are a valid `AnyRef`.
239         AnyRef::new(tag, &value)?;
240         Ok(Self { tag, value })
241     }
242 }
243 
244 #[cfg(feature = "alloc")]
245 impl Choice<'_> for Any {
can_decode(_: Tag) -> bool246     fn can_decode(_: Tag) -> bool {
247         true
248     }
249 }
250 
251 #[cfg(feature = "alloc")]
252 impl<'a> Decode<'a> for Any {
decode<R: Reader<'a>>(reader: &mut R) -> Result<Self>253     fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
254         let header = Header::decode(reader)?;
255         let value = reader.read_vec(header.length)?;
256         Self::new(header.tag, value)
257     }
258 }
259 
260 #[cfg(feature = "alloc")]
261 impl EncodeValue for Any {
value_len(&self) -> Result<Length>262     fn value_len(&self) -> Result<Length> {
263         self.value.len().try_into()
264     }
265 
encode_value(&self, writer: &mut dyn Writer) -> Result<()>266     fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
267         writer.write(&self.value)
268     }
269 }
270 
271 #[cfg(feature = "alloc")]
272 impl<'a> From<&'a Any> for AnyRef<'a> {
from(any: &'a Any) -> AnyRef<'a>273     fn from(any: &'a Any) -> AnyRef<'a> {
274         // Ensured to parse successfully in constructor
275         AnyRef::new(any.tag, &any.value).expect("invalid ANY")
276     }
277 }
278 
279 #[cfg(feature = "alloc")]
280 impl Tagged for Any {
tag(&self) -> Tag281     fn tag(&self) -> Tag {
282         self.tag
283     }
284 }
285