1use crate::error::{Error, ErrorCode, Located, Result};
4use crate::extension::{self, Extension};
5use crate::general_name::{self, GeneralName};
6use structured_asn1::memory::{Memory, OwnedVec};
7use structured_asn1::{Tag, universal};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CertificateCount {
17 Certificates(u32),
19 BeyondAnyPath,
21}
22
23impl CertificateCount {
24 #[must_use]
26 pub fn certificates(self) -> Option<u32> {
27 match self {
28 Self::Certificates(count) => Some(count),
29 Self::BeyondAnyPath => None,
30 }
31 }
32
33 #[must_use]
35 pub fn is_zero(self) -> bool {
36 self == Self::Certificates(0)
37 }
38}
39
40#[derive(Debug, Clone, Copy)]
43pub struct BasicConstraints {
44 authority: bool,
45 path_length: Option<CertificateCount>,
46}
47
48impl BasicConstraints {
49 #[must_use]
51 pub fn is_authority(self) -> bool {
52 self.authority
53 }
54
55 #[must_use]
61 pub fn path_length(self) -> Option<CertificateCount> {
62 self.path_length
63 }
64
65 pub fn read(extension: &Extension<'_>, execution: &Memory) -> Result<Self> {
67 const FIELD: &str = "extensions.basicConstraints";
68 let fail = |code| Error::new(code, FIELD, extension.span().start);
69
70 let mut inside = extension::sequence(extension, FIELD, execution)?;
71
72 let mut authority = false;
75 let mut path_length = None;
76
77 let mut next = inside.next_element().field(FIELD)?;
78 if let Some(flag) = next
79 && flag.tag() == Tag::primitive(universal::BOOLEAN)
80 {
81 authority = inside.boolean(&flag).field(FIELD)?;
82 if !authority && inside.encoding().is_der() {
86 return Err(Error::new(
87 ErrorCode::MalformedValue,
88 FIELD,
89 flag.span().start,
90 ));
91 }
92 next = inside.next_element().field(FIELD)?;
93 }
94
95 if let Some(length) = next {
96 if length.tag() != Tag::primitive(universal::INTEGER) {
97 return Err(fail(ErrorCode::Encoding(
98 structured_asn1::ErrorCode::UnexpectedTag,
99 )));
100 }
101 if !authority {
105 return Err(Error::new(
106 ErrorCode::UnexpectedField,
107 FIELD,
108 length.span().start,
109 ));
110 }
111 path_length = Some(read_count(&inside, &length, FIELD)?);
112 }
113
114 if !inside.is_empty() {
115 return Err(fail(ErrorCode::TrailingData));
116 }
117
118 Ok(Self {
119 authority,
120 path_length,
121 })
122 }
123}
124
125#[derive(Debug)]
127pub struct NameConstraints<'a> {
128 permitted: OwnedVec<Subtree<'a>>,
129 excluded: OwnedVec<Subtree<'a>>,
130}
131
132#[derive(Debug)]
137pub struct Subtree<'a> {
138 base: GeneralName<'a>,
139}
140
141impl<'a> Subtree<'a> {
142 #[must_use]
144 pub fn base(&self) -> &GeneralName<'a> {
145 &self.base
146 }
147}
148
149impl<'a> NameConstraints<'a> {
150 #[must_use]
152 pub fn permitted(&self) -> &[Subtree<'a>] {
153 &self.permitted
154 }
155
156 #[must_use]
158 pub fn excluded(&self) -> &[Subtree<'a>] {
159 &self.excluded
160 }
161
162 pub fn read(extension: &Extension<'a>, execution: &Memory) -> Result<Self> {
164 const FIELD: &str = "extensions.nameConstraints";
165 let fail = |code| Error::new(code, FIELD, extension.span().start);
166
167 let mut inside = extension::sequence(extension, FIELD, execution)?;
168 let mut constraints = Self {
169 permitted: inside.memory().vector(),
170 excluded: inside.memory().vector(),
171 };
172
173 let mut last_number = None;
177 while let Some(field) = inside.next_element().field(FIELD)? {
178 let tag = extension::context_of(field.tag());
179 let subtrees = match tag {
180 Some((0, true)) if last_number.is_none() => &mut constraints.permitted,
181 Some((1, true)) if last_number < Some(1) => &mut constraints.excluded,
182 _ => {
183 return Err(Error::new(
184 ErrorCode::UnexpectedField,
185 FIELD,
186 field.span().start,
187 ));
188 }
189 };
190 last_number = tag.map(|(number, _)| number);
191
192 let mut list = inside.enter(&field).field(FIELD)?;
193 while let Some(entry) = list.next_element().field(FIELD)? {
194 subtrees
195 .try_push(read_subtree(&list, &entry, FIELD)?)
196 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
197 }
198 if subtrees.is_empty() {
199 return Err(Error::new(
200 ErrorCode::EmptySequence,
201 FIELD,
202 field.span().start,
203 ));
204 }
205 }
206
207 if constraints.permitted.is_empty() && constraints.excluded.is_empty() {
210 return Err(fail(ErrorCode::MalformedValue));
211 }
212 Ok(constraints)
213 }
214}
215
216#[derive(Debug, Clone, Copy)]
218pub struct PolicyConstraints {
219 require_explicit_policy: Option<CertificateCount>,
220 inhibit_policy_mapping: Option<CertificateCount>,
221}
222
223impl PolicyConstraints {
224 #[must_use]
226 pub fn require_explicit_policy(self) -> Option<CertificateCount> {
227 self.require_explicit_policy
228 }
229
230 #[must_use]
232 pub fn inhibit_policy_mapping(self) -> Option<CertificateCount> {
233 self.inhibit_policy_mapping
234 }
235
236 pub fn read(extension: &Extension<'_>, execution: &Memory) -> Result<Self> {
238 const FIELD: &str = "extensions.policyConstraints";
239 let fail = |code| Error::new(code, FIELD, extension.span().start);
240
241 let mut inside = extension::sequence(extension, FIELD, execution)?;
242 let mut constraints = Self {
243 require_explicit_policy: None,
244 inhibit_policy_mapping: None,
245 };
246
247 let mut last_number = None;
250 while let Some(field) = inside.next_element().field(FIELD)? {
251 let tag = extension::context_of(field.tag());
252 match tag {
253 Some((0, false)) if last_number.is_none() => {
254 constraints.require_explicit_policy = Some(read_count(&inside, &field, FIELD)?);
255 }
256 Some((1, false)) if last_number < Some(1) => {
257 constraints.inhibit_policy_mapping = Some(read_count(&inside, &field, FIELD)?);
258 }
259 _ => {
260 return Err(Error::new(
261 ErrorCode::UnexpectedField,
262 FIELD,
263 field.span().start,
264 ));
265 }
266 }
267 last_number = tag.map(|(number, _)| number);
268 }
269
270 if constraints.require_explicit_policy.is_none()
272 && constraints.inhibit_policy_mapping.is_none()
273 {
274 return Err(fail(ErrorCode::MalformedValue));
275 }
276 Ok(constraints)
277 }
278}
279
280#[derive(Debug, Clone, Copy)]
283pub struct InhibitAnyPolicy {
284 skip: CertificateCount,
285}
286
287impl InhibitAnyPolicy {
288 #[must_use]
290 pub fn skip(self) -> CertificateCount {
291 self.skip
292 }
293
294 pub fn read(extension: &Extension<'_>, execution: &Memory) -> Result<Self> {
296 const FIELD: &str = "extensions.inhibitAnyPolicy";
297 let fail = |code| Error::new(code, FIELD, extension.span().start);
298
299 let mut reader = extension.reader(execution).field(FIELD)?;
300 let element = reader
301 .next_element()
302 .field(FIELD)?
303 .ok_or_else(|| fail(ErrorCode::MissingField))?;
304 if element.tag() != Tag::primitive(universal::INTEGER) {
305 return Err(fail(ErrorCode::Encoding(
306 structured_asn1::ErrorCode::UnexpectedTag,
307 )));
308 }
309 let skip = read_count(&reader, &element, FIELD)?;
310 if !reader.is_empty() {
311 return Err(fail(ErrorCode::TrailingData));
312 }
313
314 Ok(Self { skip })
315 }
316}
317
318fn read_subtree<'a>(
319 parent: &structured_asn1::Reader<'a>,
320 element: &structured_asn1::Element<'a>,
321 field: &'static str,
322) -> Result<Subtree<'a>> {
323 let fail = |code| Error::new(code, field, element.span().start);
324
325 if element.tag() != Tag::constructed(universal::SEQUENCE) {
326 return Err(fail(ErrorCode::Encoding(
327 structured_asn1::ErrorCode::UnexpectedTag,
328 )));
329 }
330
331 let mut inside = parent.enter(element).field(field)?;
332 let base_element = inside
333 .next_element()
334 .field(field)?
335 .ok_or_else(|| fail(ErrorCode::MissingField))?;
336 let base = general_name::read_as(
337 &inside,
338 &base_element,
339 field,
340 general_name::AddressForm::WithMask,
341 )?;
342
343 let mut last_number = None;
349 while let Some(distance) = inside.next_element().field(field)? {
350 let tag = extension::context_of(distance.tag());
351 match tag {
352 Some((0, false)) if last_number.is_none() => {
353 let count = read_count(&inside, &distance, field)?;
354 if !count.is_zero() || inside.encoding().is_der() {
355 return Err(Error::new(
356 ErrorCode::MalformedValue,
357 field,
358 distance.span().start,
359 ));
360 }
361 }
362 _ => {
363 return Err(Error::new(
364 ErrorCode::UnexpectedField,
365 field,
366 distance.span().start,
367 ));
368 }
369 }
370 last_number = tag.map(|(number, _)| number);
371 }
372
373 Ok(Subtree { base })
374}
375
376fn read_count(
378 parent: &structured_asn1::Reader<'_>,
379 element: &structured_asn1::Element<'_>,
380 field: &'static str,
381) -> Result<CertificateCount> {
382 let value = parent.integer(element).field(field)?;
383 if value.is_negative() {
386 return Err(Error::new(
387 ErrorCode::MalformedValue,
388 field,
389 element.span().start,
390 ));
391 }
392 Ok(value.as_u32().map_or(
395 CertificateCount::BeyondAnyPath,
396 CertificateCount::Certificates,
397 ))
398}
399
400#[cfg(test)]
401mod tests;