Coverage Report

Created: 2025-12-31 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-9.0.0/src/ber/ber.rs
Line
Count
Source
1
use super::{Class, Header, Length, Tag};
2
use crate::ber::ber_read_element_content_as;
3
use crate::ber::bitstring_to_u64;
4
use crate::ber::integer::*;
5
use crate::ber::MAX_RECURSION;
6
use crate::error::BerError;
7
use crate::oid::Oid;
8
use alloc::borrow::ToOwned;
9
use alloc::boxed::Box;
10
use alloc::vec::Vec;
11
use asn1_rs::ASN1DateTime;
12
use asn1_rs::Any;
13
#[cfg(feature = "bitvec")]
14
use bitvec::{order::Msb0, slice::BitSlice};
15
use core::convert::AsRef;
16
use core::convert::From;
17
use core::convert::TryFrom;
18
use 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)]
28
pub 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)]
36
pub 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
106
impl<'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
3.49M
    pub const fn from_header_and_content<'o>(
113
3.49M
        header: Header<'o>,
114
3.49M
        content: BerObjectContent<'o>,
115
3.49M
    ) -> BerObject<'o> {
116
3.49M
        BerObject { header, content }
117
3.49M
    }
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
0
    pub const fn from_obj(c: BerObjectContent) -> BerObject {
122
0
        let class = Class::Universal;
123
0
        let tag = c.tag();
124
0
        let constructed = matches!(tag, Tag::Sequence | Tag::Set);
125
0
        let header = Header::new(class, constructed, tag, Length::Definite(0));
126
0
        BerObject { header, content: c }
127
0
    }
128
129
    /// Build a DER integer object from a slice containing an encoded integer
130
0
    pub const fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
131
0
        let header = Header::new(Class::Universal, false, Tag::Integer, Length::Definite(0));
132
0
        BerObject {
133
0
            header,
134
0
            content: BerObjectContent::Integer(i),
135
0
        }
136
0
    }
137
138
    /// Set a tag for the BER object
139
0
    pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject {
140
0
        let header = self.header.with_raw_tag(raw_tag.map(|x| x.into()));
141
0
        BerObject { header, ..self }
142
0
    }
143
144
    /// Build a DER sequence object from a vector of DER objects
145
0
    pub const fn from_seq(l: Vec<BerObject>) -> BerObject {
146
0
        BerObject::from_obj(BerObjectContent::Sequence(l))
147
0
    }
148
149
    /// Build a DER set object from a vector of DER objects
150
0
    pub const fn from_set(l: Vec<BerObject>) -> BerObject {
151
0
        BerObject::from_obj(BerObjectContent::Set(l))
152
0
    }
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
0
    pub fn as_i64(&self) -> Result<i64, BerError> {
169
0
        self.content.as_i64()
170
0
    }
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
0
    pub fn as_i32(&self) -> Result<i32, BerError> {
187
0
        self.content.as_i32()
188
0
    }
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
0
    pub fn as_u64(&self) -> Result<u64, BerError> {
205
0
        self.content.as_u64()
206
0
    }
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
11.5k
    pub fn as_u32(&self) -> Result<u32, BerError> {
224
11.5k
        self.content.as_u32()
225
11.5k
    }
226
227
    /// Attempt to read integer value from DER object.
228
    /// This can fail if the object is not a boolean.
229
3.60k
    pub fn as_bool(&self) -> Result<bool, BerError> {
230
3.60k
        self.content.as_bool()
231
3.60k
    }
232
233
    /// Attempt to read an OID value from DER object.
234
    /// This can fail if the object is not an OID.
235
0
    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
236
0
        self.content.as_oid()
237
0
    }
238
239
    /// Attempt to read an OID value from DER object.
240
    /// This can fail if the object is not an OID.
241
0
    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
242
0
        self.content.as_oid_val()
243
0
    }
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
0
    pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
248
0
        self.content.as_optional()
249
0
    }
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
0
    pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
254
0
        self.content.as_tagged()
255
0
    }
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
0
    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
263
0
        self.content.as_bitstring_ref()
264
0
    }
265
266
    /// Attempt to read a BitString value from DER object.
267
    /// This can fail if the object is not an BitString.
268
0
    pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
269
0
        self.content.as_bitstring()
270
0
    }
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
0
    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
287
0
        self.content.as_set()
288
0
    }
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
32.6k
    pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
295
32.6k
        self.content.as_slice()
296
32.6k
    }
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
0
    pub fn as_str(&self) -> Result<&'a str, BerError> {
304
0
        self.content.as_str()
305
0
    }
306
307
    /// Get the BER object header's class.
308
    #[inline]
309
0
    pub const fn class(&self) -> Class {
310
0
        self.header.class()
311
0
    }
312
313
    /// Get the BER object header's tag.
314
    #[inline]
315
0
    pub const fn tag(&self) -> Tag {
316
0
        self.header.tag()
317
0
    }
318
319
    /// Get the BER object header's length.
320
    #[inline]
321
0
    pub const fn length(&self) -> Length {
322
0
        self.header.length()
323
0
    }
324
325
    /// Test if object class is Universal
326
    #[inline]
327
0
    pub const fn is_universal(&self) -> bool {
328
0
        self.header.is_universal()
329
0
    }
330
    /// Test if object class is Application
331
    #[inline]
332
0
    pub const fn is_application(&self) -> bool {
333
0
        self.header.is_application()
334
0
    }
335
    /// Test if object class is Context-specific
336
    #[inline]
337
0
    pub const fn is_contextspecific(&self) -> bool {
338
0
        self.header.is_contextspecific()
339
0
    }
340
    /// Test if object class is Private
341
    #[inline]
342
0
    pub fn is_private(&self) -> bool {
343
0
        self.header.is_private()
344
0
    }
345
346
    /// Test if object is primitive
347
    #[inline]
348
0
    pub const fn is_primitive(&self) -> bool {
349
0
        self.header.is_primitive()
350
0
    }
351
    /// Test if object is constructed
352
    #[inline]
353
0
    pub const fn is_constructed(&self) -> bool {
354
0
        self.header.is_constructed()
355
0
    }
356
357
    /// Return error if `class` is not the expected class
358
    #[inline]
359
0
    pub const fn assert_class(&self, class: Class) -> Result<(), BerError> {
360
0
        self.header.assert_class(class)
361
0
    }
362
363
    /// Return error if `tag` is not the expected tag
364
    #[inline]
365
0
    pub const fn assert_tag(&self, tag: Tag) -> Result<(), BerError> {
366
0
        self.header.assert_tag(tag)
367
0
    }
368
369
    /// Return error if object is not constructed
370
    #[inline]
371
0
    pub const fn assert_constructed(&self) -> Result<(), BerError> {
372
0
        self.header.assert_constructed()
373
0
    }
374
375
    /// Return error if object is not primitive
376
    #[inline]
377
0
    pub const fn assert_primitive(&self) -> Result<(), BerError> {
378
0
        self.header.assert_primitive()
379
0
    }
380
}
381
382
/// Build a DER object from an OID.
383
impl<'a> From<Oid<'a>> for BerObject<'a> {
384
0
    fn from(oid: Oid<'a>) -> BerObject<'a> {
385
0
        BerObject::from_obj(BerObjectContent::OID(oid))
386
0
    }
387
}
388
389
/// Build a DER object from a BerObjectContent.
390
impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
391
0
    fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
392
0
        BerObject::from_obj(obj)
393
0
    }
394
}
395
396
impl<'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
0
    pub fn as_i64(&self) -> Result<i64, BerError> {
412
0
        if let BerObjectContent::Integer(bytes) = self {
413
0
            let result = if is_highest_bit_set(bytes) {
414
0
                <i64>::from_be_bytes(decode_array_int8(bytes)?)
415
            } else {
416
0
                <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
417
            };
418
0
            Ok(result)
419
        } else {
420
0
            Err(BerError::BerValueError)
421
        }
422
0
    }
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
0
    pub fn as_i32(&self) -> Result<i32, BerError> {
439
0
        if let BerObjectContent::Integer(bytes) = self {
440
0
            let result = if is_highest_bit_set(bytes) {
441
0
                <i32>::from_be_bytes(decode_array_int4(bytes)?)
442
            } else {
443
0
                <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
444
            };
445
0
            Ok(result)
446
        } else {
447
0
            Err(BerError::BerValueError)
448
        }
449
0
    }
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
0
    pub fn as_u64(&self) -> Result<u64, BerError> {
466
0
        match self {
467
0
            BerObjectContent::Integer(i) => {
468
0
                let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
469
0
                Ok(result)
470
            }
471
0
            BerObjectContent::BitString(ignored_bits, data) => {
472
0
                bitstring_to_u64(*ignored_bits as usize, data)
473
            }
474
0
            BerObjectContent::Enum(i) => Ok(*i),
475
0
            _ => Err(BerError::BerTypeError),
476
        }
477
0
    }
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
11.5k
    pub fn as_u32(&self) -> Result<u32, BerError> {
495
11.5k
        match self {
496
7.75k
            BerObjectContent::Integer(i) => {
497
7.75k
                let result = <u32>::from_be_bytes(decode_array_uint4(i)?);
498
7.70k
                Ok(result)
499
            }
500
225
            BerObjectContent::BitString(ignored_bits, data) => {
501
225
                bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
502
190
                    if x > u64::from(core::u32::MAX) {
503
99
                        Err(BerError::IntegerTooLarge)
504
                    } else {
505
91
                        Ok(x as u32)
506
                    }
507
190
                })
508
            }
509
126
            BerObjectContent::Enum(i) => {
510
126
                if *i > u64::from(core::u32::MAX) {
511
0
                    Err(BerError::IntegerTooLarge)
512
                } else {
513
126
                    Ok(*i as u32)
514
                }
515
            }
516
3.45k
            _ => Err(BerError::BerTypeError),
517
        }
518
11.5k
    }
519
520
3.60k
    pub fn as_bool(&self) -> Result<bool, BerError> {
521
3.60k
        match *self {
522
3.60k
            BerObjectContent::Boolean(b) => Ok(b),
523
1
            _ => Err(BerError::BerTypeError),
524
        }
525
3.60k
    }
526
527
9.47k
    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
528
9.47k
        match *self {
529
9.47k
            BerObjectContent::OID(ref o) => Ok(o),
530
0
            BerObjectContent::RelativeOID(ref o) => Ok(o),
531
0
            _ => Err(BerError::BerTypeError),
532
        }
533
9.47k
    }
534
535
0
    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
536
0
        self.as_oid().map(|o| o.clone())
537
0
    }
538
539
0
    pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
540
0
        match *self {
541
0
            BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
542
0
            BerObjectContent::Optional(None) => Ok(None),
543
0
            _ => Err(BerError::BerTypeError),
544
        }
545
0
    }
546
547
0
    pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
548
0
        match *self {
549
0
            BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())),
550
0
            _ => Err(BerError::BerTypeError),
551
        }
552
0
    }
553
554
0
    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
555
0
        match *self {
556
0
            BerObjectContent::BitString(_, ref b) => Ok(b),
557
0
            _ => Err(BerError::BerTypeError),
558
        }
559
0
    }
560
561
2.00k
    pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
562
2.00k
        match *self {
563
2.00k
            BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
564
0
            _ => Err(BerError::BerTypeError),
565
        }
566
2.00k
    }
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
0
    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
583
0
        match *self {
584
0
            BerObjectContent::Set(ref s) => Ok(s),
585
0
            _ => Err(BerError::BerTypeError),
586
        }
587
0
    }
588
589
    #[rustfmt::skip]
590
98.8k
    pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
591
98.8k
        match *self {
592
567
            BerObjectContent::NumericString(s) |
593
941
            BerObjectContent::BmpString(s) |
594
1.23k
            BerObjectContent::VisibleString(s) |
595
2.58k
            BerObjectContent::PrintableString(s) |
596
1.54k
            BerObjectContent::GeneralString(s) |
597
312
            BerObjectContent::ObjectDescriptor(s) |
598
810
            BerObjectContent::GraphicString(s) |
599
875
            BerObjectContent::T61String(s) |
600
296
            BerObjectContent::VideotexString(s) |
601
575
            BerObjectContent::UTF8String(s) |
602
10.4k
            BerObjectContent::IA5String(s) => Ok(s.as_ref()),
603
3.38k
            BerObjectContent::Integer(s) |
604
5.84k
            BerObjectContent::BitString(_,BitStringObject{data:s}) |
605
423
            BerObjectContent::OctetString(s) |
606
10.2k
            BerObjectContent::UniversalString(s) => Ok(s),
607
54.8k
            BerObjectContent::Unknown(ref any) => Ok(any.data),
608
23.3k
            _ => Err(BerError::BerTypeError),
609
        }
610
98.8k
    }
611
612
    #[rustfmt::skip]
613
0
    pub fn as_str(&self) -> Result<&'a str,BerError> {
614
0
        match *self {
615
0
            BerObjectContent::NumericString(s) |
616
0
            BerObjectContent::BmpString(s) |
617
0
            BerObjectContent::VisibleString(s) |
618
0
            BerObjectContent::PrintableString(s) |
619
0
            BerObjectContent::GeneralString(s) |
620
0
            BerObjectContent::ObjectDescriptor(s) |
621
0
            BerObjectContent::GraphicString(s) |
622
0
            BerObjectContent::T61String(s) |
623
0
            BerObjectContent::VideotexString(s) |
624
0
            BerObjectContent::UTF8String(s) |
625
0
            BerObjectContent::IA5String(s) => Ok(s),
626
0
            _ => Err(BerError::BerTypeError),
627
        }
628
0
    }
629
630
    #[rustfmt::skip]
631
0
    const fn tag(&self) -> Tag {
632
0
        match self {
633
0
            BerObjectContent::EndOfContent         => Tag::EndOfContent,
634
0
            BerObjectContent::Boolean(_)           => Tag::Boolean,
635
0
            BerObjectContent::Integer(_)           => Tag::Integer,
636
0
            BerObjectContent::BitString(_,_)       => Tag::BitString,
637
0
            BerObjectContent::OctetString(_)       => Tag::OctetString,
638
0
            BerObjectContent::Null                 => Tag::Null,
639
0
            BerObjectContent::Enum(_)              => Tag::Enumerated,
640
0
            BerObjectContent::OID(_)               => Tag::Oid,
641
0
            BerObjectContent::NumericString(_)     => Tag::NumericString,
642
0
            BerObjectContent::VisibleString(_)     => Tag::VisibleString,
643
0
            BerObjectContent::PrintableString(_)   => Tag::PrintableString,
644
0
            BerObjectContent::IA5String(_)         => Tag::Ia5String,
645
0
            BerObjectContent::UTF8String(_)        => Tag::Utf8String,
646
0
            BerObjectContent::RelativeOID(_)       => Tag::RelativeOid,
647
0
            BerObjectContent::T61String(_)         => Tag::T61String,
648
0
            BerObjectContent::VideotexString(_)    => Tag::VideotexString,
649
0
            BerObjectContent::BmpString(_)         => Tag::BmpString,
650
0
            BerObjectContent::UniversalString(_)   => Tag::UniversalString,
651
0
            BerObjectContent::Sequence(_)          => Tag::Sequence,
652
0
            BerObjectContent::Set(_)               => Tag::Set,
653
0
            BerObjectContent::UTCTime(_)           => Tag::UtcTime,
654
0
            BerObjectContent::GeneralizedTime(_)   => Tag::GeneralizedTime,
655
0
            BerObjectContent::ObjectDescriptor(_)  => Tag::ObjectDescriptor,
656
0
            BerObjectContent::GraphicString(_)     => Tag::GraphicString,
657
0
            BerObjectContent::GeneralString(_)     => Tag::GeneralString,
658
0
            BerObjectContent::Tagged(_,x,_) => *x,
659
0
            BerObjectContent::Unknown(any) => any.tag(),
660
0
            BerObjectContent::Optional(Some(obj))  => obj.content.tag(),
661
0
            BerObjectContent::Optional(None)       => Tag(0x00), // XXX invalid !
662
        }
663
0
    }
664
}
665
666
#[cfg(feature = "bigint")]
667
#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
668
use num_bigint::{BigInt, BigUint};
669
670
#[cfg(feature = "bigint")]
671
#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
672
impl<'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
0
    pub fn as_bigint(&self) -> Result<BigInt, BerError> {
689
0
        match self.content {
690
0
            BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
691
0
            _ => Err(BerError::BerValueError),
692
        }
693
0
    }
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
0
    pub fn as_biguint(&self) -> Result<BigUint, BerError> {
711
0
        match self.content {
712
0
            BerObjectContent::Integer(s) => {
713
0
                if is_highest_bit_set(s) {
714
0
                    return Err(BerError::IntegerNegative);
715
0
                }
716
0
                Ok(BigUint::from_bytes_be(s))
717
            }
718
0
            _ => Err(BerError::BerValueError),
719
        }
720
0
    }
721
}
722
723
impl<'a> TryFrom<Any<'a>> for BerObject<'a> {
724
    type Error = asn1_rs::Error;
725
726
0
    fn try_from(any: Any<'a>) -> Result<Self, Self::Error> {
727
0
        let (header, data) = (any.header, any.data);
728
0
        let (_, content) = ber_read_element_content_as(
729
0
            data,
730
0
            header.tag(),
731
0
            header.length(),
732
0
            header.constructed(),
733
            MAX_RECURSION,
734
0
        )?;
735
0
        let obj = BerObject::from_header_and_content(header, content);
736
0
        Ok(obj)
737
0
    }
738
}
739
740
impl<'a, 'b> TryFrom<&'b Any<'a>> for BerObject<'a> {
741
    type Error = asn1_rs::Error;
742
743
0
    fn try_from(any: &'b Any<'a>) -> Result<Self, Self::Error> {
744
0
        let (header, data) = (any.header.clone(), any.data);
745
0
        let (_, content) = ber_read_element_content_as(
746
0
            data,
747
0
            header.tag(),
748
0
            header.length(),
749
0
            header.constructed(),
750
            MAX_RECURSION,
751
0
        )?;
752
0
        let obj = BerObject::from_header_and_content(header, content);
753
0
        Ok(obj)
754
0
    }
755
}
756
757
// This is a consuming iterator
758
impl<'a> IntoIterator for BerObject<'a> {
759
    type Item = BerObject<'a>;
760
    type IntoIter = BerObjectIntoIterator<'a>;
761
762
3.17k
    fn into_iter(self) -> Self::IntoIter {
763
        // match self {
764
        //     BerObjectContent::Sequence(ref v) => (),
765
        //     _ => (),
766
        // };
767
3.17k
        BerObjectIntoIterator { val: self, idx: 0 }
768
3.17k
    }
769
}
770
771
#[derive(Debug)]
772
pub struct BerObjectIntoIterator<'a> {
773
    val: BerObject<'a>,
774
    idx: usize,
775
}
776
777
impl<'a> Iterator for BerObjectIntoIterator<'a> {
778
    type Item = BerObject<'a>;
779
9.59k
    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
9.59k
        let res = match self.val.content {
786
9.59k
            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
787
0
            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
788
            _ => {
789
3.18k
                if self.idx == 0 {
790
3
                    Some(self.val.clone())
791
                } else {
792
3.17k
                    None
793
                }
794
            }
795
        };
796
9.59k
        self.idx += 1;
797
9.59k
        res
798
9.59k
    }
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)]
810
pub struct BerObjectRefIterator<'a> {
811
    obj: &'a BerObject<'a>,
812
    idx: usize,
813
}
814
815
impl<'a> Iterator for BerObjectRefIterator<'a> {
816
    type Item = &'a BerObject<'a>;
817
0
    fn next(&mut self) -> Option<&'a BerObject<'a>> {
818
0
        let res = match (self.obj).content {
819
0
            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
820
0
            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
821
0
            _ => None,
822
        };
823
0
        self.idx += 1;
824
0
        res
825
0
    }
826
}
827
828
impl<'a> BerObject<'a> {
829
0
    pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
830
0
        BerObjectRefIterator { obj: self, idx: 0 }
831
0
    }
832
}
833
834
impl<'a> Index<usize> for BerObject<'a> {
835
    type Output = BerObject<'a>;
836
837
0
    fn index(&self, idx: usize) -> &BerObject<'a> {
838
0
        match (self).content {
839
0
            BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
840
0
            BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
841
0
            _ => 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
0
    }
849
}
850
851
/// BitString wrapper
852
#[derive(Clone, Debug, PartialEq)]
853
pub struct BitStringObject<'a> {
854
    pub data: &'a [u8],
855
}
856
857
impl<'a> BitStringObject<'a> {
858
    /// Test if bit `bitnum` is set
859
0
    pub fn is_set(&self, bitnum: usize) -> bool {
860
0
        let byte_pos = bitnum / 8;
861
0
        if byte_pos >= self.data.len() {
862
0
            return false;
863
0
        }
864
0
        let b = 7 - (bitnum % 8);
865
0
        (self.data[byte_pos] & (1 << b)) != 0
866
0
    }
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
875
impl<'a> AsRef<[u8]> for BitStringObject<'a> {
876
0
    fn as_ref(&self) -> &[u8] {
877
0
        self.data
878
0
    }
879
}
880
881
#[cfg(test)]
882
mod 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
}