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#[derive(Clone, Debug)]
20pub struct Header<'a> {
21 pub(crate) class: Class,
23 pub(crate) constructed: bool,
25 pub(crate) tag: Tag,
27 pub(crate) length: Length,
29
30 pub(crate) raw_tag: Option<Cow<'a, [u8]>>,
35
36 pub(crate) raw_header: Option<Input<'a>>,
37}
38
39impl<'a> Header<'a> {
40 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 #[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 #[inline]
61 pub fn with_class(self, class: Class) -> Self {
62 Self { class, ..self }
63 }
64
65 #[inline]
67 pub fn with_constructed(self, constructed: bool) -> Self {
68 Self {
69 constructed,
70 ..self
71 }
72 }
73
74 #[inline]
76 pub fn with_tag(self, tag: Tag) -> Self {
77 Self { tag, ..self }
78 }
79
80 #[inline]
82 pub fn with_length(self, length: Length) -> Self {
83 Self { length, ..self }
84 }
85
86 #[inline]
88 pub fn with_raw_tag(self, raw_tag: Option<Cow<'a, [u8]>>) -> Self {
89 Header { raw_tag, ..self }
90 }
91
92 #[inline]
94 pub fn with_raw_header(self, raw_header: Option<Input<'a>>) -> Self {
95 Header { raw_header, ..self }
96 }
97
98 #[inline]
100 pub const fn class(&self) -> Class {
101 self.class
102 }
103
104 #[inline]
106 pub const fn constructed(&self) -> bool {
107 self.constructed
108 }
109
110 #[inline]
112 pub const fn tag(&self) -> Tag {
113 self.tag
114 }
115
116 #[inline]
118 pub const fn length(&self) -> Length {
119 self.length
120 }
121
122 #[inline]
124 pub fn raw_tag(&self) -> Option<&[u8]> {
125 self.raw_tag.as_ref().map(|cow| cow.as_ref())
126 }
127
128 #[inline]
130 pub fn raw_header(&self) -> Option<&Input<'a>> {
131 self.raw_header.as_ref()
132 }
133
134 #[inline]
136 pub const fn is_primitive(&self) -> bool {
137 !self.constructed
138 }
139
140 #[inline]
142 pub const fn is_constructed(&self) -> bool {
143 self.constructed
144 }
145
146 #[inline]
148 pub const fn assert_class(&self, class: Class) -> Result<()> {
149 self.class.assert_eq(class)
150 }
151
152 #[inline]
154 pub const fn assert_tag(&self, tag: Tag) -> Result<()> {
155 self.tag.assert_eq(tag)
156 }
157
158 #[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 #[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 #[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 #[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 #[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 #[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 #[inline]
232 pub const fn is_universal(&self) -> bool {
233 self.class as u8 == Class::Universal as u8
234 }
235 #[inline]
237 pub const fn is_application(&self) -> bool {
238 self.class as u8 == Class::Application as u8
239 }
240 #[inline]
242 pub const fn is_contextspecific(&self) -> bool {
243 self.class as u8 == Class::ContextSpecific as u8
244 }
245 #[inline]
247 pub const fn is_private(&self) -> bool {
248 self.class as u8 == Class::Private as u8
249 }
250
251 #[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 #[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 #[inline]
275 pub fn parse_ber_content<'i>(
276 &'_ self,
277 i: Input<'i>,
278 ) -> IResult<Input<'i>, Input<'i>, BerError<Input<'i>>> {
279 BerMode::get_object_content(self, i, 8)
282 }
283
284 #[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 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 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 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 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 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
446impl<'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 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 let (rem, b0) = be_u8(input.clone())?;
487
488 let class_b0 = b0 >> 6;
490
491 let class = match Class::try_from(class_b0) {
492 Ok(c) => c,
493 Err(_) => unreachable!(), };
495
496 const CONSTRUCTED_BIT: u8 = 0b0010_0000;
497 let constructed = (b0 & CONSTRUCTED_BIT) != 0;
499
500 const TAG_MASK0: u8 = 0b0001_1111;
501 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 if tag0 == TAG_MASK0 {
509 let mut c = 0;
511 loop {
512 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 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 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 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 Length::Definite(len_b0 as usize)
554 } else {
555 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#[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 #[test]
604 fn methods_header() {
605 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 let hdr2 = Header::new_simple(Tag::Integer);
619 assert_eq!(header, hdr2);
620
621 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 hdr4 = hdr3.with_length(Length::Indefinite);
635 assert!(hdr4.assert_definite().is_err());
636 let primitive_indef = &hex!("0280");
641 Header::parse_ber(primitive_indef.into()).expect_err("primitive with indefinite length");
642
643 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}