Coverage Report

Created: 2025-07-02 06:49

/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
}