Skip to main content

structured_pkix/
identifier.rs

1//! The identifiers that say which key signed a certificate and which key it
2//! carries.
3//!
4//! These are hints for finding a candidate issuer, not proof of one. A path is
5//! built by verifying signatures and matching names; an identifier that
6//! matches only says which certificate to try first, and a certificate whose
7//! identifier matches nothing may still be the right one.
8
9use crate::error::{Error, ErrorCode, Located, Result};
10use crate::extension::{self, Extension};
11use crate::general_name::{self, GeneralName};
12use structured_asn1::memory::{Memory, OwnedVec};
13use structured_asn1::{Element, Integer, Reader, Tag, universal};
14
15/// An identifier for the key this certificate carries.
16#[derive(Debug, Clone, Copy)]
17pub struct SubjectKeyIdentifier<'a> {
18    bytes: &'a [u8],
19}
20
21impl<'a> SubjectKeyIdentifier<'a> {
22    /// The identifier, as the issuer computed it. How it was computed is the
23    /// issuer's choice and is not stated in the certificate, so it is compared
24    /// rather than recomputed.
25    #[must_use]
26    pub fn as_bytes(self) -> &'a [u8] {
27        self.bytes
28    }
29
30    /// Reads the value of a subject key identifier extension.
31    pub fn read(extension: &Extension<'a>, execution: &Memory) -> Result<Self> {
32        Self::read_value(
33            extension,
34            extension
35                .reader(execution)
36                .field("extensions.subjectKeyIdentifier")?,
37        )
38    }
39
40    /// Reads the original value while also enforcing current query ceilings.
41    /// The returned identifier borrows the original extension, not the query.
42    pub fn read_in<'query>(extension: &Extension<'a>, query: &Reader<'query>) -> Result<Self>
43    where
44        'a: 'query,
45    {
46        Self::read_value(
47            extension,
48            extension
49                .reader_in(query)
50                .field("extensions.subjectKeyIdentifier")?,
51        )
52    }
53
54    fn read_value(extension: &Extension<'a>, mut reader: Reader<'_>) -> Result<Self> {
55        const FIELD: &str = "extensions.subjectKeyIdentifier";
56        let fail = |code| Error::new(code, FIELD, extension.span().start);
57
58        let element = reader
59            .next_element()
60            .field(FIELD)?
61            .ok_or_else(|| fail(ErrorCode::MissingField))?;
62        if element.tag() != Tag::primitive(universal::OCTET_STRING) {
63            return Err(fail(ErrorCode::Encoding(
64                structured_asn1::ErrorCode::UnexpectedTag,
65            )));
66        }
67        if !reader.is_empty() {
68            return Err(fail(ErrorCode::TrailingData));
69        }
70
71        // The common reader admitted one complete primitive OCTET STRING and
72        // no trailing data. Its contents are the suffix of this original value;
73        // project that validated length without tying storage to query lifetime
74        // or implementing another tag/length decoder.
75        let original = extension.value();
76        let from = original.len() - element.contents().len();
77        Ok(Self {
78            bytes: &original[from..],
79        })
80    }
81}
82
83/// An identifier for the key that signed this certificate.
84#[derive(Debug)]
85pub struct AuthorityKeyIdentifier<'a> {
86    key_id: Option<&'a [u8]>,
87    issuer: OwnedVec<GeneralName<'a>>,
88    serial: Option<Integer<'a>>,
89}
90
91impl<'a> AuthorityKeyIdentifier<'a> {
92    /// The identifier of the signing key, where the issuer wrote one.
93    #[must_use]
94    pub fn key_id(&self) -> Option<&'a [u8]> {
95        self.key_id
96    }
97
98    /// The names of the certificate that carries the signing key, where the
99    /// issuer wrote them.
100    #[must_use]
101    pub fn issuer(&self) -> &[GeneralName<'a>] {
102        &self.issuer
103    }
104
105    /// The serial number of that certificate, which is written with the names
106    /// or not at all.
107    #[must_use]
108    pub fn serial(&self) -> Option<Integer<'a>> {
109        self.serial
110    }
111
112    /// Reads the value of an authority key identifier extension.
113    pub fn read(extension: &Extension<'a>, execution: &Memory) -> Result<Self> {
114        const FIELD: &str = "extensions.authorityKeyIdentifier";
115        let fail = |code| Error::new(code, FIELD, extension.span().start);
116
117        let mut inside = extension::sequence(extension, FIELD, execution)?;
118        let mut identifier = Self {
119            key_id: None,
120            issuer: inside.memory().vector(),
121            serial: None,
122        };
123
124        // The three fields are written in the order of their numbers, once
125        // each: a tag at or below the last one read is not this schema.
126        let mut last_number = None;
127        while let Some(field) = inside.next_element().field(FIELD)? {
128            let tag = extension::context_of(field.tag());
129            match tag {
130                Some((0, false)) if last_number.is_none() => {
131                    identifier.key_id = Some(field.contents());
132                }
133                Some((1, true)) if last_number < Some(1) => {
134                    identifier.issuer = general_name::read_all(&inside, &field, FIELD)?;
135                }
136                Some((2, false)) if last_number < Some(2) => {
137                    identifier.serial = Some(inside.integer(&field).field(FIELD)?);
138                }
139                _ => return Err(at(FIELD, ErrorCode::UnexpectedField, &field)),
140            }
141            last_number = tag.map(|(number, _)| number);
142        }
143
144        // The names and the serial number identify one certificate together.
145        // Either alone names a certificate the issuer did not mean: a serial
146        // number is unique within one issuer and says nothing without it.
147        if identifier.issuer.is_empty() != identifier.serial.is_none() {
148            return Err(fail(ErrorCode::MalformedValue));
149        }
150
151        // The issuer half of the pair stands for the issuer field of the
152        // identified certificate, which is a distinguished name: without at
153        // least one directory name beside the serial, the pair names no
154        // certificate issuer while claiming to.
155        if !identifier.issuer.is_empty()
156            && !identifier
157                .issuer
158                .iter()
159                .any(|name| matches!(name, general_name::GeneralName::Directory(_)))
160        {
161            return Err(fail(ErrorCode::MalformedValue));
162        }
163
164        // Empty, the structure names no issuing key and no certificate while
165        // wearing the extension that exists to name one: at least the key
166        // identifier or the complete issuer-and-serial pair is required.
167        if identifier.key_id.is_none() && identifier.serial.is_none() {
168            return Err(fail(ErrorCode::MalformedValue));
169        }
170
171        Ok(identifier)
172    }
173}
174
175fn at(field: &'static str, code: ErrorCode, element: &Element<'_>) -> Error {
176    Error::new(code, field, element.span().start)
177}
178
179#[cfg(test)]
180mod tests;