Skip to main content

structured_asn1/
value.rs

1//! The contents of primitive elements, read without copying them.
2//!
3//! Tags are deliberately not checked here. Implicit tagging replaces the tag of
4//! a value with the one its position gives it, so a `[0] IMPLICIT INTEGER` is
5//! still an integer and the caller is the only one who knows that. What is
6//! checked is the encoding of the value itself, which no amount of tagging
7//! changes.
8
9use crate::error::ErrorCode;
10use crate::length::Encoding;
11use crate::memory::{Memory, MemoryError, OwnedString};
12
13mod text;
14
15/// An object identifier, as the arcs are encoded, without the tag or length.
16///
17/// Held encoded rather than decoded because identity is the encoding: two
18/// identifiers are the same one when their bytes match, and comparing rendered
19/// text instead would make `1.2.840.113549` and a lookalike written with an
20/// arc padded to the same digits into the same identifier.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub struct Oid<'a>(&'a [u8]);
23
24impl<'a> Oid<'a> {
25    /// An identifier from written-out bytes, validated as it is built.
26    ///
27    /// For the constants a schema names. The same rules the document reader
28    /// enforces are held here by construction, so a table entry cannot name
29    /// something no document could: a malformed constant fails the build
30    /// during constant evaluation, and a malformed runtime call panics at
31    /// the constructor rather than printing nonsense later. Document bytes
32    /// never come through here; the parser validates them.
33    ///
34    /// # Panics
35    ///
36    /// When the bytes are not a well formed object identifier: empty, a
37    /// padded arc, or a truncated continuation. Width is not among them, as
38    /// it is not for a document: the encoding bounds no subidentifier
39    /// (X.690 8.19.2).
40    #[must_use]
41    pub const fn from_bytes(bytes: &'a [u8]) -> Self {
42        assert!(
43            Self::well_formed(bytes),
44            "not a well formed object identifier"
45        );
46        Self(bytes)
47    }
48
49    /// The validation the constructor asserts, mirroring the document
50    /// reader's rules in a form constant evaluation can run.
51    const fn well_formed(bytes: &[u8]) -> bool {
52        if bytes.is_empty() {
53            return false;
54        }
55        let mut starting = true;
56        let mut at = 0;
57        while at < bytes.len() {
58            let byte = bytes[at];
59            // A leading 0x80 pads the arc with a zero seven-bit group.
60            if starting && byte == 0x80 {
61                return false;
62            }
63            starting = byte & 0x80 == 0;
64            at += 1;
65        }
66        // The last byte asked for a continuation that never came.
67        starting
68    }
69
70    /// The encoded arcs.
71    #[must_use]
72    pub fn as_bytes(self) -> &'a [u8] {
73        self.0
74    }
75
76    /// Exact dotted-decimal text, admitting conversion work and storage in
77    /// the current execution domain. The result retains its capacity charge.
78    /// Width is unrestricted by ASN.1; insufficient resources return an error.
79    pub fn text(self, execution: &Memory) -> Result<OwnedString, MemoryError> {
80        text::oid(self, execution)
81    }
82
83    /// The arcs, root first.
84    ///
85    /// Constructing the iterator is constant work. Advancing it scans the
86    /// encoded groups of one subidentifier; the caller must admit that work
87    /// when iterating untrusted input. [`Self::text`] accounts for its traversal.
88    #[must_use]
89    pub fn arcs(self) -> Arcs<'a> {
90        Arcs {
91            bytes: self.0,
92            first: true,
93            pending: None,
94        }
95    }
96}
97
98/// One arc of an [`Oid`].
99///
100/// The encoding bounds no subidentifier (X.690 8.19.2), so an arc may be
101/// wider than any integer this crate names. Such an arc keeps the base-128
102/// groups it was written in, and the joint offset the first subidentifier
103/// carries, so it still prints the number the document holds instead of
104/// reporting some other one.
105#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub struct Arc<'a> {
107    /// The value, where it fits.
108    value: Option<u64>,
109    /// The groups it was written in, for one that does not.
110    groups: &'a [u8],
111    /// What the first subidentifier's packing adds to this arc: 0, 40 or 80
112    /// (X.690 8.19.4). Zero for every later arc.
113    offset: u64,
114}
115
116impl Arc<'_> {
117    /// Exact decimal text, with conversion and retained storage charged to
118    /// the current execution domain. No alternate-width rendering is used.
119    pub fn text(self, execution: &Memory) -> Result<OwnedString, MemoryError> {
120        text::arc(self, execution)
121    }
122
123    /// The arc where it fits sixty-four bits, and `None` where nothing that
124    /// wide could hold it. This accessor reads the already decoded value in
125    /// constant work; decoding occurred when the arcs iterator advanced.
126    #[must_use]
127    pub fn as_u64(self) -> Option<u64> {
128        self.value
129    }
130}
131
132/// The largest power of ten a remainder fits, and how many digits it writes.
133/// Dividing by this rather than by ten is what keeps the number of passes
134/// over the groups to a nineteenth of the digits.
135const DECIMAL_BLOCK: u128 = 10_000_000_000_000_000_000;
136const DECIMAL_BLOCK_DIGITS: usize = 19;
137
138/// An arc's base-128 groups with the joint offset already taken off, read
139/// where the document put them.
140///
141/// The offset comes off the least significant group, and where that group
142/// cannot pay it the borrow travels back through the zero groups above it
143/// (X.690 8.19.4). That is a suffix and nothing else, so which groups it
144/// changes is one index, found by a scan that copies nothing.
145struct Groups<'a> {
146    encoded: &'a [u8],
147    /// What the least significant group owes: 0, 40 or 80.
148    offset: u64,
149    /// The group the borrow reaches back to and stops at.
150    stop: usize,
151}
152
153impl<'a> Groups<'a> {
154    fn of(encoded: &'a [u8], offset: u64) -> Self {
155        let last = encoded.len() - 1;
156        let mut stop = last;
157        // The borrow cannot travel past the groups: an arc that is read here
158        // did not fit sixty-four bits, so it has more groups than the offset
159        // spans and the leading one is not zero.
160        while stop > 0 {
161            let owed = if stop == last { offset } else { 1 };
162            if u64::from(encoded[stop] & 0x7f) >= owed {
163                break;
164            }
165            stop -= 1;
166        }
167        Self {
168            encoded,
169            offset,
170            stop,
171        }
172    }
173
174    fn count(&self) -> usize {
175        self.encoded.len()
176    }
177
178    /// The groups from one position on, most significant first.
179    fn iter_from(&self, first: usize) -> impl ExactSizeIterator<Item = u8> + '_ {
180        (first..self.encoded.len()).map(|at| self.at(at))
181    }
182
183    /// The groups, most significant first.
184    fn iter(&self) -> impl ExactSizeIterator<Item = u8> + '_ {
185        self.iter_from(0)
186    }
187
188    /// How many groups the arc has once the leading zeros the borrow can
189    /// leave behind are dropped.
190    fn significant(&self) -> usize {
191        let leading = self.iter().take_while(|group| *group == 0).count();
192        self.encoded.len() - leading
193    }
194
195    fn at(&self, at: usize) -> u8 {
196        let last = self.encoded.len() - 1;
197        let group = u64::from(self.encoded[at] & 0x7f);
198        let owed = if at == last { self.offset } else { 1 };
199        let value = match at.cmp(&self.stop) {
200            core::cmp::Ordering::Less => group,
201            // The scan stopped here because this group can pay.
202            core::cmp::Ordering::Equal => group - owed,
203            // Above the group that pays, so this one lends and takes the
204            // base back.
205            core::cmp::Ordering::Greater => group + 128 - owed,
206        };
207        u8::try_from(value).expect("a group below the base")
208    }
209}
210
211/// The arcs of an [`Oid`], root first.
212#[derive(Debug, Clone)]
213pub struct Arcs<'a> {
214    bytes: &'a [u8],
215    first: bool,
216    pending: Option<Arc<'a>>,
217}
218
219impl<'a> Iterator for Arcs<'a> {
220    type Item = Arc<'a>;
221
222    fn next(&mut self) -> Option<Arc<'a>> {
223        if let Some(second) = self.pending.take() {
224            return Some(second);
225        }
226
227        // Accumulated wide so that a value one bit past the narrow width is
228        // still recognized as not fitting rather than wrapping. Wider than
229        // that keeps its groups: the last byte of the slice cannot ask for
230        // continuation, which was established when the identifier was read.
231        //
232        // Multiplied rather than shifted: a shift by seven is always a
233        // shift this type permits, so it reports nothing when the seven bits
234        // it drops were significant, and the arc would read as whatever
235        // survived. The multiplication answers about the value instead.
236        let mut value: Option<u128> = Some(0);
237        let mut taken = 0;
238        for byte in self.bytes {
239            taken += 1;
240            value = value
241                .and_then(|value| value.checked_mul(128)?.checked_add(u128::from(byte & 0x7f)));
242            if byte & 0x80 == 0 {
243                break;
244            }
245        }
246        let (groups, rest) = self.bytes.split_at(taken);
247        self.bytes = rest;
248        if taken == 0 {
249            return None;
250        }
251
252        let arc = |value: Option<u128>, offset: u64| Arc {
253            value: value.and_then(|value| u64::try_from(value - u128::from(offset)).ok()),
254            groups,
255            offset,
256        };
257        if self.first {
258            self.first = false;
259            // The first byte carries two arcs. Above 79 the root is 2 and the
260            // second arc continues past 39, which is how identifiers such as
261            // 2.999 are written. A value too wide to have been compared is
262            // above 79 either way: its groups reach past the root's own.
263            let root = match value {
264                Some(0..=39) => 0,
265                Some(40..=79) => 1,
266                _ => 2,
267            };
268            self.pending = Some(arc(value, root * 40));
269            return Some(Arc {
270                value: Some(root),
271                groups: &[],
272                offset: 0,
273            });
274        }
275
276        Some(arc(value, 0))
277    }
278}
279
280/// An integer, as its two's complement bytes.
281///
282/// Serial numbers reach twenty bytes and public key moduli are far larger, so
283/// this stays as it was encoded and converts on request.
284#[derive(Debug, Clone, Copy, PartialEq, Eq)]
285pub struct Integer<'a>(&'a [u8]);
286
287impl<'a> Integer<'a> {
288    /// The two's complement bytes, most significant first.
289    #[must_use]
290    pub fn as_bytes(self) -> &'a [u8] {
291        self.0
292    }
293
294    /// Whether the value is below zero.
295    #[must_use]
296    pub fn is_negative(self) -> bool {
297        self.0.first().is_some_and(|first| first & 0x80 != 0)
298    }
299
300    /// The value as an unsigned number, or `None` when it is negative or wider
301    /// than sixty-four bits.
302    #[must_use]
303    pub fn as_u64(self) -> Option<u64> {
304        if self.is_negative() {
305            return None;
306        }
307        // A leading zero is the sign byte of a value whose top bit is set, and
308        // carries no magnitude.
309        let magnitude = match self.0 {
310            [0x00, rest @ ..] => rest,
311            all => all,
312        };
313        if magnitude.len() > 8 {
314            return None;
315        }
316        Some(
317            magnitude
318                .iter()
319                .fold(0u64, |value, byte| (value << 8) | u64::from(*byte)),
320        )
321    }
322
323    /// The value as a signed number, or `None` when it is wider than
324    /// sixty-four bits.
325    #[must_use]
326    pub fn as_i64(self) -> Option<i64> {
327        if self.0.len() > 8 {
328            return None;
329        }
330        let sign = if self.is_negative() { -1i64 } else { 0 };
331        Some(
332            self.0
333                .iter()
334                .fold(sign, |value, byte| (value << 8) | i64::from(*byte)),
335        )
336    }
337
338    /// The value as a count, or `None` when it does not fit one.
339    #[must_use]
340    pub fn as_u32(self) -> Option<u32> {
341        self.as_u64().and_then(|value| u32::try_from(value).ok())
342    }
343}
344
345/// A string of bits, which is not the same as a string of bytes: the last byte
346/// may be partly padding, and a key usage of one bit occupies one of them.
347#[derive(Debug, Clone, Copy, PartialEq, Eq)]
348pub struct BitString<'a> {
349    bytes: &'a [u8],
350    unused: u8,
351}
352
353impl<'a> BitString<'a> {
354    /// The bytes holding the bits, padding included.
355    #[must_use]
356    pub fn as_bytes(self) -> &'a [u8] {
357        self.bytes
358    }
359
360    /// How many bits of the last byte are padding.
361    #[must_use]
362    pub fn unused_bits(self) -> u8 {
363        self.unused
364    }
365
366    /// How many bits the string holds.
367    #[must_use]
368    pub fn len(self) -> u64 {
369        // Every byte holds eight bits less whatever the last one pads, and the
370        // count of padding bits is below eight whenever the string is not
371        // empty, so neither the multiplication nor the subtraction can wrap.
372        (self.bytes.len() as u64) * 8 - u64::from(self.unused)
373    }
374
375    /// Whether the string holds no bits at all.
376    #[must_use]
377    pub fn is_empty(self) -> bool {
378        self.bytes.is_empty()
379    }
380
381    /// Whether the bit at `position` is set, counting from the first bit of the
382    /// first byte. Padding and anything past the end read as unset, which is
383    /// what a key usage shorter than the bit asked about means.
384    #[must_use]
385    pub fn bit(self, position: u64) -> bool {
386        if position >= self.len() {
387            return false;
388        }
389        // Below the bit count, so the byte it sits in exists and its index fits
390        // whatever a slice index is on this target.
391        let within = (position % 8) as u32;
392        usize::try_from(position / 8)
393            .ok()
394            .and_then(|byte| self.bytes.get(byte))
395            .is_some_and(|value| value & (0x80u8 >> within) != 0)
396    }
397
398    /// The bytes with the padding bits of the last one cleared, for a value
399    /// meant to be read as octets.
400    #[must_use]
401    pub fn octets(self) -> Option<&'a [u8]> {
402        (self.unused == 0).then_some(self.bytes)
403    }
404}
405
406/// Reads an object identifier's contents.
407pub(crate) fn oid(contents: &[u8]) -> Result<Oid<'_>, ErrorCode> {
408    if contents.is_empty() {
409        return Err(ErrorCode::MalformedOid);
410    }
411
412    // No arc is bounded here. The encoding bounds no subidentifier
413    // (X.690 8.19.2), so a width this reader cannot hold in an integer is
414    // still a number the document names: refusing it would abort a whole
415    // certificate over an arc that only ever gets printed. An arc past the
416    // integer keeps its groups and prints from them.
417    let mut starting = true;
418    for byte in contents {
419        // A leading 0x80 pads the arc with a zero seven-bit group, which is a
420        // second way to write a number that already has one.
421        if starting && *byte == 0x80 {
422            return Err(ErrorCode::MalformedOid);
423        }
424        starting = byte & 0x80 == 0;
425    }
426
427    // The last byte asked for a continuation that never came.
428    if !starting {
429        return Err(ErrorCode::MalformedOid);
430    }
431
432    Ok(Oid(contents))
433}
434
435/// Reads an integer's contents.
436pub(crate) fn integer(contents: &[u8]) -> Result<Integer<'_>, ErrorCode> {
437    match contents {
438        [] => Err(ErrorCode::IntegerEmpty),
439        // Both spellings write a value that one fewer byte already writes, and
440        // a signature computed over the bytes makes two spellings of one number
441        // into two documents.
442        [0x00, second, ..] if second & 0x80 == 0 => Err(ErrorCode::IntegerNotMinimal),
443        [0xff, second, ..] if second & 0x80 != 0 => Err(ErrorCode::IntegerNotMinimal),
444        _ => Ok(Integer(contents)),
445    }
446}
447
448/// Reads a bit string's contents.
449pub(crate) fn bit_string(contents: &[u8], encoding: Encoding) -> Result<BitString<'_>, ErrorCode> {
450    let (unused, bytes) = contents
451        .split_first()
452        .ok_or(ErrorCode::MalformedBitString)?;
453    let unused = *unused;
454
455    if unused > 7 || (bytes.is_empty() && unused != 0) {
456        return Err(ErrorCode::MalformedBitString);
457    }
458
459    // Padding that carries data is a place to put bytes that a reader ignoring
460    // them will not report, and DER settles it by requiring zeroes. BER does
461    // not: X.690 places the zero-padding rule in clause 11.2, among the
462    // restrictions that only CER and DER add, so a BER document with set
463    // padding bits is well formed and is read as it was written. The bits
464    // never reach a value either way: the length excludes them, asking for a
465    // bit inside them answers unset, and octets() refuses a padded string.
466    if encoding.is_der()
467        && unused > 0
468        && let Some(last) = bytes.last()
469        && last & (0xffu8 >> (8 - unused)) != 0
470    {
471        return Err(ErrorCode::MalformedBitString);
472    }
473
474    Ok(BitString { bytes, unused })
475}
476
477/// Reads a boolean's contents.
478pub(crate) fn boolean(contents: &[u8], encoding: Encoding) -> Result<bool, ErrorCode> {
479    match contents {
480        [0x00] => Ok(false),
481        [0xff] => Ok(true),
482        // BER lets any non-zero byte mean true. DER settles on one spelling,
483        // and accepting the others where a signature covers the bytes would
484        // make several documents into one.
485        [_] if !encoding.is_der() => Ok(true),
486        _ => Err(ErrorCode::MalformedBoolean),
487    }
488}
489
490/// Reads a real's contents, which the encoding settles down to the last
491/// octet (X.690 8.5) and the distinguished rules settle further (11.3).
492///
493/// Nothing here reads the number: no schema this product parses has a real
494/// in it, and one arrives only inside a value preserved for somebody else.
495/// What that somebody is promised is that the octets are a value of the type
496/// they claim, which is what this decides.
497pub(crate) fn real(contents: &[u8], encoding: Encoding) -> Result<(), ErrorCode> {
498    let Some((first, rest)) = contents.split_first() else {
499        // Plus zero is written with no contents octets at all (8.5.2).
500        return Ok(());
501    };
502    match first & 0xc0 {
503        // A special value or minus zero: one octet, and one of the four
504        // (8.5.9). The rest of that range is reserved.
505        0x40 => (rest.is_empty() && matches!(first, 0x40..=0x43))
506            .then_some(())
507            .ok_or(ErrorCode::MalformedReal),
508        // Decimal (8.5.8): the form octet names an ISO 6093 representation,
509        // and the octets after it are that representation.
510        0x00 => decimal_real(*first, rest, encoding),
511        // Binary (8.5.7): a sign, a base, a scaling factor and an exponent
512        // in the first octet, then the exponent and the mantissa.
513        _ => binary_real(*first, rest, encoding),
514    }
515}
516
517/// The decimal form of a real.
518fn decimal_real(first: u8, field: &[u8], encoding: Encoding) -> Result<(), ErrorCode> {
519    let malformed = || ErrorCode::MalformedReal;
520    // NR1, NR2 and NR3 are the three the encoding names; the rest of the
521    // range is reserved (8.5.8). The distinguished rules use NR3 alone
522    // (11.3.2.1).
523    let form = first & 0x3f;
524    if !matches!(form, 1..=3) || (encoding.is_der() && form != 3) {
525        return Err(malformed());
526    }
527    if !encoding.is_der() {
528        // Outside the distinguished rules the field is ISO 6093 as the
529        // sender chose to write it, and reading it is not this crate's
530        // business: what is checkable is that there is one.
531        return (!field.is_empty()).then_some(()).ok_or_else(malformed);
532    }
533
534    // NR3 as 11.3.2 writes it: an optional minus, the mantissa's digits, a
535    // full stop, the exponent mark, and the exponent. No space anywhere
536    // (11.3.2.2), a leading minus only where the value is negative
537    // (11.3.2.3), neither the first nor the last digit of the mantissa a
538    // zero (11.3.2.4), the stop immediately after that last digit
539    // (11.3.2.5), and a zero exponent written as `+0` with no other
540    // exponent signed or led by a zero (11.3.2.6).
541    let digits = field.strip_prefix(b"-").unwrap_or(field);
542    let (mantissa, exponent) = digits
543        .iter()
544        .position(|byte| *byte == b'.')
545        .map(|stop| digits.split_at(stop))
546        .ok_or_else(malformed)?;
547    let exponent = exponent.strip_prefix(b".E").ok_or_else(malformed)?;
548
549    let sound_mantissa = mantissa.first().is_some_and(|digit| *digit != b'0')
550        && mantissa.last().is_some_and(|digit| *digit != b'0')
551        && mantissa.iter().all(u8::is_ascii_digit);
552    let sound_exponent = exponent == b"+0"
553        || exponent
554            .strip_prefix(b"-")
555            .unwrap_or(exponent)
556            .split_first()
557            .is_some_and(|(lead, rest)| {
558                lead.is_ascii_digit() && *lead != b'0' && rest.iter().all(u8::is_ascii_digit)
559            });
560    (sound_mantissa && sound_exponent)
561        .then_some(())
562        .ok_or_else(malformed)
563}
564
565/// The binary form of a real.
566fn binary_real(first: u8, rest: &[u8], encoding: Encoding) -> Result<(), ErrorCode> {
567    let malformed = || ErrorCode::MalformedReal;
568    // The distinguished rules use base two and no scaling factor, and write
569    // both parts in the fewest octets (11.3.1). Base 11 is reserved in
570    // either encoding (8.5.7.2).
571    let base = (first >> 4) & 0x03;
572    let scaling = (first >> 2) & 0x03;
573    if base == 0x03 || (encoding.is_der() && (base != 0 || scaling != 0)) {
574        return Err(malformed());
575    }
576
577    // How the exponent is written: one, two or three octets, or a count and
578    // then that many (8.5.7.4).
579    let (exponent, mantissa) = match first & 0x03 {
580        0 => rest.split_at_checked(1),
581        1 => rest.split_at_checked(2),
582        2 => rest.split_at_checked(3),
583        _ => rest.split_first().and_then(|(count, after)| {
584            // At least one octet, and the count is not part of the number.
585            // Past three the selector cannot say the length itself, which is
586            // what this form is for; at three or fewer it spends an octet
587            // saying what a selector already says, and the distinguished
588            // rules ask for the fewest octets (11.3.1).
589            let shortest = !encoding.is_der() || *count > 3;
590            (*count >= 1 && shortest).then(|| after.split_at_checked(usize::from(*count)))?
591        }),
592    }
593    .ok_or_else(malformed)?;
594
595    // The first nine bits of an exponent written in more than one octet are
596    // neither all zeros nor all ones: that is what the long form says
597    // (8.5.7.4 d), and what writing it in the fewest octets means for the
598    // shorter forms too.
599    if let [lead, next, ..] = exponent {
600        let padded = *lead == 0x00 && next & 0x80 == 0;
601        let signed = *lead == 0xff && next & 0x80 != 0;
602        if padded || signed {
603            return Err(malformed());
604        }
605    }
606
607    // The mantissa is there, written in the fewest octets, and odd: the
608    // normalization shifts it until its least significant bit is one, and a
609    // mantissa of zero is written as the value zero instead (11.3.1).
610    match mantissa {
611        // There, and without a leading octet that adds nothing.
612        [] | [0x00, ..] => Err(malformed()),
613        [.., last] if encoding.is_der() && last & 0x01 == 0 => Err(malformed()),
614        _ => Ok(()),
615    }
616}
617
618/// Reads a null's contents, which are none.
619pub(crate) fn null(contents: &[u8]) -> Result<(), ErrorCode> {
620    if contents.is_empty() {
621        Ok(())
622    } else {
623        Err(ErrorCode::MalformedNull)
624    }
625}
626
627#[cfg(test)]
628mod tests;