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