1use crate::ber::*;
2use crate::*;
3use alloc::borrow::Cow;
4#[cfg(not(feature = "std"))]
5use alloc::string::{String, ToString};
6use core::convert::{TryFrom, TryInto};
7
8use self::debug::trace;
9
10#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct Any<'a> {
18 pub header: Header<'a>,
20 pub data: &'a [u8],
22}
23
24impl<'a> Any<'a> {
25 #[inline]
27 pub const fn new(header: Header<'a>, data: &'a [u8]) -> Self {
28 Any { header, data }
29 }
30
31 #[inline]
33 pub const fn from_tag_and_data(tag: Tag, data: &'a [u8]) -> Self {
34 let constructed = matches!(tag, Tag::Sequence | Tag::Set);
35 Any {
36 header: Header {
37 tag,
38 constructed,
39 class: Class::Universal,
40 length: Length::Definite(data.len()),
41 raw_tag: None,
42 },
43 data,
44 }
45 }
46
47 #[inline]
49 pub const fn class(&self) -> Class {
50 self.header.class
51 }
52
53 #[inline]
55 pub fn with_class(self, class: Class) -> Self {
56 Any {
57 header: self.header.with_class(class),
58 ..self
59 }
60 }
61
62 #[inline]
64 pub const fn tag(&self) -> Tag {
65 self.header.tag
66 }
67
68 #[inline]
70 pub fn with_tag(self, tag: Tag) -> Self {
71 Any {
72 header: self.header.with_tag(tag),
73 data: self.data,
74 }
75 }
76
77 #[inline]
79 pub fn as_bytes(&self) -> &'a [u8] {
80 self.data
81 }
82
83 #[inline]
84 pub fn parse_ber<T>(&self) -> ParseResult<'a, T>
85 where
86 T: FromBer<'a>,
87 {
88 T::from_ber(self.data)
89 }
90
91 pub fn from_ber_and_then<F, T, E>(
95 class: Class,
96 tag: u32,
97 bytes: &'a [u8],
98 op: F,
99 ) -> ParseResult<'a, T, E>
100 where
101 F: FnOnce(&'a [u8]) -> ParseResult<'a, T, E>,
102 E: From<Error>,
103 {
104 let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
105 any.tag()
106 .assert_eq(Tag(tag))
107 .map_err(|e| Err::Error(e.into()))?;
108 any.class()
109 .assert_eq(class)
110 .map_err(|e| Err::Error(e.into()))?;
111 let (_, res) = op(any.data)?;
112 Ok((rem, res))
113 }
114
115 pub fn from_der_and_then<F, T, E>(
119 class: Class,
120 tag: u32,
121 bytes: &'a [u8],
122 op: F,
123 ) -> ParseResult<'a, T, E>
124 where
125 F: FnOnce(&'a [u8]) -> ParseResult<'a, T, E>,
126 E: From<Error>,
127 {
128 let (rem, any) = Any::from_der(bytes).map_err(Err::convert)?;
129 any.tag()
130 .assert_eq(Tag(tag))
131 .map_err(|e| Err::Error(e.into()))?;
132 any.class()
133 .assert_eq(class)
134 .map_err(|e| Err::Error(e.into()))?;
135 let (_, res) = op(any.data)?;
136 Ok((rem, res))
137 }
138
139 #[inline]
140 pub fn parse_der<T>(&self) -> ParseResult<'a, T>
141 where
142 T: FromDer<'a>,
143 {
144 T::from_der(self.data)
145 }
146
147 #[inline]
149 pub fn parse_ber_content<'i>(i: &'i [u8], header: &'_ Header) -> ParseResult<'i, &'i [u8]> {
150 header.parse_ber_content(i)
151 }
152
153 #[inline]
155 pub fn parse_der_content<'i>(i: &'i [u8], header: &'_ Header) -> ParseResult<'i, &'i [u8]> {
156 header.assert_definite()?;
157 DerParser::get_object_content(i, header, 8)
158 }
159}
160
161macro_rules! impl_any_into {
162 (IMPL $sname:expr, $fn_name:ident => $ty:ty, $asn1:expr) => {
163 #[doc = "Attempt to convert object to `"]
164 #[doc = $sname]
165 #[doc = "` (ASN.1 type: `"]
166 #[doc = $asn1]
167 #[doc = "`)."]
168 pub fn $fn_name(self) -> Result<$ty> {
169 self.try_into()
170 }
171 };
172 ($fn_name:ident => $ty:ty, $asn1:expr) => {
173 impl_any_into! {
174 IMPL stringify!($ty), $fn_name => $ty, $asn1
175 }
176 };
177}
178
179macro_rules! impl_any_as {
180 (IMPL $sname:expr, $fn_name:ident => $ty:ty, $asn1:expr) => {
181 #[doc = "Attempt to create ASN.1 type `"]
182 #[doc = $asn1]
183 #[doc = "` from this object."]
184 #[inline]
185 pub fn $fn_name(&self) -> Result<$ty> {
186 TryFrom::try_from(self)
187 }
188 };
189 ($fn_name:ident => $ty:ty, $asn1:expr) => {
190 impl_any_as! {
191 IMPL stringify!($ty), $fn_name => $ty, $asn1
192 }
193 };
194}
195
196impl<'a> Any<'a> {
197 impl_any_into!(bitstring => BitString<'a>, "BIT STRING");
198 impl_any_into!(bmpstring => BmpString<'a>, "BMPString");
199 impl_any_into!(bool => bool, "BOOLEAN");
200 impl_any_into!(boolean => Boolean, "BOOLEAN");
201 impl_any_into!(embedded_pdv => EmbeddedPdv<'a>, "EMBEDDED PDV");
202 impl_any_into!(enumerated => Enumerated, "ENUMERATED");
203 impl_any_into!(generalizedtime => GeneralizedTime, "GeneralizedTime");
204 impl_any_into!(generalstring => GeneralString<'a>, "GeneralString");
205 impl_any_into!(graphicstring => GraphicString<'a>, "GraphicString");
206 impl_any_into!(i8 => i8, "INTEGER");
207 impl_any_into!(i16 => i16, "INTEGER");
208 impl_any_into!(i32 => i32, "INTEGER");
209 impl_any_into!(i64 => i64, "INTEGER");
210 impl_any_into!(i128 => i128, "INTEGER");
211 impl_any_into!(ia5string => Ia5String<'a>, "IA5String");
212 impl_any_into!(integer => Integer<'a>, "INTEGER");
213 impl_any_into!(null => Null, "NULL");
214 impl_any_into!(numericstring => NumericString<'a>, "NumericString");
215 impl_any_into!(objectdescriptor => ObjectDescriptor<'a>, "ObjectDescriptor");
216 impl_any_into!(octetstring => OctetString<'a>, "OCTET STRING");
217 impl_any_into!(oid => Oid<'a>, "OBJECT IDENTIFIER");
218 impl_any_into!(real => Real, "REAL");
219 pub fn relative_oid(self) -> Result<Oid<'a>> {
221 self.header.assert_tag(Tag::RelativeOid)?;
222 let asn1 = Cow::Borrowed(self.data);
223 Ok(Oid::new_relative(asn1))
224 }
225 impl_any_into!(printablestring => PrintableString<'a>, "PrintableString");
226 impl_any_into!(sequence => Sequence<'a>, "SEQUENCE");
228 impl_any_into!(set => Set<'a>, "SET");
229 impl_any_into!(str => &'a str, "UTF8String");
230 impl_any_into!(string => String, "UTF8String");
231 impl_any_into!(teletexstring => TeletexString<'a>, "TeletexString");
232 impl_any_into!(u8 => u8, "INTEGER");
233 impl_any_into!(u16 => u16, "INTEGER");
234 impl_any_into!(u32 => u32, "INTEGER");
235 impl_any_into!(u64 => u64, "INTEGER");
236 impl_any_into!(u128 => u128, "INTEGER");
237 impl_any_into!(universalstring => UniversalString<'a>, "UniversalString");
238 impl_any_into!(utctime => UtcTime, "UTCTime");
239 impl_any_into!(utf8string => Utf8String<'a>, "UTF8String");
240 impl_any_into!(videotexstring => VideotexString<'a>, "VideotexString");
241 impl_any_into!(visiblestring => VisibleString<'a>, "VisibleString");
242
243 impl_any_as!(as_bitstring => BitString, "BITSTRING");
244 impl_any_as!(as_bmpstring => BmpString, "BMPString");
245 impl_any_as!(as_bool => bool, "BOOLEAN");
246 impl_any_as!(as_boolean => Boolean, "BOOLEAN");
247 impl_any_as!(as_embedded_pdv => EmbeddedPdv, "EMBEDDED PDV");
248 impl_any_as!(as_endofcontent => EndOfContent, "END OF CONTENT (not a real ASN.1 type)");
249 impl_any_as!(as_enumerated => Enumerated, "ENUMERATED");
250 impl_any_as!(as_generalizedtime => GeneralizedTime, "GeneralizedTime");
251 impl_any_as!(as_generalstring => GeneralString, "GeneralString");
252 impl_any_as!(as_graphicstring => GraphicString, "GraphicString");
253 impl_any_as!(as_i8 => i8, "INTEGER");
254 impl_any_as!(as_i16 => i16, "INTEGER");
255 impl_any_as!(as_i32 => i32, "INTEGER");
256 impl_any_as!(as_i64 => i64, "INTEGER");
257 impl_any_as!(as_i128 => i128, "INTEGER");
258 impl_any_as!(as_ia5string => Ia5String, "IA5String");
259 impl_any_as!(as_integer => Integer, "INTEGER");
260 impl_any_as!(as_null => Null, "NULL");
261 impl_any_as!(as_numericstring => NumericString, "NumericString");
262 impl_any_as!(as_objectdescriptor => ObjectDescriptor, "OBJECT IDENTIFIER");
263 impl_any_as!(as_octetstring => OctetString, "OCTET STRING");
264 impl_any_as!(as_oid => Oid, "OBJECT IDENTIFIER");
265 impl_any_as!(as_real => Real, "REAL");
266 pub fn as_relative_oid(&self) -> Result<Oid<'a>> {
268 self.header.assert_tag(Tag::RelativeOid)?;
269 let asn1 = Cow::Borrowed(self.data);
270 Ok(Oid::new_relative(asn1))
271 }
272 impl_any_as!(as_printablestring => PrintableString, "PrintableString");
273 impl_any_as!(as_sequence => Sequence, "SEQUENCE");
274 impl_any_as!(as_set => Set, "SET");
275 impl_any_as!(as_str => &str, "UTF8String");
276 impl_any_as!(as_string => String, "UTF8String");
277 impl_any_as!(as_teletexstring => TeletexString, "TeletexString");
278 impl_any_as!(as_u8 => u8, "INTEGER");
279 impl_any_as!(as_u16 => u16, "INTEGER");
280 impl_any_as!(as_u32 => u32, "INTEGER");
281 impl_any_as!(as_u64 => u64, "INTEGER");
282 impl_any_as!(as_u128 => u128, "INTEGER");
283 impl_any_as!(as_universalstring => UniversalString, "UniversalString");
284 impl_any_as!(as_utctime => UtcTime, "UTCTime");
285 impl_any_as!(as_utf8string => Utf8String, "UTF8String");
286 impl_any_as!(as_videotexstring => VideotexString, "VideotexString");
287 impl_any_as!(as_visiblestring => VisibleString, "VisibleString");
288
289 pub fn as_optional<'b, T>(&'b self) -> Result<Option<T>>
291 where
292 T: TryFrom<&'b Any<'a>, Error = Error>,
293 'a: 'b,
294 {
295 match TryFrom::try_from(self) {
296 Ok(t) => Ok(Some(t)),
297 Err(Error::UnexpectedTag { .. }) => Ok(None),
298 Err(e) => Err(e),
299 }
300 }
301
302 pub fn as_tagged_explicit<T, E, const CLASS: u8, const TAG: u32>(
304 &self,
305 ) -> Result<TaggedValue<T, E, Explicit, CLASS, TAG>, E>
306 where
307 T: FromBer<'a, E>,
308 E: From<Error>,
309 {
310 TryFrom::try_from(self)
311 }
312
313 pub fn as_tagged_implicit<T, E, const CLASS: u8, const TAG: u32>(
315 &self,
316 ) -> Result<TaggedValue<T, E, Implicit, CLASS, TAG>, E>
317 where
318 T: TryFrom<Any<'a>, Error = E>,
319 T: Tagged,
320 E: From<Error>,
321 {
322 TryFrom::try_from(self)
323 }
324
325 pub fn as_any_str(&self) -> Result<String> {
330 match self.tag() {
331 Tag::GeneralString
332 | Tag::GraphicString
333 | Tag::Ia5String
334 | Tag::NumericString
335 | Tag::PrintableString
336 | Tag::T61String
337 | Tag::Utf8String
338 | Tag::VideotexString
339 | Tag::VisibleString => {
340 let res = core::str::from_utf8(self.data)?;
341 Ok(res.to_string())
342 }
343 Tag::UniversalString => {
344 let us = UniversalString::try_from(self)?;
345 Ok(us.string())
346 }
347 _ => todo!(),
348 }
349 }
350
351 pub fn as_any_string(&self) -> Result<&str> {
355 match self.tag() {
356 Tag::GeneralString
357 | Tag::GraphicString
358 | Tag::Ia5String
359 | Tag::NumericString
360 | Tag::PrintableString
361 | Tag::T61String
362 | Tag::Utf8String
364 | Tag::VideotexString
365 | Tag::VisibleString => {
366 let res = core::str::from_utf8(self.data)?;
367 Ok(res)
368 }
369 _ => todo!(),
370 }
371 }
372}
373
374pub(crate) fn parse_ber_any(input: &[u8]) -> ParseResult<Any> {
375 let (i, header) = Header::from_ber(input)?;
376 let (i, data) = BerParser::get_object_content(i, &header, MAX_RECURSION)?;
377 Ok((i, Any { header, data }))
378}
379
380pub(crate) fn parse_der_any(input: &[u8]) -> ParseResult<Any> {
381 let (i, header) = Header::from_der(input)?;
382 header.length.assert_definite()?;
384 let (i, data) = DerParser::get_object_content(i, &header, MAX_RECURSION)?;
385 Ok((i, Any { header, data }))
386}
387
388impl<'a> FromBer<'a> for Any<'a> {
389 #[inline]
390 fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self> {
391 trace("Any", parse_ber_any, bytes)
392 }
393}
394
395impl<'a> FromDer<'a> for Any<'a> {
396 #[inline]
397 fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self> {
398 trace("Any", parse_der_any, bytes)
399 }
400}
401
402impl CheckDerConstraints for Any<'_> {
403 fn check_constraints(any: &Any) -> Result<()> {
404 any.header.length().assert_definite()?;
405 Ok(())
407 }
408}
409
410impl DerAutoDerive for Any<'_> {}
411
412impl DynTagged for Any<'_> {
413 fn tag(&self) -> Tag {
414 self.tag()
415 }
416}
417
418#[cfg(feature = "std")]
430impl ToDer for Any<'_> {
431 fn to_der_len(&self) -> Result<usize> {
432 let hdr_len = self.header.to_der_len()?;
433 Ok(hdr_len + self.data.len())
434 }
435
436 fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
437 let header = Header::new(
439 self.header.class,
440 self.header.constructed,
441 self.header.tag,
442 Length::Definite(self.data.len()),
443 );
444 let sz = header.write_der_header(writer)?;
445 Ok(sz)
446 }
447
448 fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
449 writer.write(self.data).map_err(Into::into)
450 }
451
452 fn write_der_raw(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
454 let sz = self.header.write_der_header(writer)?;
455 let sz = sz + writer.write(self.data)?;
456 Ok(sz)
457 }
458}
459
460#[cfg(test)]
461mod tests {
462 use crate::*;
463 use hex_literal::hex;
464
465 #[test]
466 fn methods_any() {
467 let header = Header::new_simple(Tag::Integer);
468 let any = Any::new(header, &[])
469 .with_class(Class::ContextSpecific)
470 .with_tag(Tag(0));
471 assert_eq!(any.as_bytes(), &[]);
472
473 let input = &hex! {"80 03 02 01 01"};
474 let (_, any) = Any::from_ber(input).expect("parsing failed");
475
476 let (_, r) = any.parse_ber::<Integer>().expect("parse_ber failed");
477 assert_eq!(r.as_u32(), Ok(1));
478 let (_, r) = any.parse_der::<Integer>().expect("parse_der failed");
479 assert_eq!(r.as_u32(), Ok(1));
480
481 let header = &any.header;
482 let (_, content) = Any::parse_ber_content(&input[2..], header).unwrap();
483 assert_eq!(content.len(), 3);
484 let (_, content) = Any::parse_der_content(&input[2..], header).unwrap();
485 assert_eq!(content.len(), 3);
486
487 let (_, any) = Any::from_der(&input[2..]).unwrap();
488 Any::check_constraints(&any).unwrap();
489 assert_eq!(<Any as DynTagged>::tag(&any), any.tag());
490 let int = any.integer().unwrap();
491 assert_eq!(int.as_u16(), Ok(1));
492 }
493}