webpki/
der.rs

1// Copyright 2015 Brian Smith.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15use crate::{calendar, time, Error};
16pub(crate) use ring::io::der::{CONSTRUCTED, CONTEXT_SPECIFIC};
17
18// Copied (and extended) from ring's src/der.rs
19#[allow(clippy::upper_case_acronyms)]
20#[derive(Clone, Copy, Eq, PartialEq)]
21#[repr(u8)]
22pub(crate) enum Tag {
23    Boolean = 0x01,
24    Integer = 0x02,
25    BitString = 0x03,
26    OctetString = 0x04,
27    OID = 0x06,
28    Enum = 0x0A,
29    Sequence = CONSTRUCTED | 0x10, // 0x30
30    UTCTime = 0x17,
31    GeneralizedTime = 0x18,
32
33    #[allow(clippy::identity_op)]
34    ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0,
35    ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1,
36    ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3,
37}
38
39impl From<Tag> for usize {
40    #[allow(clippy::as_conversions)]
41    fn from(tag: Tag) -> Self {
42        tag as Self
43    }
44}
45
46impl From<Tag> for u8 {
47    #[allow(clippy::as_conversions)]
48    fn from(tag: Tag) -> Self {
49        tag as Self
50    } // XXX: narrowing conversion.
51}
52
53#[inline(always)]
54pub(crate) fn expect_tag_and_get_value<'a>(
55    input: &mut untrusted::Reader<'a>,
56    tag: Tag,
57) -> Result<untrusted::Input<'a>, Error> {
58    let (actual_tag, inner) = read_tag_and_get_value(input)?;
59    if usize::from(tag) != usize::from(actual_tag) {
60        return Err(Error::BadDer);
61    }
62    Ok(inner)
63}
64
65#[inline(always)]
66pub(crate) fn expect_tag_and_get_value_limited<'a>(
67    input: &mut untrusted::Reader<'a>,
68    tag: Tag,
69    size_limit: usize,
70) -> Result<untrusted::Input<'a>, Error> {
71    let (actual_tag, inner) = read_tag_and_get_value_limited(input, size_limit)?;
72    if usize::from(tag) != usize::from(actual_tag) {
73        return Err(Error::BadDer);
74    }
75    Ok(inner)
76}
77
78pub(crate) fn nested_limited<'a, R, E: Copy>(
79    input: &mut untrusted::Reader<'a>,
80    tag: Tag,
81    error: E,
82    decoder: impl FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
83    size_limit: usize,
84) -> Result<R, E> {
85    expect_tag_and_get_value_limited(input, tag, size_limit)
86        .map_err(|_| error)?
87        .read_all(error, decoder)
88}
89
90// TODO: investigate taking decoder as a reference to reduce generated code
91// size.
92pub(crate) fn nested<'a, R, E: Copy>(
93    input: &mut untrusted::Reader<'a>,
94    tag: Tag,
95    error: E,
96    decoder: impl FnOnce(&mut untrusted::Reader<'a>) -> Result<R, E>,
97) -> Result<R, E> {
98    nested_limited(input, tag, error, decoder, TWO_BYTE_DER_SIZE)
99}
100
101pub(crate) struct Value<'a> {
102    value: untrusted::Input<'a>,
103}
104
105impl<'a> Value<'a> {
106    pub(crate) fn value(&self) -> untrusted::Input<'a> {
107        self.value
108    }
109}
110
111pub(crate) fn expect_tag<'a>(
112    input: &mut untrusted::Reader<'a>,
113    tag: Tag,
114) -> Result<Value<'a>, Error> {
115    let (actual_tag, value) = read_tag_and_get_value(input)?;
116    if usize::from(tag) != usize::from(actual_tag) {
117        return Err(Error::BadDer);
118    }
119
120    Ok(Value { value })
121}
122
123#[inline(always)]
124pub(crate) fn read_tag_and_get_value<'a>(
125    input: &mut untrusted::Reader<'a>,
126) -> Result<(u8, untrusted::Input<'a>), Error> {
127    read_tag_and_get_value_limited(input, TWO_BYTE_DER_SIZE)
128}
129
130#[inline(always)]
131pub(crate) fn read_tag_and_get_value_limited<'a>(
132    input: &mut untrusted::Reader<'a>,
133    size_limit: usize,
134) -> Result<(u8, untrusted::Input<'a>), Error> {
135    let tag = input.read_byte()?;
136    if (tag & HIGH_TAG_RANGE_START) == HIGH_TAG_RANGE_START {
137        return Err(Error::BadDer); // High tag number form is not allowed.
138    }
139
140    // If the high order bit of the first byte is set to zero then the length
141    // is encoded in the seven remaining bits of that byte. Otherwise, those
142    // seven bits represent the number of bytes used to encode the length.
143    let length = match input.read_byte()? {
144        n if (n & SHORT_FORM_LEN_MAX) == 0 => usize::from(n),
145        LONG_FORM_LEN_ONE_BYTE => {
146            let length_byte = input.read_byte()?;
147            if length_byte < SHORT_FORM_LEN_MAX {
148                return Err(Error::BadDer); // Not the canonical encoding.
149            }
150            usize::from(length_byte)
151        }
152        LONG_FORM_LEN_TWO_BYTES => {
153            let length_byte_one = usize::from(input.read_byte()?);
154            let length_byte_two = usize::from(input.read_byte()?);
155            let combined = (length_byte_one << 8) | length_byte_two;
156            if combined <= LONG_FORM_LEN_ONE_BYTE_MAX {
157                return Err(Error::BadDer); // Not the canonical encoding.
158            }
159            combined
160        }
161        LONG_FORM_LEN_THREE_BYTES => {
162            let length_byte_one = usize::from(input.read_byte()?);
163            let length_byte_two = usize::from(input.read_byte()?);
164            let length_byte_three = usize::from(input.read_byte()?);
165            let combined = (length_byte_one << 16) | (length_byte_two << 8) | length_byte_three;
166            if combined <= LONG_FORM_LEN_TWO_BYTES_MAX {
167                return Err(Error::BadDer); // Not the canonical encoding.
168            }
169            combined
170        }
171        LONG_FORM_LEN_FOUR_BYTES => {
172            let length_byte_one = usize::from(input.read_byte()?);
173            let length_byte_two = usize::from(input.read_byte()?);
174            let length_byte_three = usize::from(input.read_byte()?);
175            let length_byte_four = usize::from(input.read_byte()?);
176            let combined = (length_byte_one << 24)
177                | (length_byte_two << 16)
178                | (length_byte_three << 8)
179                | length_byte_four;
180            if combined <= LONG_FORM_LEN_THREE_BYTES_MAX {
181                return Err(Error::BadDer); // Not the canonical encoding.
182            }
183            combined
184        }
185        _ => {
186            return Err(Error::BadDer); // We don't support longer lengths.
187        }
188    };
189
190    if length >= size_limit {
191        return Err(Error::BadDer); // The length is larger than the caller accepts.
192    }
193
194    let inner = input.read_bytes(length)?;
195    Ok((tag, inner))
196}
197
198// Long-form DER encoded lengths of two bytes can express lengths up to the following limit.
199//
200// The upstream ring::io::der::read_tag_and_get_value() function limits itself to up to two byte
201// long-form DER lengths, and so this limit represents the maximum length that was possible to
202// read before the introduction of the read_tag_and_get_value_limited function.
203pub(crate) const TWO_BYTE_DER_SIZE: usize = LONG_FORM_LEN_TWO_BYTES_MAX;
204
205// The maximum size of a DER value that Webpki can support reading.
206//
207// Webpki limits itself to four byte long-form DER lengths, and so this limit represents
208// the maximum size tagged DER value that can be read for any purpose.
209pub(crate) const MAX_DER_SIZE: usize = LONG_FORM_LEN_FOUR_BYTES_MAX;
210
211// DER Tag identifiers have two forms:
212// * Low tag number form (for tags values in the range [0..30]
213// * High tag number form (for tag values in the range [31..]
214// We only support low tag number form.
215const HIGH_TAG_RANGE_START: u8 = 31;
216
217// DER length octets have two forms:
218// * Short form: 1 octet supporting lengths between 0 and 127.
219// * Long definite form: 2 to 127 octets, number of octets encoded into first octet.
220const SHORT_FORM_LEN_MAX: u8 = 128;
221
222// Leading octet for long definite form DER length expressed in second byte.
223const LONG_FORM_LEN_ONE_BYTE: u8 = 0x81;
224
225// Maximum size that can be expressed in a one byte long form len.
226const LONG_FORM_LEN_ONE_BYTE_MAX: usize = 0xff;
227
228// Leading octet for long definite form DER length expressed in subsequent two bytes.
229const LONG_FORM_LEN_TWO_BYTES: u8 = 0x82;
230
231// Maximum size that can be expressed in a two byte long form len.
232const LONG_FORM_LEN_TWO_BYTES_MAX: usize = 0xff_ff;
233
234// Leading octet for long definite form DER length expressed in subsequent three bytes.
235const LONG_FORM_LEN_THREE_BYTES: u8 = 0x83;
236
237// Maximum size that can be expressed in a three byte long form len.
238const LONG_FORM_LEN_THREE_BYTES_MAX: usize = 0xff_ff_ff;
239
240// Leading octet for long definite form DER length expressed in subsequent four bytes.
241const LONG_FORM_LEN_FOUR_BYTES: u8 = 0x84;
242
243// Maximum size that can be expressed in a four byte long form der len.
244const LONG_FORM_LEN_FOUR_BYTES_MAX: usize = 0xff_ff_ff_ff;
245
246// TODO: investigate taking decoder as a reference to reduce generated code
247// size.
248pub(crate) fn nested_of_mut<'a, E>(
249    input: &mut untrusted::Reader<'a>,
250    outer_tag: Tag,
251    inner_tag: Tag,
252    error: E,
253    mut decoder: impl FnMut(&mut untrusted::Reader<'a>) -> Result<(), E>,
254) -> Result<(), E>
255where
256    E: Copy,
257{
258    nested(input, outer_tag, error, |outer| {
259        loop {
260            nested(outer, inner_tag, error, |inner| decoder(inner))?;
261            if outer.at_end() {
262                break;
263            }
264        }
265        Ok(())
266    })
267}
268
269pub(crate) fn bit_string_with_no_unused_bits<'a>(
270    input: &mut untrusted::Reader<'a>,
271) -> Result<untrusted::Input<'a>, Error> {
272    nested(input, Tag::BitString, Error::BadDer, |value| {
273        let unused_bits_at_end = value.read_byte().map_err(|_| Error::BadDer)?;
274        if unused_bits_at_end != 0 {
275            return Err(Error::BadDer);
276        }
277        Ok(value.read_bytes_to_end())
278    })
279}
280
281pub(crate) struct BitStringFlags<'a> {
282    raw_bits: &'a [u8],
283}
284
285impl<'a> BitStringFlags<'a> {
286    pub(crate) fn bit_set(&self, bit: usize) -> bool {
287        let byte_index = bit / 8;
288        let bit_shift = 7 - (bit % 8);
289
290        if self.raw_bits.len() < (byte_index + 1) {
291            false
292        } else {
293            ((self.raw_bits[byte_index] >> bit_shift) & 1) != 0
294        }
295    }
296}
297
298// ASN.1 BIT STRING fields for sets of flags are encoded in DER with some peculiar details related
299// to padding. Notably this means we expect a Tag::BitString, a length, an indicator of the number
300// of bits of padding, and then the actual bit values. See this Stack Overflow discussion[0], and
301// ITU X690-0207[1] Section 8.6 and Section 11.2 for more information.
302//
303// [0]: https://security.stackexchange.com/a/10396
304// [1]: https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
305pub(crate) fn bit_string_flags<'a>(
306    input: &mut untrusted::Reader<'a>,
307) -> Result<BitStringFlags<'a>, Error> {
308    expect_tag_and_get_value(input, Tag::BitString)?.read_all(Error::BadDer, |bit_string| {
309        // ITU X690-0207 11.2:
310        //   "The initial octet shall encode, as an unsigned binary integer with bit 1 as the least
311        //   significant bit, the number of unused bits in the final subsequent octet.
312        //   The number shall be in the range zero to seven"
313        let padding_bits = bit_string.read_byte().map_err(|_| Error::BadDer)?;
314        let raw_bits = bit_string.read_bytes_to_end().as_slice_less_safe();
315
316        // It's illegal to have more than 7 bits of padding. Similarly, if the raw bitflags
317        // are empty there should be no padding.
318        if padding_bits > 7 || (raw_bits.is_empty() && padding_bits != 0) {
319            return Err(Error::BadDer);
320        }
321
322        // If there are padding bits then the last bit of the last raw byte must be 0 or the
323        // distinguished encoding rules are not being followed.
324        let last_byte = raw_bits[raw_bits.len() - 1];
325        let padding_mask = (1 << padding_bits) - 1;
326
327        match padding_bits > 0 && (last_byte & padding_mask) != 0 {
328            true => Err(Error::BadDer),
329            false => Ok(BitStringFlags { raw_bits }),
330        }
331    })
332}
333
334// Like mozilla::pkix, we accept the nonconformant explicit encoding of
335// the default value (false) for compatibility with real-world certificates.
336pub(crate) fn optional_boolean(input: &mut untrusted::Reader) -> Result<bool, Error> {
337    if !input.peek(Tag::Boolean.into()) {
338        return Ok(false);
339    }
340    nested(input, Tag::Boolean, Error::BadDer, |input| {
341        match input.read_byte() {
342            Ok(0xff) => Ok(true),
343            Ok(0x00) => Ok(false),
344            _ => Err(Error::BadDer),
345        }
346    })
347}
348
349pub(crate) fn small_nonnegative_integer(input: &mut untrusted::Reader) -> Result<u8, Error> {
350    ring::io::der::small_nonnegative_integer(input).map_err(|_| Error::BadDer)
351}
352
353pub(crate) fn time_choice(input: &mut untrusted::Reader) -> Result<time::Time, Error> {
354    let is_utc_time = input.peek(Tag::UTCTime.into());
355    let expected_tag = if is_utc_time {
356        Tag::UTCTime
357    } else {
358        Tag::GeneralizedTime
359    };
360
361    fn read_digit(inner: &mut untrusted::Reader) -> Result<u64, Error> {
362        const DIGIT: core::ops::RangeInclusive<u8> = b'0'..=b'9';
363        let b = inner.read_byte().map_err(|_| Error::BadDerTime)?;
364        if DIGIT.contains(&b) {
365            return Ok(u64::from(b - DIGIT.start()));
366        }
367        Err(Error::BadDerTime)
368    }
369
370    fn read_two_digits(inner: &mut untrusted::Reader, min: u64, max: u64) -> Result<u64, Error> {
371        let hi = read_digit(inner)?;
372        let lo = read_digit(inner)?;
373        let value = (hi * 10) + lo;
374        if value < min || value > max {
375            return Err(Error::BadDerTime);
376        }
377        Ok(value)
378    }
379
380    nested(input, expected_tag, Error::BadDer, |value| {
381        let (year_hi, year_lo) = if is_utc_time {
382            let lo = read_two_digits(value, 0, 99)?;
383            let hi = if lo >= 50 { 19 } else { 20 };
384            (hi, lo)
385        } else {
386            let hi = read_two_digits(value, 0, 99)?;
387            let lo = read_two_digits(value, 0, 99)?;
388            (hi, lo)
389        };
390
391        let year = (year_hi * 100) + year_lo;
392        let month = read_two_digits(value, 1, 12)?;
393        let days_in_month = calendar::days_in_month(year, month);
394        let day_of_month = read_two_digits(value, 1, days_in_month)?;
395        let hours = read_two_digits(value, 0, 23)?;
396        let minutes = read_two_digits(value, 0, 59)?;
397        let seconds = read_two_digits(value, 0, 59)?;
398
399        let time_zone = value.read_byte().map_err(|_| Error::BadDerTime)?;
400        if time_zone != b'Z' {
401            return Err(Error::BadDerTime);
402        }
403
404        calendar::time_from_ymdhms_utc(year, month, day_of_month, hours, minutes, seconds)
405    })
406}
407
408macro_rules! oid {
409    ( $first:expr, $second:expr, $( $tail:expr ),* ) =>
410    (
411        [(40 * $first) + $second, $( $tail ),*]
412    )
413}
414
415#[cfg(test)]
416mod tests {
417    #[test]
418    fn test_optional_boolean() {
419        use super::{optional_boolean, Error};
420
421        // Empty input results in false
422        assert!(!optional_boolean(&mut bytes_reader(&[])).unwrap());
423
424        // Optional, so another data type results in false
425        assert!(!optional_boolean(&mut bytes_reader(&[0x05, 0x00])).unwrap());
426
427        // Only 0x00 and 0xff are accepted values
428        assert_eq!(
429            optional_boolean(&mut bytes_reader(&[0x01, 0x01, 0x42])).unwrap_err(),
430            Error::BadDer,
431        );
432
433        // True
434        assert!(optional_boolean(&mut bytes_reader(&[0x01, 0x01, 0xff])).unwrap());
435
436        // False
437        assert!(!optional_boolean(&mut bytes_reader(&[0x01, 0x01, 0x00])).unwrap());
438    }
439
440    #[test]
441    fn test_bit_string_with_no_unused_bits() {
442        use super::{bit_string_with_no_unused_bits, Error};
443
444        // Unexpected type
445        assert_eq!(
446            bit_string_with_no_unused_bits(&mut bytes_reader(&[0x01, 0x01, 0xff])).unwrap_err(),
447            Error::BadDer,
448        );
449
450        // Unexpected nonexistent type
451        assert_eq!(
452            bit_string_with_no_unused_bits(&mut bytes_reader(&[0x42, 0xff, 0xff])).unwrap_err(),
453            Error::BadDer,
454        );
455
456        // Unexpected empty input
457        assert_eq!(
458            bit_string_with_no_unused_bits(&mut bytes_reader(&[])).unwrap_err(),
459            Error::BadDer,
460        );
461
462        // Valid input with non-zero unused bits
463        assert_eq!(
464            bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x04, 0x12, 0x34]))
465                .unwrap_err(),
466            Error::BadDer,
467        );
468
469        // Valid input
470        assert_eq!(
471            bit_string_with_no_unused_bits(&mut bytes_reader(&[0x03, 0x03, 0x00, 0x12, 0x34]))
472                .unwrap()
473                .as_slice_less_safe(),
474            &[0x12, 0x34],
475        );
476    }
477
478    fn bytes_reader(bytes: &[u8]) -> untrusted::Reader {
479        return untrusted::Reader::new(untrusted::Input::from(bytes));
480    }
481
482    #[test]
483    fn read_tag_and_get_value_default_limit() {
484        use super::{read_tag_and_get_value, Error};
485
486        let inputs = &[
487            // DER with short-form length encoded as three bytes.
488            &[EXAMPLE_TAG, 0x83, 0xFF, 0xFF, 0xFF].as_slice(),
489            // DER with short-form length encoded as four bytes.
490            &[EXAMPLE_TAG, 0x84, 0xFF, 0xFF, 0xFF, 0xFF].as_slice(),
491        ];
492
493        for input in inputs {
494            let mut bytes = untrusted::Reader::new(untrusted::Input::from(input));
495            // read_tag_and_get_value should reject DER with encoded lengths larger than two
496            // bytes as BadDer.
497            assert!(matches!(
498                read_tag_and_get_value(&mut bytes),
499                Err(Error::BadDer)
500            ));
501        }
502    }
503
504    #[test]
505    fn read_tag_and_get_value_limited_high_form() {
506        use super::{read_tag_and_get_value_limited, Error, LONG_FORM_LEN_TWO_BYTES_MAX};
507
508        let mut bytes = untrusted::Reader::new(untrusted::Input::from(&[0xFF]));
509        // read_tag_and_get_value_limited_high_form should reject DER with "high tag number form" tags.
510        assert!(matches!(
511            read_tag_and_get_value_limited(&mut bytes, LONG_FORM_LEN_TWO_BYTES_MAX),
512            Err(Error::BadDer)
513        ));
514    }
515
516    #[test]
517    fn read_tag_and_get_value_limited_non_canonical() {
518        use super::{read_tag_and_get_value_limited, Error, LONG_FORM_LEN_TWO_BYTES_MAX};
519
520        let inputs = &[
521            // Two byte length, with expressed length < 128.
522            &[EXAMPLE_TAG, 0x81, 0x01].as_slice(),
523            // Three byte length, with expressed length < 256.
524            &[EXAMPLE_TAG, 0x82, 0x00, 0x01].as_slice(),
525            // Four byte length, with expressed length, < 65536.
526            &[EXAMPLE_TAG, 0x83, 0x00, 0x00, 0x01].as_slice(),
527            // Five byte length, with expressed length < 16777216.
528            &[EXAMPLE_TAG, 0x84, 0x00, 0x00, 0x00, 0x01].as_slice(),
529        ];
530
531        for input in inputs {
532            let mut bytes = untrusted::Reader::new(untrusted::Input::from(input));
533            // read_tag_and_get_value_limited should reject DER with non-canonical lengths.
534            assert!(matches!(
535                read_tag_and_get_value_limited(&mut bytes, LONG_FORM_LEN_TWO_BYTES_MAX),
536                Err(Error::BadDer)
537            ));
538        }
539    }
540
541    #[test]
542    #[cfg(feature = "alloc")]
543    fn read_tag_and_get_value_limited_limits() {
544        use super::{read_tag_and_get_value_limited, Error};
545
546        let short_input = &[0xFF];
547        let short_input_encoded = &[
548            &[EXAMPLE_TAG],
549            der_encode_length(short_input.len()).as_slice(),
550            short_input,
551        ]
552        .concat();
553
554        let long_input = &[1_u8; 65537];
555        let long_input_encoded = &[
556            &[EXAMPLE_TAG],
557            der_encode_length(long_input.len()).as_slice(),
558            long_input,
559        ]
560        .concat();
561
562        struct Testcase<'a> {
563            input: &'a [u8],
564            limit: usize,
565            err: Option<Error>,
566        }
567
568        let testcases = &[
569            Testcase {
570                input: short_input_encoded,
571                limit: 1,
572                err: Some(Error::BadDer),
573            },
574            Testcase {
575                input: short_input_encoded,
576                limit: short_input_encoded.len() + 1,
577                err: None,
578            },
579            Testcase {
580                input: long_input_encoded,
581                limit: long_input.len(),
582                err: Some(Error::BadDer),
583            },
584            Testcase {
585                input: long_input_encoded,
586                limit: long_input.len() + 1,
587                err: None,
588            },
589        ];
590
591        for tc in testcases {
592            let mut bytes = untrusted::Reader::new(untrusted::Input::from(tc.input));
593
594            let res = read_tag_and_get_value_limited(&mut bytes, tc.limit);
595            match tc.err {
596                None => assert!(res.is_ok()),
597                Some(e) => {
598                    let actual = res.unwrap_err();
599                    assert_eq!(actual, e)
600                }
601            }
602        }
603    }
604
605    #[allow(clippy::as_conversions)] // infallible.
606    const EXAMPLE_TAG: u8 = super::Tag::Sequence as u8;
607
608    #[cfg(feature = "alloc")]
609    #[allow(clippy::as_conversions)] // test code.
610    fn der_encode_length(length: usize) -> Vec<u8> {
611        if length < 128 {
612            vec![length as u8]
613        } else {
614            let mut encoded: Vec<u8> = Vec::new();
615            let mut remaining_length = length;
616
617            while remaining_length > 0 {
618                let byte = (remaining_length & 0xFF) as u8;
619                encoded.insert(0, byte);
620                remaining_length >>= 8;
621            }
622
623            let length_octet = encoded.len() as u8 | 0x80;
624            encoded.insert(0, length_octet);
625
626            encoded
627        }
628    }
629
630    #[allow(clippy::as_conversions)] // infallible.
631    const BITSTRING_TAG: u8 = super::Tag::BitString as u8;
632
633    #[test]
634    fn misencoded_bit_string_flags() {
635        use super::{bit_string_flags, Error};
636
637        let mut bad_padding_example = untrusted::Reader::new(untrusted::Input::from(&[
638            BITSTRING_TAG, // BitString
639            0x2,           // 2 bytes of content.
640            0x08,          // 8 bit of padding (illegal!).
641            0x06,          // 1 byte of bit flags asserting bits 5 and 6.
642        ]));
643        assert!(matches!(
644            bit_string_flags(&mut bad_padding_example),
645            Err(Error::BadDer)
646        ));
647
648        let mut bad_padding_example = untrusted::Reader::new(untrusted::Input::from(&[
649            BITSTRING_TAG, // BitString
650            0x2,           // 2 bytes of content.
651            0x01,          // 1 bit of padding.
652                           // No flags value (illegal with padding!).
653        ]));
654        assert!(matches!(
655            bit_string_flags(&mut bad_padding_example),
656            Err(Error::BadDer)
657        ));
658
659        let mut trailing_zeroes = untrusted::Reader::new(untrusted::Input::from(&[
660            BITSTRING_TAG, // BitString
661            0x2,           // 2 bytes of content.
662            0x01,          // 1 bit of padding.
663            0xFF,          // Flag data with
664            0x00,          // trailing zeros.
665        ]));
666        assert!(matches!(
667            bit_string_flags(&mut trailing_zeroes),
668            Err(Error::BadDer)
669        ))
670    }
671
672    #[test]
673    fn valid_bit_string_flags() {
674        use super::bit_string_flags;
675
676        let mut example_key_usage = untrusted::Reader::new(untrusted::Input::from(&[
677            BITSTRING_TAG, // BitString
678            0x2,           // 2 bytes of content.
679            0x01,          // 1 bit of padding.
680            0x06,          // 1 byte of bit flags asserting bits 5 and 6.
681        ]));
682        let res = bit_string_flags(&mut example_key_usage).unwrap();
683
684        assert!(!res.bit_set(0));
685        assert!(!res.bit_set(1));
686        assert!(!res.bit_set(2));
687        assert!(!res.bit_set(3));
688        assert!(!res.bit_set(4));
689        // NB: Bits 5 and 6 should be set.
690        assert!(res.bit_set(5));
691        assert!(res.bit_set(6));
692        assert!(!res.bit_set(7));
693        assert!(!res.bit_set(8));
694        // Bits outside the range of values shouldn't be considered set.
695        assert!(!res.bit_set(256));
696    }
697}