|
1 | 1 | //! Length calculations for encoded ASN.1 DER values
|
2 | 2 |
|
| 3 | +pub(crate) mod indefinite; |
| 4 | + |
| 5 | +use self::indefinite::INDEFINITE_LENGTH_OCTET; |
3 | 6 | use crate::{
|
4 |
| - Decode, DerOrd, Encode, EncodingRules, Error, ErrorKind, Header, Reader, Result, SliceWriter, |
5 |
| - Tag, Writer, |
| 7 | + Decode, DerOrd, Encode, EncodingRules, Error, ErrorKind, Reader, Result, SliceWriter, Tag, |
| 8 | + Writer, |
6 | 9 | };
|
7 | 10 | use core::{
|
8 | 11 | cmp::Ordering,
|
9 | 12 | fmt,
|
10 | 13 | ops::{Add, Sub},
|
11 | 14 | };
|
12 | 15 |
|
13 |
| -/// Octet identifying an indefinite length as described in X.690 Section |
14 |
| -/// 8.1.3.6.1: |
15 |
| -/// |
16 |
| -/// > The single octet shall have bit 8 set to one, and bits 7 to |
17 |
| -/// > 1 set to zero. |
18 |
| -const INDEFINITE_LENGTH_OCTET: u8 = 0b10000000; // 0x80 |
19 |
| - |
20 | 16 | /// ASN.1-encoded length.
|
21 | 17 | #[derive(Copy, Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
22 | 18 | pub struct Length {
|
@@ -257,7 +253,7 @@ impl<'a> Decode<'a> for Length {
|
257 | 253 | // Note: per X.690 Section 8.1.3.6.1 the byte 0x80 encodes indefinite lengths
|
258 | 254 | INDEFINITE_LENGTH_OCTET => match reader.encoding_rules() {
|
259 | 255 | // Indefinite lengths are allowed when decoding BER
|
260 |
| - EncodingRules::Ber => decode_indefinite_length(&mut reader.clone()), |
| 256 | + EncodingRules::Ber => indefinite::decode_indefinite_length(&mut reader.clone()), |
261 | 257 | // Indefinite lengths are disallowed when decoding DER
|
262 | 258 | EncodingRules::Der => Err(reader.error(ErrorKind::IndefiniteLength)),
|
263 | 259 | },
|
@@ -370,75 +366,12 @@ impl<'a> arbitrary::Arbitrary<'a> for Length {
|
370 | 366 | }
|
371 | 367 | }
|
372 | 368 |
|
373 |
| -/// Decode indefinite lengths as used by ASN.1 BER and described in X.690 Section 8.1.3.6: |
374 |
| -/// |
375 |
| -/// > 8.1.3.6 For the indefinite form, the length octets indicate that the |
376 |
| -/// > contents octets are terminated by end-of-contents |
377 |
| -/// > octets (see 8.1.5), and shall consist of a single octet. |
378 |
| -/// > |
379 |
| -/// > 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to |
380 |
| -/// > 1 set to zero. |
381 |
| -/// > |
382 |
| -/// > 8.1.3.6.2 If this form of length is used, then end-of-contents octets |
383 |
| -/// > (see 8.1.5) shall be present in the encoding following the contents |
384 |
| -/// > octets. |
385 |
| -/// > |
386 |
| -/// > [...] |
387 |
| -/// > |
388 |
| -/// > 8.1.5 End-of-contents octets |
389 |
| -/// > The end-of-contents octets shall be present if the length is encoded as specified in 8.1.3.6, |
390 |
| -/// > otherwise they shall not be present. |
391 |
| -/// > |
392 |
| -/// > The end-of-contents octets shall consist of two zero octets. |
393 |
| -/// |
394 |
| -/// This function decodes TLV records until it finds an end-of-contents marker (`00 00`), and |
395 |
| -/// computes the resulting length as the amount of data decoded. |
396 |
| -fn decode_indefinite_length<'a, R: Reader<'a>>(reader: &mut R) -> Result<Length> { |
397 |
| - /// The end-of-contents octets can be considered as the encoding of a value whose tag is |
398 |
| - /// universal class, whose form is primitive, whose number of the tag is zero, and whose |
399 |
| - /// contents are absent. |
400 |
| - const EOC_TAG: u8 = 0x00; |
401 |
| - |
402 |
| - let start_pos = reader.position(); |
403 |
| - |
404 |
| - loop { |
405 |
| - // Look for the end-of-contents marker |
406 |
| - if reader.peek_byte() == Some(EOC_TAG) { |
407 |
| - read_eoc(reader)?; |
408 |
| - |
409 |
| - // Compute how much we read and flag the decoded length as indefinite |
410 |
| - let mut ret = (reader.position() - start_pos)?; |
411 |
| - ret.indefinite = true; |
412 |
| - return Ok(ret); |
413 |
| - } |
414 |
| - |
415 |
| - let header = Header::decode(reader)?; |
416 |
| - reader.drain(header.length)?; |
417 |
| - } |
418 |
| -} |
419 |
| - |
420 |
| -/// Read an expected end-of-contents (EOC) marker: `00 00`. |
421 |
| -/// |
422 |
| -/// # Errors |
423 |
| -/// |
424 |
| -/// - Returns `ErrorKind::IndefiniteLength` if the EOC marker isn't present as expected. |
425 |
| -pub(crate) fn read_eoc<'a>(reader: &mut impl Reader<'a>) -> Result<()> { |
426 |
| - for _ in 0..Length::EOC_LEN.inner as usize { |
427 |
| - if reader.read_byte()? != 0 { |
428 |
| - return Err(reader.error(ErrorKind::IndefiniteLength)); |
429 |
| - } |
430 |
| - } |
431 |
| - |
432 |
| - Ok(()) |
433 |
| -} |
434 |
| - |
435 | 369 | #[cfg(test)]
|
436 | 370 | #[allow(clippy::unwrap_used)]
|
437 | 371 | mod tests {
|
438 | 372 | use super::Length;
|
439 |
| - use crate::{Decode, DerOrd, Encode, EncodingRules, ErrorKind, Reader, SliceReader, Tag}; |
| 373 | + use crate::{Decode, DerOrd, Encode, ErrorKind}; |
440 | 374 | use core::cmp::Ordering;
|
441 |
| - use hex_literal::hex; |
442 | 375 |
|
443 | 376 | #[test]
|
444 | 377 | fn decode() {
|
@@ -529,64 +462,4 @@ mod tests {
|
529 | 462 | Ordering::Greater
|
530 | 463 | );
|
531 | 464 | }
|
532 |
| - |
533 |
| - #[test] |
534 |
| - fn indefinite() { |
535 |
| - /// Length of example in octets. |
536 |
| - const EXAMPLE_LEN: usize = 68; |
537 |
| - |
538 |
| - /// Test vector from: <https://github.com/RustCrypto/formats/issues/779#issuecomment-2902948789> |
539 |
| - /// |
540 |
| - /// Notably this example contains nested indefinite lengths to ensure the decoder handles |
541 |
| - /// them correctly. |
542 |
| - const EXAMPLE_BER: [u8; EXAMPLE_LEN] = hex!( |
543 |
| - "30 80 06 09 2A 86 48 86 F7 0D 01 07 01 |
544 |
| - 30 1D 06 09 60 86 48 01 65 03 04 01 2A 04 10 37 |
545 |
| - 34 3D F1 47 0D F6 25 EE B6 F4 BF D2 F1 AC C3 A0 |
546 |
| - 80 04 10 CC 74 AD F6 5D 97 3C 8B 72 CD 51 E1 B9 |
547 |
| - 27 F0 F0 00 00 00 00" |
548 |
| - ); |
549 |
| - |
550 |
| - // Ensure the indefinite bit isn't set when decoding DER |
551 |
| - assert!(!Length::from_der(&[0x00]).unwrap().indefinite); |
552 |
| - |
553 |
| - let mut reader = |
554 |
| - SliceReader::new_with_encoding_rules(&EXAMPLE_BER, EncodingRules::Ber).unwrap(); |
555 |
| - |
556 |
| - // Decode initial tag of the message, leaving the reader at the length |
557 |
| - let tag = Tag::decode(&mut reader).unwrap(); |
558 |
| - assert_eq!(tag, Tag::Sequence); |
559 |
| - |
560 |
| - // Decode indefinite length |
561 |
| - let length = Length::decode(&mut reader).unwrap(); |
562 |
| - assert!(length.is_indefinite()); |
563 |
| - |
564 |
| - // Decoding the length should leave the position at the end of the indefinite length octet |
565 |
| - let pos = usize::try_from(reader.position()).unwrap(); |
566 |
| - assert_eq!(pos, 2); |
567 |
| - |
568 |
| - // The first two bytes are the header and the rest is the length of the message. |
569 |
| - // The last four are two end-of-content markers (2 * 2 bytes). |
570 |
| - assert_eq!(usize::try_from(length).unwrap(), EXAMPLE_LEN - pos); |
571 |
| - |
572 |
| - // Read OID |
573 |
| - reader.tlv_bytes().unwrap(); |
574 |
| - // Read SEQUENCE |
575 |
| - reader.tlv_bytes().unwrap(); |
576 |
| - |
577 |
| - // We're now at the next indefinite length record |
578 |
| - let tag = Tag::decode(&mut reader).unwrap(); |
579 |
| - assert_eq!( |
580 |
| - tag, |
581 |
| - Tag::ContextSpecific { |
582 |
| - constructed: true, |
583 |
| - number: 0u32.into() |
584 |
| - } |
585 |
| - ); |
586 |
| - |
587 |
| - // Parse the inner indefinite length |
588 |
| - let length = Length::decode(&mut reader).unwrap(); |
589 |
| - assert!(length.is_indefinite()); |
590 |
| - assert_eq!(usize::try_from(length).unwrap(), 20); |
591 |
| - } |
592 | 465 | }
|
0 commit comments