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