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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
//! What a certificate may certify below itself.
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::{Tag, universal};
/// A count of certificates a constraint names.
///
/// The fields counted here are `INTEGER (0..MAX)` (RFC 5280 4.2.1.9, 4.2.1.11
/// and 4.2.1.14), so a count wider than any path that could be built is inside
/// the schema. It is kept as what it is, a bound nothing reaches, rather than
/// refused as malformed or folded into a number the certificate never wrote.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CertificateCount {
/// The count the certificate names.
Certificates(u32),
/// A count past what a path could hold, which therefore never binds.
BeyondAnyPath,
}
impl CertificateCount {
/// The count where a path could reach it, and `None` where nothing can.
#[must_use]
pub fn certificates(self) -> Option<u32> {
match self {
Self::Certificates(count) => Some(count),
Self::BeyondAnyPath => None,
}
}
/// Whether the count is zero, which is the only value some fields permit.
#[must_use]
pub fn is_zero(self) -> bool {
self == Self::Certificates(0)
}
}
/// Whether this is a certification authority, and how far below it a path may
/// go.
#[derive(Debug, Clone, Copy)]
pub struct BasicConstraints {
authority: bool,
path_length: Option<CertificateCount>,
}
impl BasicConstraints {
/// Whether the certificate may sign other certificates.
#[must_use]
pub fn is_authority(self) -> bool {
self.authority
}
/// How many certificates may sit between this one and the one at the end
/// of the path, where the certificate says.
///
/// Written without the flag above it constrains nothing, and is kept as
/// what the certificate said rather than dropped.
#[must_use]
pub fn path_length(self) -> Option<CertificateCount> {
self.path_length
}
/// Reads the value of a basic constraints extension.
pub fn read<W: Work>(extension: &Extension<'_>, execution: &W) -> Result<Self> {
const FIELD: &str = "extensions.basicConstraints";
let fail = |code| Error::new(code, FIELD, extension.span().start);
let mut inside = extension::sequence(extension, FIELD, execution)?;
// Absent means not an authority, which is what a certificate issued to
// a person leaves it at.
let mut authority = false;
let mut path_length = None;
let mut next = inside.next_element().field(FIELD)?;
if let Some(flag) = next
&& flag.tag() == Tag::primitive(universal::BOOLEAN)
{
authority = inside.boolean(&flag).field(FIELD)?;
// X.690 11.5: DER omits a component equal to its default, and the
// flag defaults to false. Writing it out is a second spelling of
// the absent flag.
if !authority && inside.encoding().is_der() {
return Err(Error::new(
ErrorCode::MalformedValue,
FIELD,
flag.span().start,
));
}
next = inside.next_element().field(FIELD)?;
}
if let Some(length) = next {
if length.tag() != Tag::primitive(universal::INTEGER) {
return Err(fail(ErrorCode::Encoding(
structured_asn1::ErrorCode::UnexpectedTag,
)));
}
// The path length must not be present unless the authority flag
// is asserted (RFC 5280 4.2.1.9): without it, the value
// constrains a path below a certificate that says it heads none.
if !authority {
return Err(Error::new(
ErrorCode::UnexpectedField,
FIELD,
length.span().start,
));
}
path_length = Some(read_count(&inside, &length, FIELD)?);
}
if !inside.is_empty() {
return Err(fail(ErrorCode::TrailingData));
}
Ok(Self {
authority,
path_length,
})
}
}
/// The name space a certification authority may certify within.
#[derive(Debug)]
pub struct NameConstraints<'a> {
permitted: OwnedVec<Subtree<'a>>,
excluded: OwnedVec<Subtree<'a>>,
}
/// One region of the name space, as a name every name in it sits under. The
/// region starts at its base: the profile requires the minimum distance to
/// be zero and the maximum to be absent, and a subtree written otherwise is
/// refused when it is read.
#[derive(Debug)]
pub struct Subtree<'a> {
base: GeneralName<'a>,
}
impl<'a> Subtree<'a> {
/// The name the region is described by.
#[must_use]
pub fn base(&self) -> &GeneralName<'a> {
&self.base
}
}
impl<'a> NameConstraints<'a> {
/// The regions names below this certificate must sit in.
#[must_use]
pub fn permitted(&self) -> &[Subtree<'a>] {
&self.permitted
}
/// The regions they must not.
#[must_use]
pub fn excluded(&self) -> &[Subtree<'a>] {
&self.excluded
}
/// Reads the value of a name constraints extension.
pub fn read<W: Work>(extension: &Extension<'a>, execution: &W) -> Result<Self> {
const FIELD: &str = "extensions.nameConstraints";
let fail = |code| Error::new(code, FIELD, extension.span().start);
let mut inside = extension::sequence(extension, FIELD, execution)?;
let work = inside.execution_in(execution.memory());
let mut permitted = work.vector();
let mut excluded = work.vector();
// The schema fixes the order: permitted, then excluded. A tag at or
// below the last one read is a repeat or a field written backwards,
// and neither is this schema.
let mut last_number = None;
while let Some(field) = inside.next_element().field(FIELD)? {
let tag = extension::context_of(field.tag());
let subtrees = match tag {
Some((0, true)) if last_number.is_none() => &mut permitted,
Some((1, true)) if last_number < Some(1) => &mut excluded,
_ => {
return Err(Error::new(
ErrorCode::UnexpectedField,
FIELD,
field.span().start,
));
}
};
last_number = tag.map(|(number, _)| number);
let mut list = inside.enter(&field).field(FIELD)?;
while let Some(entry) = list.next_element().field(FIELD)? {
subtrees
.try_push(read_subtree(&list, &entry, FIELD)?)
.map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
}
if subtrees.is_empty() {
return Err(Error::new(
ErrorCode::EmptySequence,
FIELD,
field.span().start,
));
}
}
// A constraint that permits nothing and excludes nothing constrains
// nothing, while being marked critical to say it must be obeyed.
if permitted.is_empty() && excluded.is_empty() {
return Err(fail(ErrorCode::MalformedValue));
}
Ok(Self {
permitted: permitted.into_owned(),
excluded: excluded.into_owned(),
})
}
}
/// Limits on how policies are processed below this certificate.
#[derive(Debug, Clone, Copy)]
pub struct PolicyConstraints {
require_explicit_policy: Option<CertificateCount>,
inhibit_policy_mapping: Option<CertificateCount>,
}
impl PolicyConstraints {
/// After how many certificates a path must name a policy.
#[must_use]
pub fn require_explicit_policy(self) -> Option<CertificateCount> {
self.require_explicit_policy
}
/// After how many certificates policy mappings stop being honoured.
#[must_use]
pub fn inhibit_policy_mapping(self) -> Option<CertificateCount> {
self.inhibit_policy_mapping
}
/// Reads the value of a policy constraints extension.
pub fn read<W: Work>(extension: &Extension<'_>, execution: &W) -> Result<Self> {
const FIELD: &str = "extensions.policyConstraints";
let fail = |code| Error::new(code, FIELD, extension.span().start);
let mut inside = extension::sequence(extension, FIELD, execution)?;
let mut constraints = Self {
require_explicit_policy: None,
inhibit_policy_mapping: None,
};
// Fixed order here too: 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() => {
constraints.require_explicit_policy = Some(read_count(&inside, &field, FIELD)?);
}
Some((1, false)) if last_number < Some(1) => {
constraints.inhibit_policy_mapping = Some(read_count(&inside, &field, FIELD)?);
}
_ => {
return Err(Error::new(
ErrorCode::UnexpectedField,
FIELD,
field.span().start,
));
}
}
last_number = tag.map(|(number, _)| number);
}
// Neither field written is an extension that says nothing.
if constraints.require_explicit_policy.is_none()
&& constraints.inhibit_policy_mapping.is_none()
{
return Err(fail(ErrorCode::MalformedValue));
}
Ok(constraints)
}
}
/// After how many certificates the identifier standing for any policy stops
/// being accepted.
#[derive(Debug, Clone, Copy)]
pub struct InhibitAnyPolicy {
skip: CertificateCount,
}
impl InhibitAnyPolicy {
/// How many certificates it survives.
#[must_use]
pub fn skip(self) -> CertificateCount {
self.skip
}
/// Reads the value of an inhibit-any-policy extension.
pub fn read<W: Work>(extension: &Extension<'_>, execution: &W) -> Result<Self> {
const FIELD: &str = "extensions.inhibitAnyPolicy";
let fail = |code| Error::new(code, FIELD, extension.span().start);
let mut reader = extension.reader_scoped(execution).field(FIELD)?;
let element = reader
.next_element()
.field(FIELD)?
.ok_or_else(|| fail(ErrorCode::MissingField))?;
if element.tag() != Tag::primitive(universal::INTEGER) {
return Err(fail(ErrorCode::Encoding(
structured_asn1::ErrorCode::UnexpectedTag,
)));
}
let skip = read_count(&reader, &element, FIELD)?;
if !reader.is_empty() {
return Err(fail(ErrorCode::TrailingData));
}
Ok(Self { skip })
}
}
fn read_subtree<'a>(
parent: &structured_asn1::ScopedReader<'a, '_>,
element: &structured_asn1::Element<'a>,
field: &'static str,
) -> Result<Subtree<'a>> {
let fail = |code| Error::new(code, field, element.span().start);
if element.tag() != Tag::constructed(universal::SEQUENCE) {
return Err(fail(ErrorCode::Encoding(
structured_asn1::ErrorCode::UnexpectedTag,
)));
}
let mut inside = parent.enter(element).field(field)?;
let base_element = inside
.next_element()
.field(field)?
.ok_or_else(|| fail(ErrorCode::MissingField))?;
let base = general_name::read_as(
&inside,
&base_element,
field,
general_name::AddressForm::WithMask,
)?;
// The profile requires the minimum to be zero and the maximum to be
// absent (RFC 5280 4.2.1.10): either written otherwise asks for a
// reading this profile does not define. Zero spelled out is refused
// under DER as a second spelling of the absent default (X.690 11.5) and
// read under BER, which carries no such rule.
let mut last_number = None;
while let Some(distance) = inside.next_element().field(field)? {
let tag = extension::context_of(distance.tag());
match tag {
Some((0, false)) if last_number.is_none() => {
let count = read_count(&inside, &distance, field)?;
if !count.is_zero() || inside.encoding().is_der() {
return Err(Error::new(
ErrorCode::MalformedValue,
field,
distance.span().start,
));
}
}
_ => {
return Err(Error::new(
ErrorCode::UnexpectedField,
field,
distance.span().start,
));
}
}
last_number = tag.map(|(number, _)| number);
}
Ok(Subtree { base })
}
/// Reads a count of certificates, which is never negative.
fn read_count(
parent: &structured_asn1::ScopedReader<'_, '_>,
element: &structured_asn1::Element<'_>,
field: &'static str,
) -> Result<CertificateCount> {
let value = parent.integer(element).field(field)?;
// Below zero is outside the schema, which bounds every one of these
// fields at zero (RFC 5280 4.2.1.9, 4.2.1.11, 4.2.1.14).
if value.is_negative() {
return Err(Error::new(
ErrorCode::MalformedValue,
field,
element.span().start,
));
}
// Above the type is still inside the schema, whose upper bound is MAX:
// the count is understood, and what it says is that nothing reaches it.
Ok(value.as_u32().map_or(
CertificateCount::BeyondAnyPath,
CertificateCount::Certificates,
))
}
#[cfg(test)]
mod tests;