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(extension, execution)?);
60 } else if extension.kind() == oid::OCSP_EXTENDED_REVOKE {
61 retention::extended_revoke(extension, execution)?;
62 extended_revoke = true;
63 } else if extension.is_critical() {
64 return Ok(Processed {
65 processing: ExtensionProcessing::Unsupported {
66 kind: extension.kind(),
67 span: extension.span(),
68 },
69 nonce,
70 extended_revoke,
71 });
72 }
73 }
74 Ok(Processed {
75 processing: ExtensionProcessing::Understood,
76 nonce,
77 extended_revoke,
78 })
79 }
80}
81
82impl<'a> SingleResponse<'a> {
83 pub fn check_extensions<W: Work>(&self, execution: &W) -> Result<ExtensionProcessing<'a>> {
87 self.process_extensions(execution)
88 .map(|facts| facts.processing)
89 }
90
91 pub(super) fn process_extensions<W: Work>(&self, execution: &W) -> Result<ProcessedSingle<'a>> {
92 const FIELD: &str = "ocspResponse.singleResponse.extensions";
93 execution
94 .charge_work(1)
95 .map_err(|reason| Error::resource(reason, FIELD, self.span.start))?;
96 let mut archive_cutoff = None;
97 for extension in self.extensions.iter(execution) {
98 let extension = extension?;
99 execution
101 .charge_work(10)
102 .map_err(|reason| Error::resource(reason, FIELD, extension.span().start))?;
103 if extension.kind() == oid::OCSP_ARCHIVE_CUTOFF {
104 archive_cutoff = Some(retention::archive_cutoff(extension, execution)?);
105 } else if extension.kind() == oid::OCSP_EXTENDED_REVOKE {
106 return Err(retention::misplaced(extension));
107 } else if extension.is_critical() {
108 return Ok(ProcessedSingle {
109 processing: ExtensionProcessing::Unsupported {
110 kind: extension.kind(),
111 span: extension.span(),
112 },
113 archive_cutoff,
114 });
115 }
116 }
117 Ok(ProcessedSingle {
118 processing: ExtensionProcessing::Understood,
119 archive_cutoff,
120 })
121 }
122}