1use crate::error::{Error, ErrorCode, Located, Result};
4use crate::extension::{self, Extension};
5use crate::general_name::{self, GeneralName};
6use structured_asn1::memory::{Memory, OwnedVec, Work};
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 work = inside.execution_in(execution);
169 let mut permitted = work.vector();
170 let mut excluded = work.vector();
171
172 let mut last_number = None;
176 while let Some(field) = inside.next_element().field(FIELD)? {
177 let tag = extension::context_of(field.tag());
178 let subtrees = match tag {
179 Some((0, true)) if last_number.is_none() => &mut permitted,
180 Some((1, true)) if last_number < Some(1) => &mut excluded,
181 _ => {
182 return Err(Error::new(
183 ErrorCode::UnexpectedField,
184 FIELD,
185 field.span().start,
186 ));
187 }
188 };
189 last_number = tag.map(|(number, _)| number);
190
191 let mut list = inside.enter(&field).field(FIELD)?;
192 while let Some(entry) = list.next_element().field(FIELD)? {
193 subtrees
194 .try_push(read_subtree(&list, &entry, FIELD)?)
195 .map_err(|reason| Error::resource(reason, FIELD, entry.span().start))?;
196 }
197 if subtrees.is_empty() {
198 return Err(Error::new(
199 ErrorCode::EmptySequence,
200 FIELD,
201 field.span().start,
202 ));
203 }
204 }
205
206 if permitted.is_empty() && excluded.is_empty() {
209 return Err(fail(ErrorCode::MalformedValue));
210 }
211 Ok(Self {
212 permitted: permitted.into_owned(),
213 excluded: excluded.into_owned(),
214 })
215 }
216}
217
218#[derive(Debug, Clone, Copy)]
220pub struct PolicyConstraints {
221 require_explicit_policy: Option<CertificateCount>,
222 inhibit_policy_mapping: Option<CertificateCount>,
223}
224
225impl PolicyConstraints {
226 #[must_use]
228 pub fn require_explicit_policy(self) -> Option<CertificateCount> {
229 self.require_explicit_policy
230 }
231
232 #[must_use]
234 pub fn inhibit_policy_mapping(self) -> Option<CertificateCount> {
235 self.inhibit_policy_mapping
236 }
237
238 pub fn read(extension: &Extension<'_>, execution: &Memory) -> Result<Self> {
240 const FIELD: &str = "extensions.policyConstraints";
241 let fail = |code| Error::new(code, FIELD, extension.span().start);
242
243 let mut inside = extension::sequence(extension, FIELD, execution)?;
244 let mut constraints = Self {
245 require_explicit_policy: None,
246 inhibit_policy_mapping: None,
247 };
248
249 let mut last_number = None;
252 while let Some(field) = inside.next_element().field(FIELD)? {
253 let tag = extension::context_of(field.tag());
254 match tag {
255 Some((0, false)) if last_number.is_none() => {
256 constraints.require_explicit_policy = Some(read_count(&inside, &field, FIELD)?);
257 }
258 Some((1, false)) if last_number < Some(1) => {
259 constraints.inhibit_policy_mapping = Some(read_count(&inside, &field, FIELD)?);
260 }
261 _ => {
262 return Err(Error::new(
263 ErrorCode::UnexpectedField,
264 FIELD,
265 field.span().start,
266 ));
267 }
268 }
269 last_number = tag.map(|(number, _)| number);
270 }
271
272 if constraints.require_explicit_policy.is_none()
274 && constraints.inhibit_policy_mapping.is_none()
275 {
276 return Err(fail(ErrorCode::MalformedValue));
277 }
278 Ok(constraints)
279 }
280}
281
282#[derive(Debug, Clone, Copy)]
285pub struct InhibitAnyPolicy {
286 skip: CertificateCount,
287}
288
289impl InhibitAnyPolicy {
290 #[must_use]
292 pub fn skip(self) -> CertificateCount {
293 self.skip
294 }
295
296 pub fn read(extension: &Extension<'_>, execution: &Memory) -> Result<Self> {
298 const FIELD: &str = "extensions.inhibitAnyPolicy";
299 let fail = |code| Error::new(code, FIELD, extension.span().start);
300
301 let mut reader = extension.reader(execution).field(FIELD)?;
302 let element = reader
303 .next_element()
304 .field(FIELD)?
305 .ok_or_else(|| fail(ErrorCode::MissingField))?;
306 if element.tag() != Tag::primitive(universal::INTEGER) {
307 return Err(fail(ErrorCode::Encoding(
308 structured_asn1::ErrorCode::UnexpectedTag,
309 )));
310 }
311 let skip = read_count(&reader, &element, FIELD)?;
312 if !reader.is_empty() {
313 return Err(fail(ErrorCode::TrailingData));
314 }
315
316 Ok(Self { skip })
317 }
318}
319
320fn read_subtree<'a>(
321 parent: &structured_asn1::Reader<'a>,
322 element: &structured_asn1::Element<'a>,
323 field: &'static str,
324) -> Result<Subtree<'a>> {
325 let fail = |code| Error::new(code, field, element.span().start);
326
327 if element.tag() != Tag::constructed(universal::SEQUENCE) {
328 return Err(fail(ErrorCode::Encoding(
329 structured_asn1::ErrorCode::UnexpectedTag,
330 )));
331 }
332
333 let mut inside = parent.enter(element).field(field)?;
334 let base_element = inside
335 .next_element()
336 .field(field)?
337 .ok_or_else(|| fail(ErrorCode::MissingField))?;
338 let base = general_name::read_as(
339 &inside,
340 &base_element,
341 field,
342 general_name::AddressForm::WithMask,
343 )?;
344
345 let mut last_number = None;
351 while let Some(distance) = inside.next_element().field(field)? {
352 let tag = extension::context_of(distance.tag());
353 match tag {
354 Some((0, false)) if last_number.is_none() => {
355 let count = read_count(&inside, &distance, field)?;
356 if !count.is_zero() || inside.encoding().is_der() {
357 return Err(Error::new(
358 ErrorCode::MalformedValue,
359 field,
360 distance.span().start,
361 ));
362 }
363 }
364 _ => {
365 return Err(Error::new(
366 ErrorCode::UnexpectedField,
367 field,
368 distance.span().start,
369 ));
370 }
371 }
372 last_number = tag.map(|(number, _)| number);
373 }
374
375 Ok(Subtree { base })
376}
377
378fn read_count(
380 parent: &structured_asn1::Reader<'_>,
381 element: &structured_asn1::Element<'_>,
382 field: &'static str,
383) -> Result<CertificateCount> {
384 let value = parent.integer(element).field(field)?;
385 if value.is_negative() {
388 return Err(Error::new(
389 ErrorCode::MalformedValue,
390 field,
391 element.span().start,
392 ));
393 }
394 Ok(value.as_u32().map_or(
397 CertificateCount::BeyondAnyPath,
398 CertificateCount::Certificates,
399 ))
400}
401
402#[cfg(test)]
403mod tests;