Coverage Report

Created: 2026-04-14 06:46

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