Coverage Report

Created: 2026-08-14 07:34

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