structured_cms/timestamp/
imprint_check.rs1use super::{HashAlgorithmReading, MessageImprint};
4use crate::Error;
5use crate::digest::{DigestError, PassError};
6use crate::provider::DigestAlgorithm;
7use crate::stream::Source;
8use structured_asn1::Reader;
9use structured_asn1::digest::Resolution;
10use structured_pkix::algorithm::digest::AsnDigest;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum ImprintAgreement {
15 Matches,
17 Differs,
19 MalformedImprint,
21 MalformedAlgorithm,
23 MalformedHash,
25 Unsupported,
27}
28
29#[derive(Debug)]
31pub enum ImprintError<SE, PE> {
32 Processing(Error),
34 Digest(DigestError<PE>),
36 Comparison(crate::binding::BindError<PE>),
38 Pass(PassError<SE, PE>),
40 LostRequest,
42 ForeignInput,
44 IncompleteInput,
47}
48
49pub(super) enum Resolved<I> {
50 Ready(I),
51 Unusable(ImprintAgreement),
52}
53
54impl<'a> MessageImprint<'a> {
55 pub async fn check_input_async<P, I>(
58 &self,
59 provider: &'a P,
60 parent: &Reader<'a>,
61 input: &mut I,
62 ) -> Result<ImprintAgreement, ImprintError<I::Error, P::Error>>
63 where
64 P: AsnDigest<'a>,
65 I: super::AsyncComputedInput<P, P::Error>,
66 {
67 match self
68 .resolve(provider, parent)
69 .map_err(ImprintError::Processing)?
70 {
71 Resolved::Ready(identity) => {
72 super::computed::compute_async(self, provider, parent, input, identity).await
73 }
74 Resolved::Unusable(answer) => Ok(answer),
75 }
76 }
77 pub fn check_content<P: AsnDigest<'a>, S: Source>(
87 &self,
88 provider: &'a P,
89 parent: &Reader<'a>,
90 source: &mut S,
91 ) -> Result<ImprintAgreement, ImprintError<S::Error, P::Error>> {
92 self.check_input(provider, parent, &mut super::RawInput::new(source))
93 }
94
95 pub fn check_input<P, I>(
101 &self,
102 provider: &'a P,
103 parent: &Reader<'a>,
104 input: &mut I,
105 ) -> Result<ImprintAgreement, ImprintError<I::Error, P::Error>>
106 where
107 P: AsnDigest<'a>,
108 I: super::ComputedInput<P, P::Error>,
109 {
110 let resolved = self
111 .resolve(provider, parent)
112 .map_err(ImprintError::Processing)?;
113 match resolved {
114 Resolved::Ready(identity) => self.compute_input(provider, parent, input, identity),
115 Resolved::Unusable(answer) => Ok(answer),
116 }
117 }
118
119 pub(super) fn require_session(&self, parent: &Reader<'_>) -> crate::Result<()> {
120 if !core::ptr::eq(self.hashed().parser(), parent.parser()) {
121 return Err(Error::pkix(structured_pkix::Error::new(
122 structured_pkix::ErrorCode::ForeignReader,
123 self.fields().enclosing,
124 self.span().start,
125 )));
126 }
127 Ok(())
128 }
129
130 pub(super) fn resolve<P: AsnDigest<'a>>(
131 &self,
132 provider: &'a P,
133 parent: &Reader<'a>,
134 ) -> crate::Result<Resolved<P::Identity>> {
135 crate::provider::require_instance(provider, self.fields().enclosing, self.span().start)?;
136 self.require_session(parent)?;
137 if !self.faults().is_empty() {
138 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
139 }
140 let HashAlgorithmReading::Identifier(identifier) = self.algorithm() else {
141 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
142 };
143 let identity = match crate::provider::resolve_digest(
144 provider,
145 DigestAlgorithm::Written(*identifier),
146 parent,
147 )? {
148 Resolution::Supported(identity) => identity,
149 Resolution::Malformed => {
150 return Ok(Resolved::Unusable(ImprintAgreement::MalformedAlgorithm));
151 }
152 Resolution::Unsupported => {
153 return Ok(Resolved::Unusable(ImprintAgreement::Unsupported));
154 }
155 };
156 if let Some(width) = provider.width(&identity)
157 && self.hashed().len() != width
158 {
159 return Ok(Resolved::Unusable(ImprintAgreement::MalformedHash));
160 }
161 Ok(Resolved::Ready(identity))
162 }
163
164 pub(super) fn compute_input<P, I>(
165 &self,
166 provider: &'a P,
167 parent: &Reader<'a>,
168 input: &mut I,
169 identity: P::Identity,
170 ) -> Result<ImprintAgreement, ImprintError<I::Error, P::Error>>
171 where
172 P: AsnDigest<'a>,
173 I: super::ComputedInput<P, P::Error>,
174 {
175 super::computed::compute(self, provider, parent, input, identity)
176 }
177}