structured_pkix/ocsp/
extensions.rs1use super::{BasicResponse, SingleResponse, retention};
4use crate::temporal::Reading;
5use crate::{Error, Result, oid};
6use structured_asn1::memory::Work;
7use structured_asn1::{Oid, Span};
8
9#[derive(Debug, Clone, Copy)]
11pub enum ExtensionProcessing<'a> {
12 Understood,
15 Unsupported {
17 kind: Oid<'a>,
19 span: Span,
21 },
22}
23
24pub(super) struct Processed<'a> {
25 pub(super) processing: ExtensionProcessing<'a>,
26 pub(super) nonce: Option<&'a [u8]>,
27 pub(super) extended_revoke: bool,
28}
29
30pub(super) struct ProcessedSingle<'a> {
31 pub(super) processing: ExtensionProcessing<'a>,
32 pub(super) archive_cutoff: Option<Reading>,
33}
34
35impl<'a> BasicResponse<'a> {
36 pub fn check_extensions<W: Work>(&self, execution: &W) -> Result<ExtensionProcessing<'a>> {
42 self.process_extensions(execution)
43 .map(|facts| facts.processing)
44 }
45
46 pub(super) fn process_extensions<W: Work>(&self, execution: &W) -> Result<Processed<'a>> {
47 execution.charge_work(1).map_err(|reason| {
48 Error::resource(reason, "ocspResponse.extensions", self.span.start)
49 })?;
50 let mut nonce = None;
51 let mut extended_revoke = false;
52 for extension in self.extensions.iter(execution) {
53 let extension = extension?;
54 execution.charge_work(10).map_err(|reason| {
56 Error::resource(reason, "ocspResponse.extensions", extension.span().start)
57 })?;
58 if extension.kind() == oid::OCSP_NONCE {
59 nonce = Some(super::nonce::read(
60 extension,
61 execution,
62 "ocspResponse.nonce",
63 )?);
64 } else if extension.kind() == oid::OCSP_EXTENDED_REVOKE {
65 retention::extended_revoke(extension, execution)?;
66 extended_revoke = true;
67 } else if extension.is_critical() {
68 return Ok(Processed {
69 processing: ExtensionProcessing::Unsupported {
70 kind: extension.kind(),
71 span: extension.span(),
72 },
73 nonce,
74 extended_revoke,
75 });
76 }
77 }
78 Ok(Processed {
79 processing: ExtensionProcessing::Understood,
80 nonce,
81 extended_revoke,
82 })
83 }
84}
85
86impl<'a> SingleResponse<'a> {
87 pub fn check_extensions<W: Work>(&self, execution: &W) -> Result<ExtensionProcessing<'a>> {
91 self.process_extensions(execution)
92 .map(|facts| facts.processing)
93 }
94
95 pub(super) fn process_extensions<W: Work>(&self, execution: &W) -> Result<ProcessedSingle<'a>> {
96 const FIELD: &str = "ocspResponse.singleResponse.extensions";
97 execution
98 .charge_work(1)
99 .map_err(|reason| Error::resource(reason, FIELD, self.span.start))?;
100 let mut archive_cutoff = None;
101 for extension in self.extensions.iter(execution) {
102 let extension = extension?;
103 execution
105 .charge_work(10)
106 .map_err(|reason| Error::resource(reason, FIELD, extension.span().start))?;
107 if extension.kind() == oid::OCSP_ARCHIVE_CUTOFF {
108 archive_cutoff = Some(retention::archive_cutoff(extension, execution)?);
109 } else if extension.kind() == oid::OCSP_EXTENDED_REVOKE {
110 return Err(retention::misplaced(extension));
111 } else if extension.is_critical() {
112 return Ok(ProcessedSingle {
113 processing: ExtensionProcessing::Unsupported {
114 kind: extension.kind(),
115 span: extension.span(),
116 },
117 archive_cutoff,
118 });
119 }
120 }
121 Ok(ProcessedSingle {
122 processing: ExtensionProcessing::Understood,
123 archive_cutoff,
124 })
125 }
126}