/rust/registry/src/index.crates.io-6f17d22bba15001f/der-0.7.10/src/asn1/any.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! ASN.1 `ANY` type. |
2 | | |
3 | | #![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))] |
4 | | |
5 | | use crate::{ |
6 | | BytesRef, Choice, Decode, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, Header, Length, |
7 | | Reader, Result, SliceReader, Tag, Tagged, ValueOrd, Writer, |
8 | | }; |
9 | | use core::cmp::Ordering; |
10 | | |
11 | | #[cfg(feature = "alloc")] |
12 | | use crate::SliceWriter; |
13 | | |
14 | | /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. |
15 | | /// |
16 | | /// This is a zero-copy reference type which borrows from the input data. |
17 | | /// |
18 | | /// Technically `ANY` hasn't been a recommended part of ASN.1 since the X.209 |
19 | | /// revision from 1988. It was deprecated and replaced by Information Object |
20 | | /// Classes in X.680 in 1994, and X.690 no longer refers to it whatsoever. |
21 | | /// |
22 | | /// Nevertheless, this crate defines an `ANY` type as it remains a familiar |
23 | | /// and useful concept which is still extensively used in things like |
24 | | /// PKI-related RFCs. |
25 | | #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] |
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: BytesRef<'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: BytesRef::EMPTY, |
40 | | }; |
41 | | |
42 | | /// Create a new [`AnyRef`] from the provided [`Tag`] and DER bytes. |
43 | 0 | pub fn new(tag: Tag, bytes: &'a [u8]) -> Result<Self> { |
44 | 0 | let value = BytesRef::new(bytes).map_err(|_| ErrorKind::Length { tag })?; |
45 | 0 | Ok(Self { tag, value }) |
46 | 0 | } |
47 | | |
48 | | /// Infallible creation of an [`AnyRef`] from a [`BytesRef`]. |
49 | 0 | pub(crate) fn from_tag_and_value(tag: Tag, value: BytesRef<'a>) -> Self { |
50 | 0 | Self { tag, value } |
51 | 0 | } |
52 | | |
53 | | /// Get the raw value for this [`AnyRef`] type as a byte slice. |
54 | 0 | pub fn value(self) -> &'a [u8] { |
55 | 0 | self.value.as_slice() |
56 | 0 | } |
57 | | |
58 | | /// Attempt to decode this [`AnyRef`] type into the inner value. |
59 | 0 | pub fn decode_as<T>(self) -> Result<T> |
60 | 0 | where |
61 | 0 | T: Choice<'a> + DecodeValue<'a>, |
62 | 0 | { |
63 | 0 | if !T::can_decode(self.tag) { |
64 | 0 | return Err(self.tag.unexpected_error(None)); |
65 | 0 | } |
66 | 0 |
|
67 | 0 | let header = Header { |
68 | 0 | tag: self.tag, |
69 | 0 | length: self.value.len(), |
70 | 0 | }; |
71 | | |
72 | 0 | let mut decoder = SliceReader::new(self.value())?; |
73 | 0 | let result = T::decode_value(&mut decoder, header)?; |
74 | 0 | decoder.finish(result) |
75 | 0 | } Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::bit_string::BitStringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::ia5_string::Ia5StringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::utf8_string::Utf8StringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::octet_string::OctetStringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::teletex_string::TeletexStringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::videotex_string::VideotexStringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::generalized_time::GeneralizedTime> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::printable_string::PrintableStringRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::null::Null> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::utc_time::UtcTime> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::bit_string::allocating::BitString> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::ia5_string::allocation::Ia5String> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::octet_string::allocating::OctetString> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::teletex_string::allocation::TeletexString> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::printable_string::allocation::PrintableString> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::integer::int::IntRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::integer::uint::UintRef> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::integer::int::allocating::Int> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<der::asn1::integer::uint::allocating::Uint> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<i8> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<u8> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<i32> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<u32> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<i128> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<u128> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<i16> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<u16> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<i64> Unexecuted instantiation: <der::asn1::any::AnyRef>::decode_as::<u64> |
76 | | |
77 | | /// Is this value an ASN.1 `NULL` value? |
78 | 0 | pub fn is_null(self) -> bool { |
79 | 0 | self == Self::NULL |
80 | 0 | } |
81 | | |
82 | | /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new |
83 | | /// nested reader and calling the provided argument with it. |
84 | 0 | pub fn sequence<F, T>(self, f: F) -> Result<T> |
85 | 0 | where |
86 | 0 | F: FnOnce(&mut SliceReader<'a>) -> Result<T>, |
87 | 0 | { |
88 | 0 | self.tag.assert_eq(Tag::Sequence)?; |
89 | 0 | let mut reader = SliceReader::new(self.value.as_slice())?; |
90 | 0 | let result = f(&mut reader)?; |
91 | 0 | reader.finish(result) |
92 | 0 | } |
93 | | } |
94 | | |
95 | | impl<'a> Choice<'a> for AnyRef<'a> { |
96 | 0 | fn can_decode(_: Tag) -> bool { |
97 | 0 | true |
98 | 0 | } |
99 | | } |
100 | | |
101 | | impl<'a> Decode<'a> for AnyRef<'a> { |
102 | 0 | fn decode<R: Reader<'a>>(reader: &mut R) -> Result<AnyRef<'a>> { |
103 | 0 | let header = Header::decode(reader)?; |
104 | 0 | Self::decode_value(reader, header) |
105 | 0 | } |
106 | | } |
107 | | |
108 | | impl<'a> DecodeValue<'a> for AnyRef<'a> { |
109 | 0 | fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { |
110 | 0 | Ok(Self { |
111 | 0 | tag: header.tag, |
112 | 0 | value: BytesRef::decode_value(reader, header)?, |
113 | | }) |
114 | 0 | } |
115 | | } |
116 | | |
117 | | impl EncodeValue for AnyRef<'_> { |
118 | 0 | fn value_len(&self) -> Result<Length> { |
119 | 0 | Ok(self.value.len()) |
120 | 0 | } |
121 | | |
122 | 0 | fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { |
123 | 0 | writer.write(self.value()) |
124 | 0 | } |
125 | | } |
126 | | |
127 | | impl Tagged for AnyRef<'_> { |
128 | 0 | fn tag(&self) -> Tag { |
129 | 0 | self.tag |
130 | 0 | } |
131 | | } |
132 | | |
133 | | impl ValueOrd for AnyRef<'_> { |
134 | 0 | fn value_cmp(&self, other: &Self) -> Result<Ordering> { |
135 | 0 | self.value.der_cmp(&other.value) |
136 | 0 | } |
137 | | } |
138 | | |
139 | | impl<'a> From<AnyRef<'a>> for BytesRef<'a> { |
140 | 0 | fn from(any: AnyRef<'a>) -> BytesRef<'a> { |
141 | 0 | any.value |
142 | 0 | } |
143 | | } |
144 | | |
145 | | impl<'a> TryFrom<&'a [u8]> for AnyRef<'a> { |
146 | | type Error = Error; |
147 | | |
148 | 0 | fn try_from(bytes: &'a [u8]) -> Result<AnyRef<'a>> { |
149 | 0 | AnyRef::from_der(bytes) |
150 | 0 | } |
151 | | } |
152 | | |
153 | | #[cfg(feature = "alloc")] |
154 | | pub use self::allocating::Any; |
155 | | |
156 | | #[cfg(feature = "alloc")] |
157 | | mod allocating { |
158 | | use super::*; |
159 | | use crate::{referenced::*, BytesOwned}; |
160 | | use alloc::boxed::Box; |
161 | | |
162 | | /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. |
163 | | /// |
164 | | /// This type provides the same functionality as [`AnyRef`] but owns the |
165 | | /// backing data. |
166 | | #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] |
167 | | #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] |
168 | | pub struct Any { |
169 | | /// Tag representing the type of the encoded value. |
170 | | tag: Tag, |
171 | | |
172 | | /// Inner value encoded as bytes. |
173 | | value: BytesOwned, |
174 | | } |
175 | | |
176 | | impl Any { |
177 | | /// Create a new [`Any`] from the provided [`Tag`] and DER bytes. |
178 | 0 | pub fn new(tag: Tag, bytes: impl Into<Box<[u8]>>) -> Result<Self> { |
179 | 0 | let value = BytesOwned::new(bytes)?; |
180 | | |
181 | | // Ensure the tag and value are a valid `AnyRef`. |
182 | 0 | AnyRef::new(tag, value.as_slice())?; |
183 | 0 | Ok(Self { tag, value }) |
184 | 0 | } |
185 | | |
186 | | /// Allow access to value |
187 | 0 | pub fn value(&self) -> &[u8] { |
188 | 0 | self.value.as_slice() |
189 | 0 | } |
190 | | |
191 | | /// Attempt to decode this [`Any`] type into the inner value. |
192 | 0 | pub fn decode_as<'a, T>(&'a self) -> Result<T> |
193 | 0 | where |
194 | 0 | T: Choice<'a> + DecodeValue<'a>, |
195 | 0 | { |
196 | 0 | AnyRef::from(self).decode_as() |
197 | 0 | } Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::bit_string::BitStringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::ia5_string::Ia5StringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::utf8_string::Utf8StringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::octet_string::OctetStringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::teletex_string::TeletexStringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::videotex_string::VideotexStringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::generalized_time::GeneralizedTime> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::printable_string::PrintableStringRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::null::Null> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::utc_time::UtcTime> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::bit_string::allocating::BitString> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::ia5_string::allocation::Ia5String> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::octet_string::allocating::OctetString> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::teletex_string::allocation::TeletexString> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::printable_string::allocation::PrintableString> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::integer::int::IntRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::integer::uint::UintRef> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::integer::int::allocating::Int> Unexecuted instantiation: <der::asn1::any::allocating::Any>::decode_as::<der::asn1::integer::uint::allocating::Uint> |
198 | | |
199 | | /// Encode the provided type as an [`Any`] value. |
200 | 0 | pub fn encode_from<T>(msg: &T) -> Result<Self> |
201 | 0 | where |
202 | 0 | T: Tagged + EncodeValue, |
203 | 0 | { |
204 | 0 | let encoded_len = usize::try_from(msg.value_len()?)?; |
205 | 0 | let mut buf = vec![0u8; encoded_len]; |
206 | 0 | let mut writer = SliceWriter::new(&mut buf); |
207 | 0 | msg.encode_value(&mut writer)?; |
208 | 0 | writer.finish()?; |
209 | 0 | Any::new(msg.tag(), buf) |
210 | 0 | } |
211 | | |
212 | | /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new |
213 | | /// nested reader and calling the provided argument with it. |
214 | 0 | pub fn sequence<'a, F, T>(&'a self, f: F) -> Result<T> |
215 | 0 | where |
216 | 0 | F: FnOnce(&mut SliceReader<'a>) -> Result<T>, |
217 | 0 | { |
218 | 0 | AnyRef::from(self).sequence(f) |
219 | 0 | } |
220 | | |
221 | | /// [`Any`] representation of the ASN.1 `NULL` type. |
222 | 0 | pub fn null() -> Self { |
223 | 0 | Self { |
224 | 0 | tag: Tag::Null, |
225 | 0 | value: BytesOwned::default(), |
226 | 0 | } |
227 | 0 | } |
228 | | } |
229 | | |
230 | | impl Choice<'_> for Any { |
231 | 0 | fn can_decode(_: Tag) -> bool { |
232 | 0 | true |
233 | 0 | } |
234 | | } |
235 | | |
236 | | impl<'a> Decode<'a> for Any { |
237 | 0 | fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> { |
238 | 0 | let header = Header::decode(reader)?; |
239 | 0 | Self::decode_value(reader, header) |
240 | 0 | } |
241 | | } |
242 | | |
243 | | impl<'a> DecodeValue<'a> for Any { |
244 | 0 | fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { |
245 | 0 | let value = reader.read_vec(header.length)?; |
246 | 0 | Self::new(header.tag, value) |
247 | 0 | } |
248 | | } |
249 | | |
250 | | impl EncodeValue for Any { |
251 | 0 | fn value_len(&self) -> Result<Length> { |
252 | 0 | Ok(self.value.len()) |
253 | 0 | } |
254 | | |
255 | 0 | fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { |
256 | 0 | writer.write(self.value.as_slice()) |
257 | 0 | } |
258 | | } |
259 | | |
260 | | impl<'a> From<&'a Any> for AnyRef<'a> { |
261 | 0 | fn from(any: &'a Any) -> AnyRef<'a> { |
262 | 0 | // Ensured to parse successfully in constructor |
263 | 0 | AnyRef::new(any.tag, any.value.as_slice()).expect("invalid ANY") |
264 | 0 | } |
265 | | } |
266 | | |
267 | | impl Tagged for Any { |
268 | 0 | fn tag(&self) -> Tag { |
269 | 0 | self.tag |
270 | 0 | } |
271 | | } |
272 | | |
273 | | impl ValueOrd for Any { |
274 | 0 | fn value_cmp(&self, other: &Self) -> Result<Ordering> { |
275 | 0 | self.value.der_cmp(&other.value) |
276 | 0 | } |
277 | | } |
278 | | |
279 | | impl<'a, T> From<T> for Any |
280 | | where |
281 | | T: Into<AnyRef<'a>>, |
282 | | { |
283 | 0 | fn from(input: T) -> Any { |
284 | 0 | let anyref: AnyRef<'a> = input.into(); |
285 | 0 | Self { |
286 | 0 | tag: anyref.tag(), |
287 | 0 | value: BytesOwned::from(anyref.value), |
288 | 0 | } |
289 | 0 | } |
290 | | } |
291 | | |
292 | | impl<'a> RefToOwned<'a> for AnyRef<'a> { |
293 | | type Owned = Any; |
294 | 0 | fn ref_to_owned(&self) -> Self::Owned { |
295 | 0 | Any { |
296 | 0 | tag: self.tag(), |
297 | 0 | value: BytesOwned::from(self.value), |
298 | 0 | } |
299 | 0 | } |
300 | | } |
301 | | |
302 | | impl OwnedToRef for Any { |
303 | | type Borrowed<'a> = AnyRef<'a>; |
304 | 0 | fn owned_to_ref(&self) -> Self::Borrowed<'_> { |
305 | 0 | self.into() |
306 | 0 | } |
307 | | } |
308 | | |
309 | | impl Any { |
310 | | /// Is this value an ASN.1 `NULL` value? |
311 | 0 | pub fn is_null(&self) -> bool { |
312 | 0 | self.owned_to_ref() == AnyRef::NULL |
313 | 0 | } |
314 | | } |
315 | | } |