Coverage Report

Created: 2026-01-16 07:00

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