• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::ber::bitstring_to_u64;
2 use crate::ber::integer::*;
3 use crate::error::BerError;
4 use crate::oid::Oid;
5 use alloc::borrow::ToOwned;
6 use alloc::boxed::Box;
7 use alloc::vec::Vec;
8 #[cfg(feature = "bitvec")]
9 use bitvec::{order::Msb0, slice::BitSlice};
10 use core::convert::AsRef;
11 use core::convert::From;
12 use core::convert::TryFrom;
13 use core::fmt;
14 use core::ops::Index;
15 use rusticata_macros::newtype_enum;
16 
17 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
18 pub struct BerClassFromIntError(pub(crate) ());
19 
20 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
21 pub struct BerSizeError(pub(crate) ());
22 
23 /// BER Object class of tag
24 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
25 #[repr(u8)]
26 pub enum BerClass {
27     Universal = 0b00,
28     Application = 0b01,
29     ContextSpecific = 0b10,
30     Private = 0b11,
31 }
32 
33 /// Ber Object Length
34 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
35 pub enum BerSize {
36     /// Definite form (X.690 8.1.3.3)
37     Definite(usize),
38     /// Indefinite form (X.690 8.1.3.6)
39     Indefinite,
40 }
41 
42 /// BER/DER Tag as defined in X.680 section 8.4
43 ///
44 /// X.690 doesn't specify the maximum tag size so we're assuming that people
45 /// aren't going to need anything more than a u32.
46 #[derive(Clone, Copy, PartialEq, Eq)]
47 pub struct BerTag(pub u32);
48 
49 newtype_enum! {
50 impl debug BerTag {
51     EndOfContent = 0x0,
52     Boolean = 0x1,
53     Integer = 0x2,
54     BitString = 0x3,
55     OctetString = 0x4,
56     Null = 0x05,
57     Oid = 0x06,
58     ObjDescriptor = 0x07,
59     External = 0x08,
60     RealType = 0x09,
61     Enumerated = 0xa,
62     EmbeddedPdv = 0xb,
63     Utf8String = 0xc,
64     RelativeOid = 0xd,
65 
66     Sequence = 0x10,
67     Set = 0x11,
68     NumericString = 0x12,
69     PrintableString = 0x13,
70     T61String = 0x14,
71     VideotexString = 0x15,
72 
73     Ia5String = 0x16,
74     UtcTime = 0x17,
75     GeneralizedTime = 0x18,
76 
77     GraphicString = 25, // 0x19
78     VisibleString = 26, // 0x1a
79     GeneralString = 27, // 0x1b
80 
81     UniversalString = 0x1c,
82     BmpString = 0x1e,
83 
84     Invalid = 0xff,
85 }
86 }
87 
88 /// Representation of a BER-encoded (X.690) object
89 ///
90 /// A BER object is composed of a header describing the object class, type and length,
91 /// and the content.
92 ///
93 /// Note that the content may sometimes not match the header tag (for ex when parsing IMPLICIT
94 /// tagged values).
95 #[derive(Debug, Clone, PartialEq)]
96 pub struct BerObject<'a> {
97     pub header: BerObjectHeader<'a>,
98     pub content: BerObjectContent<'a>,
99 }
100 
101 /// BER object header (identifier and length)
102 #[derive(Clone, Debug)]
103 pub struct BerObjectHeader<'a> {
104     /// Object class: universal, application, context-specific, or private
105     pub class: BerClass,
106     /// Constructed attribute: 1 if constructed, else 0
107     pub structured: u8,
108     /// Tag number
109     pub tag: BerTag,
110     /// Object length: definite or indefinite
111     pub len: BerSize,
112 
113     /// Optionally, the raw encoding of the tag
114     ///
115     /// This is useful in some cases, where different representations of the same
116     /// BER tags have different meanings (BER only)
117     pub raw_tag: Option<&'a [u8]>,
118 }
119 
120 /// BER object content
121 #[derive(Debug, Clone, PartialEq)]
122 #[allow(clippy::upper_case_acronyms)]
123 pub enum BerObjectContent<'a> {
124     /// EOC (no content)
125     EndOfContent,
126     /// BOOLEAN: decoded value
127     Boolean(bool),
128     /// INTEGER: raw bytes
129     ///
130     /// Note: the reason to store the raw bytes is that integers have non-finite length in the
131     /// spec, and also that the raw encoding is also important for some applications.
132     ///
133     /// To extract the number, see the `as_u64`, `as_u32`, `as_bigint` and `as_biguint` methods.
134     Integer(&'a [u8]),
135     /// BIT STRING: number of unused bits, and object
136     BitString(u8, BitStringObject<'a>),
137     /// OCTET STRING: slice
138     OctetString(&'a [u8]),
139     /// NULL (no content)
140     Null,
141     /// ENUMERATED: decoded enum number
142     Enum(u64),
143     /// OID
144     OID(Oid<'a>),
145     /// RELATIVE OID
146     RelativeOID(Oid<'a>),
147     /// NumericString: decoded string
148     NumericString(&'a str),
149     /// VisibleString: decoded string
150     VisibleString(&'a str),
151     /// PrintableString: decoded string
152     PrintableString(&'a str),
153     /// IA5String: decoded string
154     IA5String(&'a str),
155     /// UTF8String: decoded string
156     UTF8String(&'a str),
157     /// T61String: raw object bytes
158     T61String(&'a [u8]),
159     /// VideotexString: raw object bytes
160     VideotexString(&'a [u8]),
161 
162     /// BmpString: raw object bytes
163     BmpString(&'a [u8]),
164     /// UniversalString: raw object bytes
165     UniversalString(&'a [u8]),
166 
167     /// SEQUENCE: list of objects
168     Sequence(Vec<BerObject<'a>>),
169     /// SET: list of objects
170     Set(Vec<BerObject<'a>>),
171 
172     /// UTCTime: decoded string
173     UTCTime(&'a str),
174     /// GeneralizedTime: decoded string
175     GeneralizedTime(&'a str),
176 
177     /// Object descriptor: raw object bytes
178     ObjectDescriptor(&'a [u8]),
179     /// GraphicString: raw object bytes
180     GraphicString(&'a [u8]),
181     /// GeneralString: raw object bytes
182     GeneralString(&'a [u8]),
183 
184     /// Optional object
185     Optional(Option<Box<BerObject<'a>>>),
186     /// Tagged object (EXPLICIT): class, tag  and content of inner object
187     Tagged(BerClass, BerTag, Box<BerObject<'a>>),
188     /// Private
189     Private(BerObjectHeader<'a>, &'a [u8]),
190 
191     /// Unknown object: object tag (copied from header), and raw content
192     Unknown(BerClass, BerTag, &'a [u8]),
193 }
194 
195 impl fmt::Display for BerClass {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result196     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197         let s = match self {
198             BerClass::Universal => "UNIVERSAL",
199             BerClass::Application => "APPLICATION",
200             BerClass::ContextSpecific => "CONTEXT-SPECIFIC",
201             BerClass::Private => "PRIVATE",
202         };
203         write!(f, "{}", s)
204     }
205 }
206 
207 impl From<u32> for BerTag {
from(v: u32) -> Self208     fn from(v: u32) -> Self {
209         BerTag(v)
210     }
211 }
212 
213 impl BerSize {
214     /// Return true if length is definite and equal to 0
is_null(&self) -> bool215     pub fn is_null(&self) -> bool {
216         *self == BerSize::Definite(0)
217     }
218 
219     /// Get length of primitive object
220     #[inline]
primitive(&self) -> Result<usize, BerError>221     pub fn primitive(&self) -> Result<usize, BerError> {
222         match self {
223             BerSize::Definite(sz) => Ok(*sz),
224             BerSize::Indefinite => Err(BerError::IndefiniteLengthUnexpected),
225         }
226     }
227 }
228 
229 impl From<usize> for BerSize {
from(v: usize) -> Self230     fn from(v: usize) -> Self {
231         BerSize::Definite(v)
232     }
233 }
234 
235 impl TryFrom<u64> for BerSize {
236     type Error = BerSizeError;
237 
try_from(value: u64) -> Result<Self, Self::Error>238     fn try_from(value: u64) -> Result<Self, Self::Error> {
239         let v = usize::try_from(value).or(Err(BerSizeError(())))?;
240         Ok(BerSize::Definite(v))
241     }
242 }
243 
244 impl TryFrom<BerSize> for usize {
245     type Error = BerSizeError;
246 
247     #[inline]
try_from(value: BerSize) -> Result<Self, Self::Error>248     fn try_from(value: BerSize) -> Result<Self, Self::Error> {
249         match value {
250             BerSize::Definite(sz) => Ok(sz),
251             BerSize::Indefinite => Err(BerSizeError(())),
252         }
253     }
254 }
255 
256 impl TryFrom<u8> for BerClass {
257     type Error = BerClassFromIntError;
258 
259     #[inline]
try_from(value: u8) -> Result<Self, Self::Error>260     fn try_from(value: u8) -> Result<Self, Self::Error> {
261         match value {
262             0b00 => Ok(BerClass::Universal),
263             0b01 => Ok(BerClass::Application),
264             0b10 => Ok(BerClass::ContextSpecific),
265             0b11 => Ok(BerClass::Private),
266             _ => Err(BerClassFromIntError(())),
267         }
268     }
269 }
270 
271 impl<'a> BerObjectHeader<'a> {
272     /// Build a new BER header
new<Len: Into<BerSize>>(class: BerClass, structured: u8, tag: BerTag, len: Len) -> Self273     pub fn new<Len: Into<BerSize>>(class: BerClass, structured: u8, tag: BerTag, len: Len) -> Self {
274         BerObjectHeader {
275             tag,
276             structured,
277             class,
278             len: len.into(),
279             raw_tag: None,
280         }
281     }
282 
283     /// Update header class
284     #[inline]
with_class(self, class: BerClass) -> Self285     pub fn with_class(self, class: BerClass) -> Self {
286         BerObjectHeader { class, ..self }
287     }
288 
289     /// Update header tag
290     #[inline]
with_tag(self, tag: BerTag) -> Self291     pub fn with_tag(self, tag: BerTag) -> Self {
292         BerObjectHeader { tag, ..self }
293     }
294 
295     /// Update header length
296     #[inline]
with_len(self, len: BerSize) -> Self297     pub fn with_len(self, len: BerSize) -> Self {
298         BerObjectHeader { len, ..self }
299     }
300 
301     /// Update header to add reference to raw tag
302     #[inline]
with_raw_tag(self, raw_tag: Option<&'a [u8]>) -> Self303     pub fn with_raw_tag(self, raw_tag: Option<&'a [u8]>) -> Self {
304         BerObjectHeader { raw_tag, ..self }
305     }
306 
307     /// Test if object class is Universal
308     #[inline]
is_universal(&self) -> bool309     pub fn is_universal(&self) -> bool {
310         self.class == BerClass::Universal
311     }
312     /// Test if object class is Application
313     #[inline]
is_application(&self) -> bool314     pub fn is_application(&self) -> bool {
315         self.class == BerClass::Application
316     }
317     /// Test if object class is Context-specific
318     #[inline]
is_contextspecific(&self) -> bool319     pub fn is_contextspecific(&self) -> bool {
320         self.class == BerClass::ContextSpecific
321     }
322     /// Test if object class is Private
323     #[inline]
is_private(&self) -> bool324     pub fn is_private(&self) -> bool {
325         self.class == BerClass::Private
326     }
327 
328     /// Test if object is primitive
329     #[inline]
is_primitive(&self) -> bool330     pub fn is_primitive(&self) -> bool {
331         self.structured == 0
332     }
333     /// Test if object is constructed
334     #[inline]
is_constructed(&self) -> bool335     pub fn is_constructed(&self) -> bool {
336         self.structured == 1
337     }
338 }
339 
340 impl<'a> BerObject<'a> {
341     /// Build a BerObject from a header and content.
342     ///
343     /// Note: values are not checked, so the tag can be different from the real content, or flags
344     /// can be invalid.
from_header_and_content<'o>( header: BerObjectHeader<'o>, content: BerObjectContent<'o>, ) -> BerObject<'o>345     pub fn from_header_and_content<'o>(
346         header: BerObjectHeader<'o>,
347         content: BerObjectContent<'o>,
348     ) -> BerObject<'o> {
349         BerObject { header, content }
350     }
351 
352     /// Build a BerObject from its content, using default flags (no class, correct tag,
353     /// and structured flag set only for Set and Sequence)
from_obj(c: BerObjectContent) -> BerObject354     pub fn from_obj(c: BerObjectContent) -> BerObject {
355         let class = BerClass::Universal;
356         let tag = c.tag();
357         let structured = match tag {
358             BerTag::Sequence | BerTag::Set => 1,
359             _ => 0,
360         };
361         let header = BerObjectHeader::new(class, structured, tag, BerSize::Definite(0));
362         BerObject { header, content: c }
363     }
364 
365     /// Build a DER integer object from a slice containing an encoded integer
from_int_slice(i: &'a [u8]) -> BerObject<'a>366     pub fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
367         let header = BerObjectHeader::new(
368             BerClass::Universal,
369             0,
370             BerTag::Integer,
371             BerSize::Definite(0),
372         );
373         BerObject {
374             header,
375             content: BerObjectContent::Integer(i),
376         }
377     }
378 
379     /// Set a tag for the BER object
set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject380     pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject {
381         let header = BerObjectHeader {
382             raw_tag,
383             ..self.header
384         };
385         BerObject { header, ..self }
386     }
387 
388     /// Build a DER sequence object from a vector of DER objects
from_seq(l: Vec<BerObject>) -> BerObject389     pub fn from_seq(l: Vec<BerObject>) -> BerObject {
390         BerObject::from_obj(BerObjectContent::Sequence(l))
391     }
392 
393     /// Build a DER set object from a vector of DER objects
from_set(l: Vec<BerObject>) -> BerObject394     pub fn from_set(l: Vec<BerObject>) -> BerObject {
395         BerObject::from_obj(BerObjectContent::Set(l))
396     }
397 
398     /// Attempt to read a signed integer value from DER object.
399     ///
400     /// This can fail if the object is not an integer, or if it is too large.
401     ///
402     /// # Examples
403     ///
404     /// ```rust
405     /// # use der_parser::ber::BerObject;
406     /// let der_int  = BerObject::from_int_slice(b"\x80");
407     /// assert_eq!(
408     ///     der_int.as_i64(),
409     ///     Ok(-128)
410     /// );
411     /// ```
as_i64(&self) -> Result<i64, BerError>412     pub fn as_i64(&self) -> Result<i64, BerError> {
413         self.content.as_i64()
414     }
415 
416     /// Attempt to read a signed integer value from DER object.
417     ///
418     /// This can fail if the object is not an integer, or if it is too large.
419     ///
420     /// # Examples
421     ///
422     /// ```rust
423     /// # use der_parser::ber::BerObject;
424     /// let der_int  = BerObject::from_int_slice(b"\x80");
425     /// assert_eq!(
426     ///     der_int.as_i32(),
427     ///     Ok(-128)
428     /// );
429     /// ```
as_i32(&self) -> Result<i32, BerError>430     pub fn as_i32(&self) -> Result<i32, BerError> {
431         self.content.as_i32()
432     }
433 
434     /// Attempt to read integer value from DER object.
435     ///
436     /// This can fail if the object is not an unsigned integer, or if it is too large.
437     ///
438     /// # Examples
439     ///
440     /// ```rust
441     /// # use der_parser::ber::BerObject;
442     /// let der_int  = BerObject::from_int_slice(b"\x01\x00\x01");
443     /// assert_eq!(
444     ///     der_int.as_u64(),
445     ///     Ok(0x10001)
446     /// );
447     /// ```
as_u64(&self) -> Result<u64, BerError>448     pub fn as_u64(&self) -> Result<u64, BerError> {
449         self.content.as_u64()
450     }
451 
452     /// Attempt to read integer value from DER object.
453     ///
454     /// This can fail if the object is not an unsigned integer, or if it is too large.
455     ///
456     /// # Examples
457     ///
458     /// ```rust
459     /// # extern crate der_parser;
460     /// # use der_parser::ber::{BerObject,BerObjectContent};
461     /// let der_int  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
462     /// assert_eq!(
463     ///     der_int.as_u32(),
464     ///     Ok(0x10001)
465     /// );
466     /// ```
as_u32(&self) -> Result<u32, BerError>467     pub fn as_u32(&self) -> Result<u32, BerError> {
468         self.content.as_u32()
469     }
470 
471     /// Attempt to read integer value from DER object.
472     /// This can fail if the object is not a boolean.
as_bool(&self) -> Result<bool, BerError>473     pub fn as_bool(&self) -> Result<bool, BerError> {
474         self.content.as_bool()
475     }
476 
477     /// Attempt to read an OID value from DER object.
478     /// This can fail if the object is not an OID.
as_oid(&self) -> Result<&Oid<'a>, BerError>479     pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
480         self.content.as_oid()
481     }
482 
483     /// Attempt to read an OID value from DER object.
484     /// This can fail if the object is not an OID.
as_oid_val(&self) -> Result<Oid<'a>, BerError>485     pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
486         self.content.as_oid_val()
487     }
488 
489     /// Attempt to get a reference on the content from an optional object.
490     /// This can fail if the object is not optional.
as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError>491     pub fn as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError> {
492         self.content.as_optional()
493     }
494 
495     /// Attempt to get a reference on the content from a tagged object.
496     /// This can fail if the object is not tagged.
as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError>497     pub fn as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError> {
498         self.content.as_tagged()
499     }
500 
501     /// Attempt to read a reference to a BitString value from DER object.
502     /// This can fail if the object is not an BitString.
503     ///
504     /// Note that this function returns a reference to the BitString. To get an owned value,
505     /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring)
as_bitstring_ref(&self) -> Result<&BitStringObject, BerError>506     pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
507         self.content.as_bitstring_ref()
508     }
509 
510     /// Attempt to read a BitString value from DER object.
511     /// This can fail if the object is not an BitString.
as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError>512     pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> {
513         self.content.as_bitstring()
514     }
515 
516     /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
517     #[cfg(feature = "bitvec")]
as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError>518     pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
519         self.content.as_bitslice()
520     }
521 
522     /// Attempt to extract the list of objects from a DER sequence.
523     /// This can fail if the object is not a sequence.
as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError>524     pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
525         self.content.as_sequence()
526     }
527 
528     /// Attempt to extract the list of objects from a DER set.
529     /// This can fail if the object is not a set.
as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError>530     pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
531         self.content.as_set()
532     }
533 
534     /// Attempt to get the content from a DER object, as a slice.
535     /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a
536     /// sequence).
537     /// This function mostly concerns string types, integers, or unknown DER objects.
as_slice(&self) -> Result<&'a [u8], BerError>538     pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
539         self.content.as_slice()
540     }
541 
542     /// Attempt to get the content from a DER object, as a str.
543     /// This can fail if the object does not contain a string type.
544     ///
545     /// Only NumericString, VisibleString, UTCTime, GeneralizedTime,
546     /// PrintableString, UTF8String and IA5String are considered here. Other
547     /// string types can be read using `as_slice`.
as_str(&self) -> Result<&'a str, BerError>548     pub fn as_str(&self) -> Result<&'a str, BerError> {
549         self.content.as_str()
550     }
551 
552     /// Test if object class is Universal
is_universal(&self) -> bool553     pub fn is_universal(&self) -> bool {
554         self.header.class == BerClass::Universal
555     }
556     /// Test if object class is Application
is_application(&self) -> bool557     pub fn is_application(&self) -> bool {
558         self.header.class == BerClass::Application
559     }
560     /// Test if object class is Context-specific
is_contextspecific(&self) -> bool561     pub fn is_contextspecific(&self) -> bool {
562         self.header.class == BerClass::ContextSpecific
563     }
564     /// Test if object class is Private
is_private(&self) -> bool565     pub fn is_private(&self) -> bool {
566         self.header.class == BerClass::Private
567     }
568 
569     /// Test if object is primitive
is_primitive(&self) -> bool570     pub fn is_primitive(&self) -> bool {
571         self.header.structured == 0
572     }
573     /// Test if object is constructed
is_constructed(&self) -> bool574     pub fn is_constructed(&self) -> bool {
575         self.header.structured == 1
576     }
577 }
578 
579 /// Build a DER object from an OID.
580 impl<'a> From<Oid<'a>> for BerObject<'a> {
from(oid: Oid<'a>) -> BerObject<'a>581     fn from(oid: Oid<'a>) -> BerObject<'a> {
582         BerObject::from_obj(BerObjectContent::OID(oid))
583     }
584 }
585 
586 /// Build a DER object from a BerObjectContent.
587 impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
from(obj: BerObjectContent<'a>) -> BerObject<'a>588     fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
589         BerObject::from_obj(obj)
590     }
591 }
592 
593 /// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`)
594 impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
eq(&self, other: &BerObjectHeader) -> bool595     fn eq(&self, other: &BerObjectHeader) -> bool {
596         self.class == other.class
597             && self.tag == other.tag
598             && self.structured == other.structured
599             && {
600                 if self.len.is_null() && other.len.is_null() {
601                     self.len == other.len
602                 } else {
603                     true
604                 }
605             }
606             && {
607                 // it tag is present for both, compare it
608                 if self.raw_tag.xor(other.raw_tag).is_none() {
609                     self.raw_tag == other.raw_tag
610                 } else {
611                     true
612                 }
613             }
614     }
615 }
616 
617 impl<'a> BerObjectContent<'a> {
618     /// Attempt to read a signed integer value from this object.
619     ///
620     /// This can fail if the object is not an integer, or if it is too large.
621     ///
622     /// # Examples
623     ///
624     /// ```rust
625     /// # use der_parser::ber::BerObject;
626     /// let der_int  = BerObject::from_int_slice(b"\x80");
627     /// assert_eq!(
628     ///     der_int.as_i64(),
629     ///     Ok(-128)
630     /// );
631     /// ```
as_i64(&self) -> Result<i64, BerError>632     pub fn as_i64(&self) -> Result<i64, BerError> {
633         if let BerObjectContent::Integer(bytes) = self {
634             let result = if is_highest_bit_set(bytes) {
635                 <i64>::from_be_bytes(decode_array_int8(bytes)?)
636             } else {
637                 <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
638             };
639             Ok(result)
640         } else {
641             Err(BerError::InvalidTag)
642         }
643     }
644 
645     /// Attempt to read a signed integer value from this object.
646     ///
647     /// This can fail if the object is not an integer, or if it is too large.
648     ///
649     /// # Examples
650     ///
651     /// ```rust
652     /// # use der_parser::ber::BerObject;
653     /// let der_int  = BerObject::from_int_slice(b"\x80");
654     /// assert_eq!(
655     ///     der_int.as_i32(),
656     ///     Ok(-128)
657     /// );
658     /// ```
as_i32(&self) -> Result<i32, BerError>659     pub fn as_i32(&self) -> Result<i32, BerError> {
660         if let BerObjectContent::Integer(bytes) = self {
661             let result = if is_highest_bit_set(bytes) {
662                 <i32>::from_be_bytes(decode_array_int4(bytes)?)
663             } else {
664                 <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
665             };
666             Ok(result)
667         } else {
668             Err(BerError::InvalidTag)
669         }
670     }
671 
672     /// Attempt to read integer value from this object.
673     ///
674     /// This can fail if the object is not an unsigned integer, or if it is too large.
675     ///
676     /// # Examples
677     ///
678     /// ```rust
679     /// # use der_parser::ber::BerObject;
680     /// let der_int  = BerObject::from_int_slice(b"\x01\x00\x01");
681     /// assert_eq!(
682     ///     der_int.as_u64(),
683     ///     Ok(0x10001)
684     /// );
685     /// ```
as_u64(&self) -> Result<u64, BerError>686     pub fn as_u64(&self) -> Result<u64, BerError> {
687         match self {
688             BerObjectContent::Integer(i) => {
689                 let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
690                 Ok(result)
691             }
692             BerObjectContent::BitString(ignored_bits, data) => {
693                 bitstring_to_u64(*ignored_bits as usize, data)
694             }
695             BerObjectContent::Enum(i) => Ok(*i as u64),
696             _ => Err(BerError::BerTypeError),
697         }
698     }
699 
700     /// Attempt to read integer value from this object.
701     ///
702     /// This can fail if the object is not an unsigned integer, or if it is too large.
703     ///
704     /// # Examples
705     ///
706     /// ```rust
707     /// # extern crate der_parser;
708     /// # use der_parser::ber::{BerObject,BerObjectContent};
709     /// let der_int  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
710     /// assert_eq!(
711     ///     der_int.as_u32(),
712     ///     Ok(0x10001)
713     /// );
714     /// ```
as_u32(&self) -> Result<u32, BerError>715     pub fn as_u32(&self) -> Result<u32, BerError> {
716         match self {
717             BerObjectContent::Integer(i) => {
718                 let result = <u32>::from_be_bytes(decode_array_uint4(i)?);
719                 Ok(result)
720             }
721             BerObjectContent::BitString(ignored_bits, data) => {
722                 bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
723                     if x > u64::from(core::u32::MAX) {
724                         Err(BerError::IntegerTooLarge)
725                     } else {
726                         Ok(x as u32)
727                     }
728                 })
729             }
730             BerObjectContent::Enum(i) => {
731                 if *i > u64::from(core::u32::MAX) {
732                     Err(BerError::IntegerTooLarge)
733                 } else {
734                     Ok(*i as u32)
735                 }
736             }
737             _ => Err(BerError::BerTypeError),
738         }
739     }
740 
as_bool(&self) -> Result<bool, BerError>741     pub fn as_bool(&self) -> Result<bool, BerError> {
742         match *self {
743             BerObjectContent::Boolean(b) => Ok(b),
744             _ => Err(BerError::BerTypeError),
745         }
746     }
747 
as_oid(&self) -> Result<&Oid<'a>, BerError>748     pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
749         match *self {
750             BerObjectContent::OID(ref o) => Ok(o),
751             BerObjectContent::RelativeOID(ref o) => Ok(o),
752             _ => Err(BerError::BerTypeError),
753         }
754     }
755 
as_oid_val(&self) -> Result<Oid<'a>, BerError>756     pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
757         self.as_oid().map(|o| o.clone())
758     }
759 
as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError>760     pub fn as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError> {
761         match *self {
762             BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
763             BerObjectContent::Optional(None) => Ok(None),
764             _ => Err(BerError::BerTypeError),
765         }
766     }
767 
as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError>768     pub fn as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError> {
769         match *self {
770             BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())),
771             _ => Err(BerError::BerTypeError),
772         }
773     }
774 
as_bitstring_ref(&self) -> Result<&BitStringObject, BerError>775     pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
776         match *self {
777             BerObjectContent::BitString(_, ref b) => Ok(b),
778             _ => Err(BerError::BerTypeError),
779         }
780     }
781 
as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError>782     pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> {
783         match *self {
784             BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
785             _ => Err(BerError::BerTypeError),
786         }
787     }
788 
789     /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
790     #[cfg(feature = "bitvec")]
as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError>791     pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
792         self.as_slice()
793             .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).map_err(|_| BerError::BerValueError))
794     }
795 
as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError>796     pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
797         match *self {
798             BerObjectContent::Sequence(ref s) => Ok(s),
799             _ => Err(BerError::BerTypeError),
800         }
801     }
802 
as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError>803     pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
804         match *self {
805             BerObjectContent::Set(ref s) => Ok(s),
806             _ => Err(BerError::BerTypeError),
807         }
808     }
809 
810     #[rustfmt::skip]
as_slice(&self) -> Result<&'a [u8],BerError>811     pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
812         match *self {
813             BerObjectContent::NumericString(s) |
814             BerObjectContent::GeneralizedTime(s) |
815             BerObjectContent::UTCTime(s) |
816             BerObjectContent::VisibleString(s) |
817             BerObjectContent::PrintableString(s) |
818             BerObjectContent::UTF8String(s) |
819             BerObjectContent::IA5String(s) => Ok(s.as_ref()),
820             BerObjectContent::Integer(s) |
821             BerObjectContent::BitString(_,BitStringObject{data:s}) |
822             BerObjectContent::OctetString(s) |
823             BerObjectContent::T61String(s) |
824             BerObjectContent::VideotexString(s) |
825             BerObjectContent::BmpString(s) |
826             BerObjectContent::UniversalString(s) |
827             BerObjectContent::ObjectDescriptor(s) |
828             BerObjectContent::GraphicString(s) |
829             BerObjectContent::GeneralString(s) |
830             BerObjectContent::Unknown(_, _,s) |
831             BerObjectContent::Private(_,s) => Ok(s),
832             _ => Err(BerError::BerTypeError),
833         }
834     }
835 
836     #[rustfmt::skip]
as_str(&self) -> Result<&'a str,BerError>837     pub fn as_str(&self) -> Result<&'a str,BerError> {
838         match *self {
839             BerObjectContent::NumericString(s) |
840             BerObjectContent::GeneralizedTime(s) |
841             BerObjectContent::UTCTime(s) |
842             BerObjectContent::VisibleString(s) |
843             BerObjectContent::PrintableString(s) |
844             BerObjectContent::UTF8String(s) |
845             BerObjectContent::IA5String(s) => Ok(s),
846             _ => Err(BerError::BerTypeError),
847         }
848     }
849 
850     #[rustfmt::skip]
tag(&self) -> BerTag851     fn tag(&self) -> BerTag {
852         match self {
853             BerObjectContent::EndOfContent         => BerTag::EndOfContent,
854             BerObjectContent::Boolean(_)           => BerTag::Boolean,
855             BerObjectContent::Integer(_)           => BerTag::Integer,
856             BerObjectContent::BitString(_,_)       => BerTag::BitString,
857             BerObjectContent::OctetString(_)       => BerTag::OctetString,
858             BerObjectContent::Null                 => BerTag::Null,
859             BerObjectContent::Enum(_)              => BerTag::Enumerated,
860             BerObjectContent::OID(_)               => BerTag::Oid,
861             BerObjectContent::NumericString(_)     => BerTag::NumericString,
862             BerObjectContent::VisibleString(_)     => BerTag::VisibleString,
863             BerObjectContent::PrintableString(_)   => BerTag::PrintableString,
864             BerObjectContent::IA5String(_)         => BerTag::Ia5String,
865             BerObjectContent::UTF8String(_)        => BerTag::Utf8String,
866             BerObjectContent::RelativeOID(_)       => BerTag::RelativeOid,
867             BerObjectContent::T61String(_)         => BerTag::T61String,
868             BerObjectContent::VideotexString(_)    => BerTag::VideotexString,
869             BerObjectContent::BmpString(_)         => BerTag::BmpString,
870             BerObjectContent::UniversalString(_)   => BerTag::UniversalString,
871             BerObjectContent::Sequence(_)          => BerTag::Sequence,
872             BerObjectContent::Set(_)               => BerTag::Set,
873             BerObjectContent::UTCTime(_)           => BerTag::UtcTime,
874             BerObjectContent::GeneralizedTime(_)   => BerTag::GeneralizedTime,
875             BerObjectContent::ObjectDescriptor(_)  => BerTag::ObjDescriptor,
876             BerObjectContent::GraphicString(_)     => BerTag::GraphicString,
877             BerObjectContent::GeneralString(_)     => BerTag::GeneralString,
878             BerObjectContent::Tagged(_,x,_) |
879             BerObjectContent::Unknown(_, x,_)         => *x,
880             &BerObjectContent::Private(ref hdr, _) => hdr.tag,
881             BerObjectContent::Optional(Some(obj))  => obj.content.tag(),
882             BerObjectContent::Optional(None)       => BerTag(0x00), // XXX invalid !
883         }
884     }
885 }
886 
887 #[cfg(feature = "bigint")]
888 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
889 use num_bigint::{BigInt, BigUint};
890 
891 #[cfg(feature = "bigint")]
892 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
893 impl<'a> BerObject<'a> {
894     /// Attempt to read an integer value from this object.
895     ///
896     /// This can fail if the object is not an integer.
897     ///
898     /// # Examples
899     ///
900     /// ```rust
901     /// use der_parser::ber::*;
902     ///
903     /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
904     ///
905     /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
906     /// # #[cfg(feature = "bigint")]
907     /// assert_eq!(object.as_bigint(), Ok(65537.into()))
908     /// ```
as_bigint(&self) -> Result<BigInt, BerError>909     pub fn as_bigint(&self) -> Result<BigInt, BerError> {
910         match self.content {
911             BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
912             _ => Err(BerError::InvalidTag),
913         }
914     }
915 
916     /// Attempt to read a positive integer value from this object.
917     ///
918     /// This can fail if the object is not an integer, or is negative.
919     ///
920     /// # Examples
921     ///
922     /// ```rust
923     /// use der_parser::ber::*;
924     ///
925     /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
926     ///
927     /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
928     /// # #[cfg(feature = "bigint")]
929     /// assert_eq!(object.as_biguint(), Ok(65537_u32.into()))
930     /// ```
as_biguint(&self) -> Result<BigUint, BerError>931     pub fn as_biguint(&self) -> Result<BigUint, BerError> {
932         match self.content {
933             BerObjectContent::Integer(s) => {
934                 if is_highest_bit_set(s) {
935                     return Err(BerError::IntegerNegative);
936                 }
937                 Ok(BigUint::from_bytes_be(s))
938             }
939             _ => Err(BerError::InvalidTag),
940         }
941     }
942 }
943 
944 // This is a consuming iterator
945 impl<'a> IntoIterator for BerObject<'a> {
946     type Item = BerObject<'a>;
947     type IntoIter = BerObjectIntoIterator<'a>;
948 
into_iter(self) -> Self::IntoIter949     fn into_iter(self) -> Self::IntoIter {
950         // match self {
951         //     BerObjectContent::Sequence(ref v) => (),
952         //     _ => (),
953         // };
954         BerObjectIntoIterator { val: self, idx: 0 }
955     }
956 }
957 
958 #[derive(Debug)]
959 pub struct BerObjectIntoIterator<'a> {
960     val: BerObject<'a>,
961     idx: usize,
962 }
963 
964 impl<'a> Iterator for BerObjectIntoIterator<'a> {
965     type Item = BerObject<'a>;
next(&mut self) -> Option<BerObject<'a>>966     fn next(&mut self) -> Option<BerObject<'a>> {
967         // let result = if self.idx < self.vec.len() {
968         //     Some(self.vec[self.idx].clone())
969         // } else {
970         //     None
971         // };
972         let res = match self.val.content {
973             BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
974             BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
975             _ => {
976                 if self.idx == 0 {
977                     Some(self.val.clone())
978                 } else {
979                     None
980                 }
981             }
982         };
983         self.idx += 1;
984         res
985     }
986 }
987 
988 // impl<'a> Iterator for BerObjectContent<'a> {
989 //     type Item = BerObjectContent<'a>;
990 //
991 //     fn next(&mut self) -> Option<BerObjectContent<'a>> {
992 //         None
993 //     }
994 // }
995 
996 #[derive(Debug)]
997 pub struct BerObjectRefIterator<'a> {
998     obj: &'a BerObject<'a>,
999     idx: usize,
1000 }
1001 
1002 impl<'a> Iterator for BerObjectRefIterator<'a> {
1003     type Item = &'a BerObject<'a>;
next(&mut self) -> Option<&'a BerObject<'a>>1004     fn next(&mut self) -> Option<&'a BerObject<'a>> {
1005         let res = match (*self.obj).content {
1006             BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
1007             BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
1008             _ => None,
1009         };
1010         self.idx += 1;
1011         res
1012     }
1013 }
1014 
1015 impl<'a> BerObject<'a> {
ref_iter(&'a self) -> BerObjectRefIterator<'a>1016     pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
1017         BerObjectRefIterator { obj: self, idx: 0 }
1018     }
1019 }
1020 
1021 impl<'a> Index<usize> for BerObject<'a> {
1022     type Output = BerObject<'a>;
1023 
index(&self, idx: usize) -> &BerObject<'a>1024     fn index(&self, idx: usize) -> &BerObject<'a> {
1025         match (*self).content {
1026             BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
1027             BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
1028             _ => panic!("Try to index BerObjectContent which is not structured"),
1029         }
1030         // XXX the following
1031         // self.ref_iter().nth(idx).unwrap()
1032         // fails with:
1033         // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
1034         // self.ref_iter().nth(idx).unwrap()
1035     }
1036 }
1037 
1038 /// BitString wrapper
1039 #[derive(Clone, Debug, PartialEq)]
1040 pub struct BitStringObject<'a> {
1041     pub data: &'a [u8],
1042 }
1043 
1044 impl<'a> BitStringObject<'a> {
1045     /// Test if bit `bitnum` is set
is_set(&self, bitnum: usize) -> bool1046     pub fn is_set(&self, bitnum: usize) -> bool {
1047         let byte_pos = bitnum / 8;
1048         if byte_pos >= self.data.len() {
1049             return false;
1050         }
1051         let b = 7 - (bitnum % 8);
1052         (self.data[byte_pos] & (1 << b)) != 0
1053     }
1054 
1055     /// Constructs a shared `&BitSlice` reference over the object data.
1056     #[cfg(feature = "bitvec")]
as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>>1057     pub fn as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>> {
1058         BitSlice::<Msb0, _>::from_slice(self.data).ok()
1059     }
1060 }
1061 
1062 impl<'a> AsRef<[u8]> for BitStringObject<'a> {
as_ref(&self) -> &[u8]1063     fn as_ref(&self) -> &[u8] {
1064         self.data
1065     }
1066 }
1067 
1068 #[cfg(test)]
1069 mod tests {
1070     use crate::ber::*;
1071     use crate::oid::*;
1072 
1073     #[test]
test_der_as_u64()1074     fn test_der_as_u64() {
1075         let der_obj = BerObject::from_int_slice(b"\x01\x00\x02");
1076         assert_eq!(der_obj.as_u64(), Ok(0x10002));
1077     }
1078 
1079     #[test]
test_ber_as_u64_bitstring()1080     fn test_ber_as_u64_bitstring() {
1081         let (_, ber_obj) = parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xc0").unwrap();
1082         assert_eq!(ber_obj.as_u64(), Ok(0b011011100101110111));
1083 
1084         let (_, ber_obj_with_nonzero_padding) =
1085             parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xe0").unwrap();
1086         assert_eq!(
1087             ber_obj_with_nonzero_padding.as_u64(),
1088             Ok(0b011011100101110111)
1089         );
1090     }
1091 
1092     #[test]
test_der_seq_iter()1093     fn test_der_seq_iter() {
1094         let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![
1095             BerObject::from_int_slice(b"\x01\x00\x01"),
1096             BerObject::from_int_slice(b"\x01\x00\x00"),
1097         ]));
1098         let expected_values = vec![
1099             BerObject::from_int_slice(b"\x01\x00\x01"),
1100             BerObject::from_int_slice(b"\x01\x00\x00"),
1101         ];
1102 
1103         for (idx, v) in der_obj.ref_iter().enumerate() {
1104             // println!("v: {:?}", v);
1105             assert_eq!((*v), expected_values[idx]);
1106         }
1107     }
1108 
1109     #[test]
test_der_from_oid()1110     fn test_der_from_oid() {
1111         let obj: BerObject = Oid::from(&[1, 2]).unwrap().into();
1112         let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap()));
1113 
1114         assert_eq!(obj, expected);
1115     }
1116 
1117     #[test]
test_der_bitstringobject()1118     fn test_der_bitstringobject() {
1119         let obj = BitStringObject {
1120             data: &[0x0f, 0x00, 0x40],
1121         };
1122         assert!(!obj.is_set(0));
1123         assert!(obj.is_set(7));
1124         assert!(!obj.is_set(9));
1125         assert!(obj.is_set(17));
1126     }
1127 
1128     #[cfg(feature = "bitvec")]
1129     #[test]
test_der_bitslice()1130     fn test_der_bitslice() {
1131         use std::string::String;
1132         let obj = BitStringObject {
1133             data: &[0x0f, 0x00, 0x40],
1134         };
1135         let slice = obj.as_bitslice().expect("as_bitslice");
1136         assert_eq!(slice.get(0).as_deref(), Some(&false));
1137         assert_eq!(slice.get(7).as_deref(), Some(&true));
1138         assert_eq!(slice.get(9).as_deref(), Some(&false));
1139         assert_eq!(slice.get(17).as_deref(), Some(&true));
1140         let s = slice.iter().fold(String::with_capacity(24), |mut acc, b| {
1141             acc += if *b { "1" } else { "0" };
1142             acc
1143         });
1144         assert_eq!(&s, "000011110000000001000000");
1145     }
1146 
1147     #[test]
test_der_bistringobject_asref()1148     fn test_der_bistringobject_asref() {
1149         fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) {
1150             assert_eq!(s.as_ref(), b);
1151         }
1152         let b: &[u8] = &[0x0f, 0x00, 0x40];
1153         let obj = BitStringObject { data: b };
1154         assert_equal(obj, b);
1155     }
1156 
1157     #[cfg(feature = "bigint")]
1158     #[test]
test_der_to_bigint()1159     fn test_der_to_bigint() {
1160         let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
1161         let expected = ::num_bigint::BigInt::from(0x10001);
1162 
1163         assert_eq!(obj.as_bigint(), Ok(expected));
1164     }
1165 
1166     #[cfg(feature = "bigint")]
1167     #[test]
test_der_to_biguint()1168     fn test_der_to_biguint() {
1169         let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
1170         let expected = ::num_bigint::BigUint::from(0x10001_u32);
1171 
1172         assert_eq!(obj.as_biguint(), Ok(expected));
1173     }
1174 }
1175