Skip to main content

structured_pkix/
usage.rs

1//! What a key may be used for.
2
3use crate::error::{Error, ErrorCode, Located, Result};
4use crate::extension::{self, Extension};
5use structured_asn1::memory::{Memory, OwnedVec, Work};
6use structured_asn1::{BitString, Element, Oid, Reader, Tag, universal};
7
8/// The purposes a key may be used for, as the bits the certificate set.
9#[derive(Debug, Clone, Copy)]
10pub struct KeyUsage<'a> {
11    bits: BitString<'a>,
12}
13
14impl<'a> KeyUsage<'a> {
15    /// Signing data.
16    #[must_use]
17    pub fn digital_signature(self) -> bool {
18        self.bits.bit(0)
19    }
20
21    /// Signing in a way the signer is not meant to be able to deny later,
22    /// which is the bit a signature under the Regulation rests on.
23    #[must_use]
24    pub fn content_commitment(self) -> bool {
25        self.bits.bit(1)
26    }
27
28    /// Enciphering a key.
29    #[must_use]
30    pub fn key_encipherment(self) -> bool {
31        self.bits.bit(2)
32    }
33
34    /// Enciphering data directly.
35    #[must_use]
36    pub fn data_encipherment(self) -> bool {
37        self.bits.bit(3)
38    }
39
40    /// Agreeing a key.
41    #[must_use]
42    pub fn key_agreement(self) -> bool {
43        self.bits.bit(4)
44    }
45
46    /// Signing certificates, which is what makes a certification authority
47    /// one.
48    #[must_use]
49    pub fn key_cert_sign(self) -> bool {
50        self.bits.bit(5)
51    }
52
53    /// Signing revocation lists.
54    #[must_use]
55    pub fn crl_sign(self) -> bool {
56        self.bits.bit(6)
57    }
58
59    /// Enciphering only, which means something only alongside key agreement.
60    #[must_use]
61    pub fn encipher_only(self) -> bool {
62        self.bits.bit(7)
63    }
64
65    /// Deciphering only, on the same terms.
66    #[must_use]
67    pub fn decipher_only(self) -> bool {
68        self.bits.bit(8)
69    }
70
71    /// The bits as they were written, for a report that has to say what a
72    /// certificate carries rather than what it means.
73    #[must_use]
74    pub fn bits(self) -> BitString<'a> {
75        self.bits
76    }
77
78    /// Reads the value of a key usage extension.
79    pub fn read(extension: &Extension<'a>, execution: &Memory) -> Result<Self> {
80        const FIELD: &str = "extensions.keyUsage";
81        let fail = |code| Error::new(code, FIELD, extension.span().start);
82
83        let mut reader = extension.reader(execution).field(FIELD)?;
84        let bits = reader.read_bit_string().field(FIELD)?;
85        if !reader.is_empty() {
86            return Err(fail(ErrorCode::TrailingData));
87        }
88
89        // The zero walk below touches every content byte, so it is charged
90        // to the shared work budget first: a caller bounding work must see
91        // an oversized string's scan on the same meter the reads use.
92        reader.charge(bits.as_bytes().len() as u64).field(FIELD)?;
93
94        // A key usage with no bit set forbids every use while claiming to
95        // permit one, and the schema asks for at least one. Written as a
96        // string of zero bits or as zero bytes, it says the same nothing.
97        if bits.as_bytes().iter().all(|byte| *byte == 0) {
98            return Err(fail(ErrorCode::MalformedValue));
99        }
100
101        // DER trims a named bit list to its last set bit, so trailing zero
102        // bits are a second spelling of a shorter value; and a set bit past
103        // decipherOnly is a bit this schema gives no name. BER carries no
104        // trimming rule, and past-the-end bits there read as unset.
105        if reader.encoding().is_der() {
106            let length = bits.len();
107            if !bits.bit(length - 1) {
108                return Err(fail(ErrorCode::MalformedValue));
109            }
110            if length > 9 {
111                return Err(fail(ErrorCode::MalformedValue));
112            }
113        }
114
115        let usage = Self { bits };
116        // The meaning of encipherOnly and decipherOnly is undefined in the
117        // absence of the keyAgreement bit (RFC 5280 4.2.1.3): a bit with no
118        // defined meaning cannot be read as permitting anything.
119        if (usage.encipher_only() || usage.decipher_only()) && !usage.key_agreement() {
120            return Err(fail(ErrorCode::MalformedValue));
121        }
122        Ok(usage)
123    }
124}
125
126/// Further purposes, named by identifier rather than by bit.
127#[derive(Debug)]
128pub struct ExtendedKeyUsage<'a> {
129    purposes: OwnedVec<Oid<'a>>,
130    at: u64,
131}
132
133impl<'a> ExtendedKeyUsage<'a> {
134    /// Reads an original EKU SEQUENCE using its producing reader and depth.
135    /// No certificate reconstruction or replacement parser is needed.
136    /// The returned catalogue retains its allocation charge; temporary lookup
137    /// storage is released before return. All decoding and storage work uses
138    /// the producing reader's local and aggregate execution bounds.
139    ///
140    /// # Errors
141    /// Returns malformed or empty EKU syntax, inherited depth refusal, or a
142    /// located resource error before unfunded catalogue growth or copying.
143    pub fn read_value(parent: &Reader<'a>, value: &Element<'a>) -> Result<Self> {
144        const FIELD: &str = "extensions.extKeyUsage";
145        let fail = |code| Error::new(code, FIELD, value.span().start);
146        if value.tag() != Tag::constructed(universal::SEQUENCE) {
147            return Err(fail(ErrorCode::Encoding(
148                structured_asn1::ErrorCode::UnexpectedTag,
149            )));
150        }
151        Self::read_members(
152            parent.enter(value).field(FIELD)?,
153            parent.memory(),
154            value.span().start,
155        )
156    }
157
158    fn read_members(mut inside: Reader<'a>, execution: &Memory, at: u64) -> Result<Self> {
159        const FIELD: &str = "extensions.extKeyUsage";
160        let work = inside.execution_in(execution);
161        let mut purposes = work.vector();
162        let mut seen = work.map::<Oid<'a>, ()>();
163        // RFC5280 ยง4.2.1.12 gives a nonempty sequence of purpose OIDs, without
164        // a uniqueness constraint. Repeated purposes add no new capability;
165        // retain their first-occurrence order through this shared decoder.
166        // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.12
167        while !inside.is_empty() {
168            let purpose = inside.read_oid().field(FIELD)?;
169            if seen
170                .try_insert(purpose, ())
171                .map_err(|reason| Error::resource(reason, FIELD, inside.offset()))?
172                .is_none()
173            {
174                purposes
175                    .try_push(purpose)
176                    .map_err(|reason| Error::resource(reason, FIELD, inside.offset()))?;
177            }
178        }
179        if purposes.is_empty() {
180            return Err(Error::new(ErrorCode::EmptySequence, FIELD, at));
181        }
182        Ok(Self {
183            purposes: purposes.into_owned(),
184            at,
185        })
186    }
187
188    /// The purposes, in the order the certificate holds them.
189    #[must_use]
190    pub fn purposes(&self) -> &[Oid<'a>] {
191        &self.purposes
192    }
193
194    /// Whether one purpose is among them.
195    ///
196    /// The identifier that stands for any purpose is not treated as matching
197    /// everything here: whether it does is a policy question, and answering it
198    /// in the parser would hide the difference between a certificate that
199    /// names a purpose and one that names none.
200    pub fn has(&self, purpose: Oid<'_>, execution: &Memory) -> Result<bool> {
201        for candidate in &self.purposes {
202            let work = 1 + candidate.as_bytes().len().max(purpose.as_bytes().len()) as u64;
203            execution
204                .charge_work(work)
205                .map_err(|reason| Error::resource(reason, "extensions.extKeyUsage", self.at))?;
206            if *candidate == purpose {
207                return Ok(true);
208            }
209        }
210        Ok(false)
211    }
212
213    /// Reads the value of an extended key usage extension.
214    pub fn read(extension: &Extension<'a>, execution: &Memory) -> Result<Self> {
215        Self::read_members(
216            extension::sequence(extension, "extensions.extKeyUsage", execution)?,
217            execution,
218            extension.span().start,
219        )
220    }
221
222    /// Decodes the original value with current query and origin admission.
223    pub fn read_in<'work>(
224        extension: &Extension<'a>,
225        query: &Reader<'work>,
226    ) -> Result<ExtendedKeyUsage<'work>>
227    where
228        'a: 'work,
229    {
230        let reader = extension.reader_in(query).field("extensions.extKeyUsage")?;
231        let inside =
232            extension::sequence_reader(reader, "extensions.extKeyUsage", extension.span().start)?;
233        ExtendedKeyUsage::read_members(inside, query.memory(), extension.span().start)
234    }
235}
236
237#[cfg(test)]
238mod tests;