der_parser/ber/
ber.rs

1use super::{Class, Header, Length, Tag};
2use crate::ber::ber_read_element_content_as;
3use crate::ber::bitstring_to_u64;
4use crate::ber::integer::*;
5use crate::ber::MAX_RECURSION;
6use crate::error::BerError;
7use crate::oid::Oid;
8use alloc::borrow::ToOwned;
9use alloc::boxed::Box;
10use alloc::vec::Vec;
11use asn1_rs::ASN1DateTime;
12use asn1_rs::Any;
13#[cfg(feature = "as_bitvec")]
14use bitvec::{order::Msb0, slice::BitSlice};
15use core::convert::TryFrom;
16use core::ops::Index;
17
18/// Representation of a BER-encoded (X.690) object
19///
20/// A BER object is composed of a header describing the object class, type and length,
21/// and the content.
22///
23/// Note that the content may sometimes not match the header tag (for ex when parsing IMPLICIT
24/// tagged values).
25#[derive(Debug, Clone, PartialEq)]
26pub struct BerObject<'a> {
27    pub header: Header<'a>,
28    pub content: BerObjectContent<'a>,
29}
30
31/// BER object content
32#[derive(Debug, Clone, PartialEq)]
33#[allow(clippy::upper_case_acronyms)]
34pub enum BerObjectContent<'a> {
35    /// EOC (no content)
36    EndOfContent,
37    /// BOOLEAN: decoded value
38    Boolean(bool),
39    /// INTEGER: raw bytes
40    ///
41    /// Note: the reason to store the raw bytes is that integers have non-finite length in the
42    /// spec, and also that the raw encoding is also important for some applications.
43    ///
44    /// To extract the number, see the `as_u64`, `as_u32`, `as_bigint` and `as_biguint` methods.
45    Integer(&'a [u8]),
46    /// BIT STRING: number of unused bits, and object
47    BitString(u8, BitStringObject<'a>),
48    /// OCTET STRING: slice
49    OctetString(&'a [u8]),
50    /// NULL (no content)
51    Null,
52    /// ENUMERATED: decoded enum number
53    Enum(u64),
54    /// OID
55    OID(Oid<'a>),
56    /// RELATIVE OID
57    RelativeOID(Oid<'a>),
58    /// NumericString: decoded string
59    NumericString(&'a str),
60    /// VisibleString: decoded string
61    VisibleString(&'a str),
62    /// PrintableString: decoded string
63    PrintableString(&'a str),
64    /// IA5String: decoded string
65    IA5String(&'a str),
66    /// UTF8String: decoded string
67    UTF8String(&'a str),
68    /// T61String: decoded string
69    T61String(&'a str),
70    /// VideotexString: decoded string
71    VideotexString(&'a str),
72
73    /// BmpString: raw object bytes
74    ///
75    /// Note: the string is stored as raw bytes because not all UTF-16 sequences can be stored as
76    /// `&str`. To access content, use `String::from_utf16` or `String::from_utf16_lossy`.
77    BmpString(&'a [u8]),
78    /// UniversalString: raw object bytes
79    UniversalString(&'a [u8]),
80
81    /// SEQUENCE: list of objects
82    Sequence(Vec<BerObject<'a>>),
83    /// SET: list of objects
84    Set(Vec<BerObject<'a>>),
85
86    /// UTCTime: decoded string
87    UTCTime(ASN1DateTime),
88    /// GeneralizedTime: decoded string
89    GeneralizedTime(ASN1DateTime),
90
91    /// Object descriptor: decoded string
92    ObjectDescriptor(&'a str),
93    /// GraphicString: decoded string
94    GraphicString(&'a str),
95    /// GeneralString: decoded string
96    GeneralString(&'a str),
97
98    /// Optional object
99    Optional(Option<Box<BerObject<'a>>>),
100    /// Tagged object (EXPLICIT): class, tag  and content of inner object
101    Tagged(Class, Tag, Box<BerObject<'a>>),
102
103    /// Private or Unknown (for ex. unknown tag) object
104    Unknown(Any<'a>),
105}
106
107impl<'a> BerObject<'a> {
108    /// Build a BerObject from a header and content.
109    ///
110    /// Note: values are not checked, so the tag can be different from the real content, or flags
111    /// can be invalid.
112    #[inline]
113    pub const fn from_header_and_content<'o>(
114        header: Header<'o>,
115        content: BerObjectContent<'o>,
116    ) -> BerObject<'o> {
117        BerObject { header, content }
118    }
119
120    /// Build a BerObject from its content, using default flags (no class, correct tag,
121    /// and constructed flag set only for Set and Sequence)
122    pub const fn from_obj(c: BerObjectContent) -> BerObject {
123        let class = Class::Universal;
124        let tag = c.tag();
125        let constructed = matches!(tag, Tag::Sequence | Tag::Set);
126        let header = Header::new(class, constructed, tag, Length::Definite(0));
127        BerObject { header, content: c }
128    }
129
130    /// Build a DER integer object from a slice containing an encoded integer
131    pub const fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
132        let header = Header::new(Class::Universal, false, Tag::Integer, Length::Definite(0));
133        BerObject {
134            header,
135            content: BerObjectContent::Integer(i),
136        }
137    }
138
139    /// Set a tag for the BER object
140    pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject<'a> {
141        let header = self.header.with_raw_tag(raw_tag.map(|x| x.into()));
142        BerObject { header, ..self }
143    }
144
145    /// Build a DER sequence object from a vector of DER objects
146    pub const fn from_seq(l: Vec<BerObject>) -> BerObject {
147        BerObject::from_obj(BerObjectContent::Sequence(l))
148    }
149
150    /// Build a DER set object from a vector of DER objects
151    pub const fn from_set(l: Vec<BerObject>) -> BerObject {
152        BerObject::from_obj(BerObjectContent::Set(l))
153    }
154
155    /// Attempt to read a signed integer value from DER object.
156    ///
157    /// This can fail if the object is not an integer, or if it is too large.
158    ///
159    /// # Examples
160    ///
161    /// ```rust
162    /// # use der_parser::ber::BerObject;
163    /// let der_int  = BerObject::from_int_slice(b"\x80");
164    /// assert_eq!(
165    ///     der_int.as_i64(),
166    ///     Ok(-128)
167    /// );
168    /// ```
169    pub fn as_i64(&self) -> Result<i64, BerError> {
170        self.content.as_i64()
171    }
172
173    /// Attempt to read a signed integer value from DER object.
174    ///
175    /// This can fail if the object is not an integer, or if it is too large.
176    ///
177    /// # Examples
178    ///
179    /// ```rust
180    /// # use der_parser::ber::BerObject;
181    /// let der_int  = BerObject::from_int_slice(b"\x80");
182    /// assert_eq!(
183    ///     der_int.as_i32(),
184    ///     Ok(-128)
185    /// );
186    /// ```
187    pub fn as_i32(&self) -> Result<i32, BerError> {
188        self.content.as_i32()
189    }
190
191    /// Attempt to read integer value from DER object.
192    ///
193    /// This can fail if the object is not an unsigned integer, or if it is too large.
194    ///
195    /// # Examples
196    ///
197    /// ```rust
198    /// # use der_parser::ber::BerObject;
199    /// let der_int  = BerObject::from_int_slice(b"\x01\x00\x01");
200    /// assert_eq!(
201    ///     der_int.as_u64(),
202    ///     Ok(0x10001)
203    /// );
204    /// ```
205    pub fn as_u64(&self) -> Result<u64, BerError> {
206        self.content.as_u64()
207    }
208
209    /// Attempt to read integer value from DER object.
210    ///
211    /// This can fail if the object is not an unsigned integer, or if it is too large.
212    ///
213    /// # Examples
214    ///
215    /// ```rust
216    /// # extern crate der_parser;
217    /// # use der_parser::ber::{BerObject,BerObjectContent};
218    /// let der_int  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
219    /// assert_eq!(
220    ///     der_int.as_u32(),
221    ///     Ok(0x10001)
222    /// );
223    /// ```
224    pub fn as_u32(&self) -> Result<u32, BerError> {
225        self.content.as_u32()
226    }
227
228    /// Attempt to read integer value from DER object.
229    /// This can fail if the object is not a boolean.
230    pub fn as_bool(&self) -> Result<bool, BerError> {
231        self.content.as_bool()
232    }
233
234    /// Attempt to read an OID value from DER object.
235    /// This can fail if the object is not an OID.
236    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
237        self.content.as_oid()
238    }
239
240    /// Attempt to read an OID value from DER object.
241    /// This can fail if the object is not an OID.
242    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
243        self.content.as_oid_val()
244    }
245
246    /// Attempt to get a reference on the content from an optional object.
247    /// This can fail if the object is not optional.
248    pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
249        self.content.as_optional()
250    }
251
252    /// Attempt to get a reference on the content from a tagged object.
253    /// This can fail if the object is not tagged.
254    pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
255        self.content.as_tagged()
256    }
257
258    /// Attempt to read a reference to a BitString value from DER object.
259    /// This can fail if the object is not an BitString.
260    ///
261    /// Note that this function returns a reference to the BitString. To get an owned value,
262    /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring)
263    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
264        self.content.as_bitstring_ref()
265    }
266
267    /// Attempt to read a BitString value from DER object.
268    /// This can fail if the object is not an BitString.
269    pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
270        self.content.as_bitstring()
271    }
272
273    /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
274    #[cfg(feature = "as_bitvec")]
275    pub fn as_bitslice(&self) -> Result<&BitSlice<u8, Msb0>, BerError> {
276        self.content.as_bitslice()
277    }
278
279    /// Attempt to extract the list of objects from a DER sequence.
280    /// This can fail if the object is not a sequence.
281    pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
282        self.content.as_sequence()
283    }
284
285    /// Attempt to extract the list of objects from a DER set.
286    /// This can fail if the object is not a set.
287    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
288        self.content.as_set()
289    }
290
291    /// Attempt to get the content from a DER object, as a slice.
292    /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a
293    /// sequence).
294    /// This function mostly concerns string types, integers, or unknown DER objects.
295    pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
296        self.content.as_slice()
297    }
298
299    /// Attempt to get the content from a DER object, as a str.
300    /// This can fail if the object does not contain a string type.
301    ///
302    /// Only some string types are considered here. Other
303    /// string types can be read using `as_slice`.
304    pub fn as_str(&self) -> Result<&'a str, BerError> {
305        self.content.as_str()
306    }
307
308    /// Get the BER object header's class.
309    #[inline]
310    pub const fn class(&self) -> Class {
311        self.header.class()
312    }
313
314    /// Get the BER object header's tag.
315    #[inline]
316    pub const fn tag(&self) -> Tag {
317        self.header.tag()
318    }
319
320    /// Get the BER object header's length.
321    #[inline]
322    pub const fn length(&self) -> Length {
323        self.header.length()
324    }
325
326    /// Test if object class is Universal
327    #[inline]
328    pub const fn is_universal(&self) -> bool {
329        self.header.is_universal()
330    }
331    /// Test if object class is Application
332    #[inline]
333    pub const fn is_application(&self) -> bool {
334        self.header.is_application()
335    }
336    /// Test if object class is Context-specific
337    #[inline]
338    pub const fn is_contextspecific(&self) -> bool {
339        self.header.is_contextspecific()
340    }
341    /// Test if object class is Private
342    #[inline]
343    pub fn is_private(&self) -> bool {
344        self.header.is_private()
345    }
346
347    /// Test if object is primitive
348    #[inline]
349    pub const fn is_primitive(&self) -> bool {
350        self.header.is_primitive()
351    }
352    /// Test if object is constructed
353    #[inline]
354    pub const fn is_constructed(&self) -> bool {
355        self.header.is_constructed()
356    }
357
358    /// Return error if `class` is not the expected class
359    #[inline]
360    pub const fn assert_class(&self, class: Class) -> Result<(), BerError> {
361        self.header.assert_class(class)
362    }
363
364    /// Return error if `tag` is not the expected tag
365    #[inline]
366    pub const fn assert_tag(&self, tag: Tag) -> Result<(), BerError> {
367        self.header.assert_tag(tag)
368    }
369
370    /// Return error if object is not constructed
371    #[inline]
372    pub const fn assert_constructed(&self) -> Result<(), BerError> {
373        self.header.assert_constructed()
374    }
375
376    /// Return error if object is not primitive
377    #[inline]
378    pub const fn assert_primitive(&self) -> Result<(), BerError> {
379        self.header.assert_primitive()
380    }
381}
382
383/// Build a DER object from an OID.
384impl<'a> From<Oid<'a>> for BerObject<'a> {
385    fn from(oid: Oid<'a>) -> BerObject<'a> {
386        BerObject::from_obj(BerObjectContent::OID(oid))
387    }
388}
389
390/// Build a DER object from a BerObjectContent.
391impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
392    fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
393        BerObject::from_obj(obj)
394    }
395}
396
397impl<'a> BerObjectContent<'a> {
398    /// Attempt to read a signed integer value from this 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    /// ```
412    pub fn as_i64(&self) -> Result<i64, BerError> {
413        if let BerObjectContent::Integer(bytes) = self {
414            let result = if is_highest_bit_set(bytes) {
415                <i64>::from_be_bytes(decode_array_int8(bytes)?)
416            } else {
417                <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
418            };
419            Ok(result)
420        } else {
421            Err(BerError::BerValueError)
422        }
423    }
424
425    /// Attempt to read a signed integer value from this object.
426    ///
427    /// This can fail if the object is not an integer, or if it is too large.
428    ///
429    /// # Examples
430    ///
431    /// ```rust
432    /// # use der_parser::ber::BerObject;
433    /// let der_int  = BerObject::from_int_slice(b"\x80");
434    /// assert_eq!(
435    ///     der_int.as_i32(),
436    ///     Ok(-128)
437    /// );
438    /// ```
439    pub fn as_i32(&self) -> Result<i32, BerError> {
440        if let BerObjectContent::Integer(bytes) = self {
441            let result = if is_highest_bit_set(bytes) {
442                <i32>::from_be_bytes(decode_array_int4(bytes)?)
443            } else {
444                <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
445            };
446            Ok(result)
447        } else {
448            Err(BerError::BerValueError)
449        }
450    }
451
452    /// Attempt to read integer value from this 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    /// # use der_parser::ber::BerObject;
460    /// let der_int  = BerObject::from_int_slice(b"\x01\x00\x01");
461    /// assert_eq!(
462    ///     der_int.as_u64(),
463    ///     Ok(0x10001)
464    /// );
465    /// ```
466    pub fn as_u64(&self) -> Result<u64, BerError> {
467        match self {
468            BerObjectContent::Integer(i) => {
469                let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
470                Ok(result)
471            }
472            BerObjectContent::BitString(ignored_bits, data) => {
473                bitstring_to_u64(*ignored_bits as usize, data)
474            }
475            BerObjectContent::Enum(i) => Ok(*i),
476            _ => Err(BerError::BerTypeError),
477        }
478    }
479
480    /// Attempt to read integer value from this object.
481    ///
482    /// This can fail if the object is not an unsigned integer, or if it is too large.
483    ///
484    /// # Examples
485    ///
486    /// ```rust
487    /// # extern crate der_parser;
488    /// # use der_parser::ber::{BerObject,BerObjectContent};
489    /// let der_int  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
490    /// assert_eq!(
491    ///     der_int.as_u32(),
492    ///     Ok(0x10001)
493    /// );
494    /// ```
495    pub fn as_u32(&self) -> Result<u32, BerError> {
496        match self {
497            BerObjectContent::Integer(i) => {
498                let result = <u32>::from_be_bytes(decode_array_uint4(i)?);
499                Ok(result)
500            }
501            BerObjectContent::BitString(ignored_bits, data) => {
502                bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
503                    if x > u64::from(u32::MAX) {
504                        Err(BerError::IntegerTooLarge)
505                    } else {
506                        Ok(x as u32)
507                    }
508                })
509            }
510            BerObjectContent::Enum(i) => {
511                if *i > u64::from(u32::MAX) {
512                    Err(BerError::IntegerTooLarge)
513                } else {
514                    Ok(*i as u32)
515                }
516            }
517            _ => Err(BerError::BerTypeError),
518        }
519    }
520
521    pub fn as_bool(&self) -> Result<bool, BerError> {
522        match *self {
523            BerObjectContent::Boolean(b) => Ok(b),
524            _ => Err(BerError::BerTypeError),
525        }
526    }
527
528    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
529        match *self {
530            BerObjectContent::OID(ref o) => Ok(o),
531            BerObjectContent::RelativeOID(ref o) => Ok(o),
532            _ => Err(BerError::BerTypeError),
533        }
534    }
535
536    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
537        self.as_oid().cloned()
538    }
539
540    pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
541        match *self {
542            BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
543            BerObjectContent::Optional(None) => Ok(None),
544            _ => Err(BerError::BerTypeError),
545        }
546    }
547
548    pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
549        match *self {
550            BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())),
551            _ => Err(BerError::BerTypeError),
552        }
553    }
554
555    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
556        match *self {
557            BerObjectContent::BitString(_, ref b) => Ok(b),
558            _ => Err(BerError::BerTypeError),
559        }
560    }
561
562    pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
563        match *self {
564            BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
565            _ => Err(BerError::BerTypeError),
566        }
567    }
568
569    /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
570    #[cfg(feature = "as_bitvec")]
571    pub fn as_bitslice(&self) -> Result<&BitSlice<u8, Msb0>, BerError> {
572        self.as_slice().and_then(|s| {
573            BitSlice::<_, Msb0>::try_from_slice(s).map_err(|_| BerError::BerValueError)
574        })
575    }
576
577    pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
578        match *self {
579            BerObjectContent::Sequence(ref s) => Ok(s),
580            _ => Err(BerError::BerTypeError),
581        }
582    }
583
584    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
585        match *self {
586            BerObjectContent::Set(ref s) => Ok(s),
587            _ => Err(BerError::BerTypeError),
588        }
589    }
590
591    #[rustfmt::skip]
592    pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
593        match *self {
594            BerObjectContent::NumericString(s) |
595            BerObjectContent::VisibleString(s) |
596            BerObjectContent::PrintableString(s) |
597            BerObjectContent::GeneralString(s) |
598            BerObjectContent::ObjectDescriptor(s) |
599            BerObjectContent::GraphicString(s) |
600            BerObjectContent::T61String(s) |
601            BerObjectContent::VideotexString(s) |
602            BerObjectContent::UTF8String(s) |
603            BerObjectContent::IA5String(s) => Ok(s.as_ref()),
604            BerObjectContent::Integer(s) |
605            BerObjectContent::BitString(_,BitStringObject{data:s}) |
606            BerObjectContent::OctetString(s) |
607            BerObjectContent::BmpString(s) |
608            BerObjectContent::UniversalString(s) => Ok(s),
609            BerObjectContent::Unknown(ref any) => Ok(any.data),
610            _ => Err(BerError::BerTypeError),
611        }
612    }
613
614    #[rustfmt::skip]
615    pub fn as_str(&self) -> Result<&'a str,BerError> {
616        match *self {
617            BerObjectContent::NumericString(s) |
618            BerObjectContent::VisibleString(s) |
619            BerObjectContent::PrintableString(s) |
620            BerObjectContent::GeneralString(s) |
621            BerObjectContent::ObjectDescriptor(s) |
622            BerObjectContent::GraphicString(s) |
623            BerObjectContent::T61String(s) |
624            BerObjectContent::VideotexString(s) |
625            BerObjectContent::UTF8String(s) |
626            BerObjectContent::IA5String(s) => Ok(s),
627            _ => Err(BerError::BerTypeError),
628        }
629    }
630
631    #[rustfmt::skip]
632    const fn tag(&self) -> Tag {
633        match self {
634            BerObjectContent::EndOfContent         => Tag::EndOfContent,
635            BerObjectContent::Boolean(_)           => Tag::Boolean,
636            BerObjectContent::Integer(_)           => Tag::Integer,
637            BerObjectContent::BitString(_,_)       => Tag::BitString,
638            BerObjectContent::OctetString(_)       => Tag::OctetString,
639            BerObjectContent::Null                 => Tag::Null,
640            BerObjectContent::Enum(_)              => Tag::Enumerated,
641            BerObjectContent::OID(_)               => Tag::Oid,
642            BerObjectContent::NumericString(_)     => Tag::NumericString,
643            BerObjectContent::VisibleString(_)     => Tag::VisibleString,
644            BerObjectContent::PrintableString(_)   => Tag::PrintableString,
645            BerObjectContent::IA5String(_)         => Tag::Ia5String,
646            BerObjectContent::UTF8String(_)        => Tag::Utf8String,
647            BerObjectContent::RelativeOID(_)       => Tag::RelativeOid,
648            BerObjectContent::T61String(_)         => Tag::T61String,
649            BerObjectContent::VideotexString(_)    => Tag::VideotexString,
650            BerObjectContent::BmpString(_)         => Tag::BmpString,
651            BerObjectContent::UniversalString(_)   => Tag::UniversalString,
652            BerObjectContent::Sequence(_)          => Tag::Sequence,
653            BerObjectContent::Set(_)               => Tag::Set,
654            BerObjectContent::UTCTime(_)           => Tag::UtcTime,
655            BerObjectContent::GeneralizedTime(_)   => Tag::GeneralizedTime,
656            BerObjectContent::ObjectDescriptor(_)  => Tag::ObjectDescriptor,
657            BerObjectContent::GraphicString(_)     => Tag::GraphicString,
658            BerObjectContent::GeneralString(_)     => Tag::GeneralString,
659            BerObjectContent::Tagged(_,x,_) => *x,
660            BerObjectContent::Unknown(any) => any.tag(),
661            BerObjectContent::Optional(Some(obj))  => obj.content.tag(),
662            BerObjectContent::Optional(None)       => Tag(0x00), // XXX invalid !
663        }
664    }
665}
666
667#[cfg(feature = "bigint")]
668#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
669use num_bigint::{BigInt, BigUint};
670
671#[cfg(feature = "bigint")]
672#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
673impl BerObject<'_> {
674    /// Attempt to read an integer value from this object.
675    ///
676    /// This can fail if the object is not an integer.
677    ///
678    /// # Examples
679    ///
680    /// ```rust
681    /// use der_parser::ber::*;
682    ///
683    /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
684    ///
685    /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
686    /// # #[cfg(feature = "bigint")]
687    /// assert_eq!(object.as_bigint(), Ok(65537.into()))
688    /// ```
689    pub fn as_bigint(&self) -> Result<BigInt, BerError> {
690        match self.content {
691            BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
692            _ => Err(BerError::BerValueError),
693        }
694    }
695
696    /// Attempt to read a positive integer value from this object.
697    ///
698    /// This can fail if the object is not an integer, or is negative.
699    ///
700    /// # Examples
701    ///
702    /// ```rust
703    /// use der_parser::ber::*;
704    ///
705    /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
706    ///
707    /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
708    /// # #[cfg(feature = "bigint")]
709    /// assert_eq!(object.as_biguint(), Ok(65537_u32.into()))
710    /// ```
711    pub fn as_biguint(&self) -> Result<BigUint, BerError> {
712        match self.content {
713            BerObjectContent::Integer(s) => {
714                if is_highest_bit_set(s) {
715                    return Err(BerError::IntegerNegative);
716                }
717                Ok(BigUint::from_bytes_be(s))
718            }
719            _ => Err(BerError::BerValueError),
720        }
721    }
722}
723
724impl<'a> TryFrom<Any<'a>> for BerObject<'a> {
725    type Error = asn1_rs::Error;
726
727    fn try_from(any: Any<'a>) -> Result<Self, Self::Error> {
728        let (header, data) = (any.header, any.data);
729        let (_, content) = ber_read_element_content_as(
730            data,
731            header.tag(),
732            header.length(),
733            header.constructed(),
734            MAX_RECURSION,
735        )?;
736        let obj = BerObject::from_header_and_content(header, content);
737        Ok(obj)
738    }
739}
740
741impl<'a, 'b> TryFrom<&'b Any<'a>> for BerObject<'a> {
742    type Error = asn1_rs::Error;
743
744    fn try_from(any: &'b Any<'a>) -> Result<Self, Self::Error> {
745        let (header, data) = (any.header.clone(), any.data);
746        let (_, content) = ber_read_element_content_as(
747            data,
748            header.tag(),
749            header.length(),
750            header.constructed(),
751            MAX_RECURSION,
752        )?;
753        let obj = BerObject::from_header_and_content(header, content);
754        Ok(obj)
755    }
756}
757
758// This is a consuming iterator
759impl<'a> IntoIterator for BerObject<'a> {
760    type Item = BerObject<'a>;
761    type IntoIter = BerObjectIntoIterator<'a>;
762
763    fn into_iter(self) -> Self::IntoIter {
764        // match self {
765        //     BerObjectContent::Sequence(ref v) => (),
766        //     _ => (),
767        // };
768        BerObjectIntoIterator { val: self, idx: 0 }
769    }
770}
771
772#[derive(Debug)]
773pub struct BerObjectIntoIterator<'a> {
774    val: BerObject<'a>,
775    idx: usize,
776}
777
778impl<'a> Iterator for BerObjectIntoIterator<'a> {
779    type Item = BerObject<'a>;
780    fn next(&mut self) -> Option<BerObject<'a>> {
781        // let result = if self.idx < self.vec.len() {
782        //     Some(self.vec[self.idx].clone())
783        // } else {
784        //     None
785        // };
786        let res = match self.val.content {
787            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
788            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
789            _ => {
790                if self.idx == 0 {
791                    Some(self.val.clone())
792                } else {
793                    None
794                }
795            }
796        };
797        self.idx += 1;
798        res
799    }
800}
801
802// impl<'a> Iterator for BerObjectContent<'a> {
803//     type Item = BerObjectContent<'a>;
804//
805//     fn next(&mut self) -> Option<BerObjectContent<'a>> {
806//         None
807//     }
808// }
809
810#[derive(Debug)]
811pub struct BerObjectRefIterator<'a> {
812    obj: &'a BerObject<'a>,
813    idx: usize,
814}
815
816impl<'a> Iterator for BerObjectRefIterator<'a> {
817    type Item = &'a BerObject<'a>;
818    fn next(&mut self) -> Option<&'a BerObject<'a>> {
819        let res = match (self.obj).content {
820            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
821            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
822            _ => None,
823        };
824        self.idx += 1;
825        res
826    }
827}
828
829impl<'a> BerObject<'a> {
830    pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
831        BerObjectRefIterator { obj: self, idx: 0 }
832    }
833}
834
835impl<'a> Index<usize> for BerObject<'a> {
836    type Output = BerObject<'a>;
837
838    fn index(&self, idx: usize) -> &BerObject<'a> {
839        match (self).content {
840            BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
841            BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
842            _ => panic!("Try to index BerObjectContent which is not constructed"),
843        }
844        // XXX the following
845        // self.ref_iter().nth(idx).unwrap()
846        // fails with:
847        // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
848        // self.ref_iter().nth(idx).unwrap()
849    }
850}
851
852/// BitString wrapper
853#[derive(Clone, Debug, PartialEq)]
854pub struct BitStringObject<'a> {
855    pub data: &'a [u8],
856}
857
858impl BitStringObject<'_> {
859    /// Test if bit `bitnum` is set
860    pub fn is_set(&self, bitnum: usize) -> bool {
861        let byte_pos = bitnum / 8;
862        if byte_pos >= self.data.len() {
863            return false;
864        }
865        let b = 7 - (bitnum % 8);
866        (self.data[byte_pos] & (1 << b)) != 0
867    }
868
869    /// Constructs a shared `&BitSlice` reference over the object data.
870    #[cfg(feature = "as_bitvec")]
871    pub fn as_bitslice(&self) -> Option<&BitSlice<u8, Msb0>> {
872        BitSlice::<_, Msb0>::try_from_slice(self.data).ok()
873    }
874}
875
876impl AsRef<[u8]> for BitStringObject<'_> {
877    fn as_ref(&self) -> &[u8] {
878        self.data
879    }
880}
881
882#[cfg(test)]
883mod tests {
884    use asn1_rs::{Any, FromDer};
885    use core::convert::TryFrom;
886
887    use crate::ber::*;
888    use crate::oid::*;
889
890    #[test]
891    fn ber_from_any() {
892        let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
893
894        let (rem, any) = Any::from_der(bytes).expect("parsing failed");
895        assert!(rem.is_empty());
896        let obj = BerObject::try_from(any).expect("try_from(any) failed");
897        assert_eq!(obj.as_u32(), Ok(0x10001_u32));
898    }
899
900    #[test]
901    fn test_der_as_u64() {
902        let der_obj = BerObject::from_int_slice(b"\x01\x00\x02");
903        assert_eq!(der_obj.as_u64(), Ok(0x10002));
904    }
905
906    #[test]
907    fn test_ber_as_u64_bitstring() {
908        let (_, ber_obj) = parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xc0").unwrap();
909        assert_eq!(ber_obj.as_u64(), Ok(0b011011100101110111));
910
911        let (_, ber_obj_with_nonzero_padding) =
912            parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xe0").unwrap();
913        assert_eq!(
914            ber_obj_with_nonzero_padding.as_u64(),
915            Ok(0b011011100101110111)
916        );
917    }
918
919    #[test]
920    fn test_der_seq_iter() {
921        let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![
922            BerObject::from_int_slice(b"\x01\x00\x01"),
923            BerObject::from_int_slice(b"\x01\x00\x00"),
924        ]));
925        let expected_values = vec![
926            BerObject::from_int_slice(b"\x01\x00\x01"),
927            BerObject::from_int_slice(b"\x01\x00\x00"),
928        ];
929
930        for (idx, v) in der_obj.ref_iter().enumerate() {
931            // println!("v: {:?}", v);
932            assert_eq!((*v), expected_values[idx]);
933        }
934    }
935
936    #[test]
937    fn test_der_from_oid() {
938        let obj: BerObject = Oid::from(&[1, 2]).unwrap().into();
939        let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap()));
940
941        assert_eq!(obj, expected);
942    }
943
944    #[test]
945    fn test_der_bitstringobject() {
946        let obj = BitStringObject {
947            data: &[0x0f, 0x00, 0x40],
948        };
949        assert!(!obj.is_set(0));
950        assert!(obj.is_set(7));
951        assert!(!obj.is_set(9));
952        assert!(obj.is_set(17));
953    }
954
955    #[cfg(feature = "as_bitvec")]
956    #[test]
957    fn test_der_bitslice() {
958        use std::string::String;
959        let obj = BitStringObject {
960            data: &[0x0f, 0x00, 0x40],
961        };
962        let slice = obj.as_bitslice().expect("as_bitslice");
963        assert_eq!(slice.get(0).as_deref(), Some(&false));
964        assert_eq!(slice.get(7).as_deref(), Some(&true));
965        assert_eq!(slice.get(9).as_deref(), Some(&false));
966        assert_eq!(slice.get(17).as_deref(), Some(&true));
967        let s = slice.iter().fold(String::with_capacity(24), |mut acc, b| {
968            acc += if *b { "1" } else { "0" };
969            acc
970        });
971        assert_eq!(&s, "000011110000000001000000");
972    }
973
974    #[test]
975    fn test_der_bistringobject_asref() {
976        fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) {
977            assert_eq!(s.as_ref(), b);
978        }
979        let b: &[u8] = &[0x0f, 0x00, 0x40];
980        let obj = BitStringObject { data: b };
981        assert_equal(obj, b);
982    }
983
984    #[cfg(feature = "bigint")]
985    #[test]
986    fn test_der_to_bigint() {
987        let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
988        let expected = ::num_bigint::BigInt::from(0x10001);
989
990        assert_eq!(obj.as_bigint(), Ok(expected));
991    }
992
993    #[cfg(feature = "bigint")]
994    #[test]
995    fn test_der_to_biguint() {
996        let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
997        let expected = ::num_bigint::BigUint::from(0x10001_u32);
998
999        assert_eq!(obj.as_biguint(), Ok(expected));
1000    }
1001}