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