asn1_rs/
header.rs

1use crate::ber::*;
2use crate::debug::trace_input;
3use crate::error::*;
4use crate::wrap_ber_parser;
5use crate::DerParser;
6#[cfg(feature = "std")]
7use crate::ToDer;
8use crate::{BerMode, Class, DerMode, DynTagged, FromBer, FromDer, Length, Tag, ToStatic};
9use crate::{BerParser, Input};
10use alloc::borrow::Cow;
11use core::convert::TryFrom;
12use core::hash::Hash;
13use nom::bytes::streaming::take;
14use nom::number::streaming::be_u8;
15use nom::Input as _;
16use nom::{Err, IResult};
17
18/// BER/DER object header (identifier and length)
19#[derive(Clone, Debug)]
20pub struct Header<'a> {
21    /// Object class: universal, application, context-specific, or private
22    pub(crate) class: Class,
23    /// Constructed attribute: true if constructed, else false
24    pub(crate) constructed: bool,
25    /// Tag number
26    pub(crate) tag: Tag,
27    /// Object length: value if definite, or indefinite
28    pub(crate) length: Length,
29
30    /// Optionally, the raw encoding of the tag
31    ///
32    /// This is useful in some cases, where different representations of the same
33    /// BER tags have different meanings (BER only)
34    pub(crate) raw_tag: Option<Cow<'a, [u8]>>,
35
36    pub(crate) raw_header: Option<Input<'a>>,
37}
38
39impl<'a> Header<'a> {
40    /// Build a new BER/DER header from the provided values
41    pub const fn new(class: Class, constructed: bool, tag: Tag, length: Length) -> Self {
42        Header {
43            tag,
44            constructed,
45            class,
46            length,
47            raw_tag: None,
48            raw_header: None,
49        }
50    }
51
52    /// Build a new BER/DER header from the provided tag, with default values for other fields
53    #[inline]
54    pub const fn new_simple(tag: Tag) -> Self {
55        let constructed = matches!(tag, Tag::Sequence | Tag::Set);
56        Self::new(Class::Universal, constructed, tag, Length::Definite(0))
57    }
58
59    /// Set the class of this `Header`
60    #[inline]
61    pub fn with_class(self, class: Class) -> Self {
62        Self { class, ..self }
63    }
64
65    /// Set the constructed flags of this `Header`
66    #[inline]
67    pub fn with_constructed(self, constructed: bool) -> Self {
68        Self {
69            constructed,
70            ..self
71        }
72    }
73
74    /// Set the tag of this `Header`
75    #[inline]
76    pub fn with_tag(self, tag: Tag) -> Self {
77        Self { tag, ..self }
78    }
79
80    /// Set the length of this `Header`
81    #[inline]
82    pub fn with_length(self, length: Length) -> Self {
83        Self { length, ..self }
84    }
85
86    /// Update header to add reference to raw tag
87    #[inline]
88    pub fn with_raw_tag(self, raw_tag: Option<Cow<'a, [u8]>>) -> Self {
89        Header { raw_tag, ..self }
90    }
91
92    /// Update header to add reference to raw header
93    #[inline]
94    pub fn with_raw_header(self, raw_header: Option<Input<'a>>) -> Self {
95        Header { raw_header, ..self }
96    }
97
98    /// Return the class of this header.
99    #[inline]
100    pub const fn class(&self) -> Class {
101        self.class
102    }
103
104    /// Return true if this header has the 'constructed' flag.
105    #[inline]
106    pub const fn constructed(&self) -> bool {
107        self.constructed
108    }
109
110    /// Return the tag of this header.
111    #[inline]
112    pub const fn tag(&self) -> Tag {
113        self.tag
114    }
115
116    /// Return the length of this header.
117    #[inline]
118    pub const fn length(&self) -> Length {
119        self.length
120    }
121
122    /// Return the raw tag encoding, if it was stored in this object
123    #[inline]
124    pub fn raw_tag(&self) -> Option<&[u8]> {
125        self.raw_tag.as_ref().map(|cow| cow.as_ref())
126    }
127
128    /// Return the raw tag encoding, if it was stored in this object
129    #[inline]
130    pub fn raw_header(&self) -> Option<&Input<'a>> {
131        self.raw_header.as_ref()
132    }
133
134    /// Test if object is primitive
135    #[inline]
136    pub const fn is_primitive(&self) -> bool {
137        !self.constructed
138    }
139
140    /// Test if object is constructed
141    #[inline]
142    pub const fn is_constructed(&self) -> bool {
143        self.constructed
144    }
145
146    /// Return error if class is not the expected class
147    #[inline]
148    pub const fn assert_class(&self, class: Class) -> Result<()> {
149        self.class.assert_eq(class)
150    }
151
152    /// Return error if tag is not the expected tag
153    #[inline]
154    pub const fn assert_tag(&self, tag: Tag) -> Result<()> {
155        self.tag.assert_eq(tag)
156    }
157
158    /// Return error if object is not primitive (returning an `Error`)
159    #[inline]
160    pub const fn assert_primitive(&self) -> Result<()> {
161        if self.is_primitive() {
162            Ok(())
163        } else {
164            Err(Error::ConstructUnexpected)
165        }
166    }
167
168    /// Return error if object is not primitive (returning an `InnerError`)
169    #[inline]
170    pub const fn assert_primitive_inner(&self) -> Result<(), InnerError> {
171        if self.is_primitive() {
172            Ok(())
173        } else {
174            Err(InnerError::ConstructUnexpected)
175        }
176    }
177
178    /// Return error if object is not primitive (returning a `BerError`)
179    #[inline]
180    pub const fn assert_primitive_input<'i>(
181        &'_ self,
182        input: &'_ Input<'i>,
183    ) -> Result<(), BerError<Input<'i>>> {
184        if self.is_primitive() {
185            Ok(())
186        } else {
187            Err(BerError::new(
188                input.const_clone(),
189                InnerError::ConstructUnexpected,
190            ))
191        }
192    }
193
194    /// Return error if object is primitive
195    #[inline]
196    pub const fn assert_constructed(&self) -> Result<()> {
197        if !self.is_primitive() {
198            Ok(())
199        } else {
200            Err(Error::ConstructExpected)
201        }
202    }
203
204    /// Return error if object is primitive
205    #[inline]
206    pub const fn assert_constructed_inner(&self) -> Result<(), InnerError> {
207        if !self.is_primitive() {
208            Ok(())
209        } else {
210            Err(InnerError::ConstructExpected)
211        }
212    }
213
214    /// Return error if object is primitive (returning a `BerError`)
215    #[inline]
216    pub const fn assert_constructed_input<'i>(
217        &'_ self,
218        input: &'_ Input<'i>,
219    ) -> Result<(), BerError<Input<'i>>> {
220        if !self.is_primitive() {
221            Ok(())
222        } else {
223            Err(BerError::new(
224                input.const_clone(),
225                InnerError::ConstructExpected,
226            ))
227        }
228    }
229
230    /// Test if object class is Universal
231    #[inline]
232    pub const fn is_universal(&self) -> bool {
233        self.class as u8 == Class::Universal as u8
234    }
235    /// Test if object class is Application
236    #[inline]
237    pub const fn is_application(&self) -> bool {
238        self.class as u8 == Class::Application as u8
239    }
240    /// Test if object class is Context-specific
241    #[inline]
242    pub const fn is_contextspecific(&self) -> bool {
243        self.class as u8 == Class::ContextSpecific as u8
244    }
245    /// Test if object class is Private
246    #[inline]
247    pub const fn is_private(&self) -> bool {
248        self.class as u8 == Class::Private as u8
249    }
250
251    /// Return error if object length is definite
252    #[inline]
253    pub const fn assert_definite(&self) -> Result<()> {
254        if self.length.is_definite() {
255            Ok(())
256        } else {
257            Err(Error::DerConstraintFailed(DerConstraint::IndefiniteLength))
258        }
259    }
260
261    /// Return error if object length is definite
262    #[inline]
263    pub const fn assert_definite_inner(&self) -> Result<(), InnerError> {
264        if self.length.is_definite() {
265            Ok(())
266        } else {
267            Err(InnerError::DerConstraintFailed(
268                DerConstraint::IndefiniteLength,
269            ))
270        }
271    }
272
273    /// Get the content following a BER header
274    #[inline]
275    pub fn parse_ber_content<'i>(
276        &'_ self,
277        i: Input<'i>,
278    ) -> IResult<Input<'i>, Input<'i>, BerError<Input<'i>>> {
279        // defaults to maximum depth 8
280        // depth is used only if BER, and length is indefinite
281        BerMode::get_object_content(self, i, 8)
282    }
283
284    /// Get the content following a DER header
285    #[inline]
286    pub fn parse_der_content<'i>(
287        &'_ self,
288        i: Input<'i>,
289    ) -> IResult<Input<'i>, Input<'i>, BerError<Input<'i>>> {
290        self.assert_definite_inner()
291            .map_err(BerError::convert(i.clone()))?;
292        DerMode::get_object_content(self, i, 8)
293    }
294}
295
296impl From<Tag> for Header<'_> {
297    #[inline]
298    fn from(tag: Tag) -> Self {
299        let constructed = matches!(tag, Tag::Sequence | Tag::Set);
300        Self::new(Class::Universal, constructed, tag, Length::Definite(0))
301    }
302}
303
304impl ToStatic for Header<'_> {
305    type Owned = Header<'static>;
306
307    fn to_static(&self) -> Self::Owned {
308        let raw_tag: Option<Cow<'static, [u8]>> =
309            self.raw_tag.as_ref().map(|b| Cow::Owned(b.to_vec()));
310        Header {
311            tag: self.tag,
312            constructed: self.constructed,
313            class: self.class,
314            length: self.length,
315            raw_tag,
316            // Since raw_header is shared, ToStatic cannot keep a reference
317            raw_header: None,
318        }
319    }
320}
321
322impl<'a> FromBer<'a> for Header<'a> {
323    fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self> {
324        wrap_ber_parser(parse_header)(bytes)
325    }
326}
327
328impl<'i> BerParser<'i> for Header<'i> {
329    type Error = BerError<Input<'i>>;
330
331    fn parse_ber(input: Input<'i>) -> IResult<Input<'i>, Self, Self::Error> {
332        trace_input("Header::parse_ber", |i| parse_header(i))(input)
333    }
334
335    /// <div class="warning">This method is usually not called (and will create a useless clone)</div>
336    fn from_ber_content(
337        header: &'_ Header<'i>,
338        input: Input<'i>,
339    ) -> IResult<Input<'i>, Self, Self::Error> {
340        #[cfg(feature = "debug")]
341        {
342            log::trace!("Header::from_ber_content creates a useless clone and should be avoided");
343        }
344        Ok((input, header.clone()))
345    }
346}
347
348impl<'i> DerParser<'i> for Header<'i> {
349    type Error = BerError<Input<'i>>;
350
351    fn parse_der(input: Input<'i>) -> IResult<Input<'i>, Self, Self::Error> {
352        trace_input("Header::parse_ber", |input| {
353            let (rem, header) = parse_header(input.clone())?;
354            // DER parser: we reject Indefinite length
355            if !header.length.is_definite() {
356                return Err(Err::Error(BerError::new(
357                    input,
358                    InnerError::DerConstraintFailed(DerConstraint::IndefiniteLength),
359                )));
360            }
361            Ok((rem, header))
362        })(input)
363    }
364
365    /// <div class="warning">This method is usually not called (and will create a useless clone)</div>
366    fn from_der_content(
367        header: &'_ Header<'i>,
368        input: Input<'i>,
369    ) -> IResult<Input<'i>, Self, Self::Error> {
370        #[cfg(feature = "debug")]
371        {
372            log::trace!("Header::from_der_content creates a useless clone and should be avoided");
373        }
374        Ok((input, header.clone()))
375    }
376}
377
378impl<'a> FromDer<'a> for Header<'a> {
379    fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self> {
380        let (rem, header) = wrap_ber_parser(parse_header)(bytes)?;
381        // DER parser: we reject Indefinite length
382        if !header.length.is_definite() {
383            return Err(Err::Error(Error::DerConstraintFailed(
384                DerConstraint::IndefiniteLength,
385            )));
386        }
387        Ok((rem, header))
388    }
389}
390
391impl DynTagged for Header<'_> {
392    fn class(&self) -> Class {
393        self.class
394    }
395
396    fn constructed(&self) -> bool {
397        self.constructed
398    }
399
400    fn tag(&self) -> Tag {
401        self.tag
402    }
403
404    fn accept_tag(_: Tag) -> bool {
405        true
406    }
407}
408
409#[cfg(feature = "std")]
410const _: () = {
411    use crate::{BerGenericEncoder, ToBer};
412
413    impl ToBer for Header<'_> {
414        type Encoder = BerGenericEncoder;
415
416        fn ber_content_len(&self) -> Length {
417            self.length()
418        }
419
420        fn ber_write_content<W: std::io::Write>(&self, _: &mut W) -> SerializeResult<usize> {
421            Ok(0)
422        }
423
424        fn ber_tag_info(&self) -> (Class, bool, Tag) {
425            (self.class(), self.constructed(), self.tag())
426        }
427    }
428
429    impl ToDer for Header<'_> {
430        type Encoder = BerGenericEncoder;
431
432        fn der_content_len(&self) -> Length {
433            self.length()
434        }
435
436        fn der_write_content<W: std::io::Write>(&self, _: &mut W) -> SerializeResult<usize> {
437            Ok(0)
438        }
439
440        fn der_tag_info(&self) -> (Class, bool, Tag) {
441            (self.class(), self.constructed(), self.tag())
442        }
443    }
444};
445
446/// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`)
447impl<'a> PartialEq<Header<'a>> for Header<'a> {
448    fn eq(&self, other: &Header) -> bool {
449        self.class == other.class
450            && self.tag == other.tag
451            && self.constructed == other.constructed
452            && {
453                if self.length.is_null() && other.length.is_null() {
454                    self.length == other.length
455                } else {
456                    true
457                }
458            }
459            && {
460                // it tag is present for both, compare it
461                if self.raw_tag.as_ref().xor(other.raw_tag.as_ref()).is_none() {
462                    self.raw_tag == other.raw_tag
463                } else {
464                    true
465                }
466            }
467    }
468}
469
470impl Eq for Header<'_> {}
471
472impl Hash for Header<'_> {
473    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
474        self.class.hash(state);
475        self.constructed.hash(state);
476        self.tag.hash(state);
477        self.length.hash(state);
478        self.raw_tag.hash(state);
479    }
480}
481
482pub(crate) fn parse_header(
483    input: Input<'_>,
484) -> IResult<Input<'_>, Header<'_>, BerError<Input<'_>>> {
485    // parse identifier octets (X.690: 8.1.2)
486    let (rem, b0) = be_u8(input.clone())?;
487
488    // bits 8 and 7 represent the class of the tag
489    let class_b0 = b0 >> 6;
490
491    let class = match Class::try_from(class_b0) {
492        Ok(c) => c,
493        Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits
494    };
495
496    const CONSTRUCTED_BIT: u8 = 0b0010_0000;
497    // bit 6 shall be a 0 (primitive) or 1 (constructed)
498    let constructed = (b0 & CONSTRUCTED_BIT) != 0;
499
500    const TAG_MASK0: u8 = 0b0001_1111;
501    // bits 5 to 1 encode the number of the tag
502    let tag0 = b0 & TAG_MASK0;
503
504    let mut rem = rem;
505    let mut tag = u32::from(tag0);
506    let mut tag_byte_count = 1;
507    // test if tag >= 31 (X.690: 8.1.2.4)
508    if tag0 == TAG_MASK0 {
509        // read next bytes as specified in 8.1.2.4.2
510        let mut c = 0;
511        loop {
512            // Make sure we don't read past the end of our data.
513            let (r, b) = be_u8(rem).map_err(|_: Err<BerError<Input>>| {
514                BerError::nom_err_input(&input, InnerError::InvalidTag)
515            })?;
516            rem = r;
517
518            // With tag defined as u32 the most we can fit in is four tag bytes.
519            // (X.690 doesn't actually specify maximum tag width.)
520            // custom_check!(i, tag_byte_count > 5, Error::InvalidTag)?;
521            if tag_byte_count > 5 {
522                return Err(BerError::nom_err_input(&input, InnerError::InvalidTag));
523            }
524
525            c = (c << 7) | (u32::from(b) & 0x7f);
526            let done = b & 0x80 == 0;
527            tag_byte_count += 1;
528            if done {
529                break;
530            }
531        }
532        tag = c;
533    }
534
535    let raw_tag_bytes = &input.as_bytes2()[..tag_byte_count];
536
537    // now parse length byte (X.690: 8.1.3)
538    let (rem, len_b0) = be_u8(rem)?;
539    let mut rem = rem;
540
541    const INDEFINITE: u8 = 0b1000_0000;
542    let length = if len_b0 == INDEFINITE {
543        // indefinite form (X.690: 8.1.3.6)
544        if !constructed {
545            return Err(Err::Error(BerError::new(
546                input,
547                InnerError::IndefiniteLengthUnexpected,
548            )));
549        }
550        Length::Indefinite
551    } else if len_b0 & INDEFINITE == 0 {
552        // definite, short form (X.690: 8.1.3.4)
553        Length::Definite(len_b0 as usize)
554    } else {
555        // definite, long form (X.690: 8.1.3.5)
556
557        // value 0b1111_1111 shall not be used (X.690: 8.1.3.5)
558        if len_b0 == 0xff {
559            return Err(Err::Error(BerError::new(input, InnerError::InvalidLength)));
560        }
561        let (r, len_bytes) = take(len_b0 & !INDEFINITE)(rem)?;
562        rem = r;
563
564        match bytes_to_u64_g(len_bytes) {
565            Ok(l) => {
566                let l = usize::try_from(l)
567                    .map_err(|_| BerError::nom_err_input(&input, InnerError::InvalidLength))?;
568                Length::Definite(l)
569            }
570            _ => return Err(Err::Error(BerError::new(input, InnerError::InvalidLength))),
571        }
572    };
573
574    let raw_header_len = rem.start() - input.start();
575    let raw_header = input.take(raw_header_len);
576
577    let header = Header::new(class, constructed, Tag(tag), length)
578        .with_raw_tag(Some(Cow::Borrowed(raw_tag_bytes)))
579        .with_raw_header(Some(raw_header));
580    Ok((rem, header))
581}
582
583/// Try to parse *all* input bytes as u64
584#[inline]
585pub(crate) fn bytes_to_u64_g<I: nom::Input<Item = u8>>(s: I) -> Result<u64, InnerError> {
586    let mut u: u64 = 0;
587    for c in s.iter_elements() {
588        if u & 0xff00_0000_0000_0000 != 0 {
589            return Err(InnerError::IntegerTooLarge);
590        }
591        u <<= 8;
592        u |= u64::from(c);
593    }
594    Ok(u)
595}
596
597#[cfg(all(test, feature = "std"))]
598mod tests {
599    use crate::*;
600    use hex_literal::hex;
601
602    /// Generic tests on methods, and coverage tests
603    #[test]
604    fn methods_header() {
605        // Getters
606        let input = &hex! {"02 01 00"};
607        let (rem, header) = Header::from_ber(input).expect("parsing header failed");
608        assert_eq!(header.class(), Class::Universal);
609        assert_eq!(header.tag(), Tag::Integer);
610        assert!(header.assert_primitive().is_ok());
611        assert!(header.assert_constructed().is_err());
612        assert!(header.is_universal());
613        assert!(!header.is_application());
614        assert!(!header.is_private());
615        assert_eq!(rem, &input[2..]);
616
617        // test PartialEq
618        let hdr2 = Header::new_simple(Tag::Integer);
619        assert_eq!(header, hdr2);
620
621        // builder methods
622        let hdr3 = hdr2
623            .with_class(Class::ContextSpecific)
624            .with_constructed(true)
625            .with_length(Length::Definite(1));
626        assert!(hdr3.constructed());
627        assert!(hdr3.is_constructed());
628        assert!(hdr3.assert_constructed().is_ok());
629        assert!(hdr3.is_contextspecific());
630        // let xx = hdr3.to_der_vec().expect("serialize failed");
631        // assert_eq!(&xx, &[0xa2, 0x01]);
632
633        // indefinite length
634        let hdr4 = hdr3.with_length(Length::Indefinite);
635        assert!(hdr4.assert_definite().is_err());
636        // let xx = hdr4.to_der_vec().expect("serialize failed");
637        // assert_eq!(&xx, &[0xa2, 0x80]);
638
639        // indefinite length should be accepted only if constructed
640        let primitive_indef = &hex!("0280");
641        Header::parse_ber(primitive_indef.into()).expect_err("primitive with indefinite length");
642
643        // parse_*_content
644        let hdr = Header::new_simple(Tag(2)).with_length(Length::Definite(1));
645        let i: Input = (&input[2..]).into();
646        let (_, r) = hdr.parse_ber_content(i.clone()).unwrap();
647        assert_eq!(r.as_bytes2(), &input[2..]);
648        let (_, r) = hdr.parse_der_content(i).unwrap();
649        assert_eq!(r.as_bytes2(), &input[2..]);
650    }
651}