structured_cms/timestamp/
imprint_check.rs1use super::{HashAlgorithmReading, MessageImprint};
4use crate::Error;
5use crate::digest::{DigestBatch, DigestError, PassError};
6use crate::provider::DigestAlgorithm;
7use crate::stream::Source;
8use structured_asn1::Reader;
9use structured_asn1::digest::Resolution;
10use structured_asn1::memory::Work;
11use structured_pkix::algorithm::digest::AsnDigest;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ImprintAgreement {
16 Matches,
18 Differs,
20 MalformedImprint,
22 MalformedAlgorithm,
24 MalformedHash,
26 Unsupported,
28}
29
30#[derive(Debug)]
32pub enum ImprintError<SE, PE> {
33 Processing(Error),
35 Digest(DigestError<PE>),
37 Comparison(crate::binding::BindError<PE>),
39 Pass(PassError<SE, PE>),
41 LostRequest,
43}
44
45pub(super) enum Resolved<I> {
46 Ready(I),
47 Unusable(ImprintAgreement),
48}
49
50impl<'a> MessageImprint<'a> {
51 pub fn check_content<P: AsnDigest<'a>, S: Source>(
61 &self,
62 provider: &'a P,
63 parent: &Reader<'a>,
64 source: &mut S,
65 ) -> Result<ImprintAgreement, ImprintError<S::Error, P::Error>> {
66 let resolved = self
67 .resolve(provider, parent)
68 .map_err(ImprintError::Processing)?;
69 match resolved {
70 Resolved::Ready(identity) => self.compute(provider, parent, source, identity),
71 Resolved::Unusable(answer) => Ok(answer),
72 }
73 }
74
75 pub(super) fn require_session(&self, parent: &Reader<'_>) -> crate::Result<()> {
76 if !core::ptr::eq(self.hashed().parser(), parent.parser()) {
77 return Err(Error::pkix(structured_pkix::Error::new(
78 structured_pkix::ErrorCode::ForeignReader,
79 self.fields().enclosing,
80 self.span().start,
81 )));
82 }
83 Ok(())
84 }
85
86 pub(super) fn resolve<P: AsnDigest<'a>>(
87 &self,
88 provider: &'a P,
89 parent: &Reader<'a>,
90 ) -> crate::Result<Resolved<P::Identity>> {
91 crate::provider::require_instance(provider, self.fields().enclosing, self.span().start)?;
92 self.require_session(parent)?;
93 if !self.faults().is_empty() {
94 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
95 }
96 let HashAlgorithmReading::Identifier(identifier) = self.algorithm() else {
97 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
98 };
99 let identity = match crate::provider::resolve_digest(
100 provider,
101 DigestAlgorithm::Written(*identifier),
102 parent,
103 )? {
104 Resolution::Supported(identity) => identity,
105 Resolution::Malformed => {
106 return Ok(Resolved::Unusable(ImprintAgreement::MalformedAlgorithm));
107 }
108 Resolution::Unsupported => {
109 return Ok(Resolved::Unusable(ImprintAgreement::Unsupported));
110 }
111 };
112 if let Some(width) = provider.width(&identity)
113 && self.hashed().len() != width
114 {
115 return Ok(Resolved::Unusable(ImprintAgreement::MalformedHash));
116 }
117 Ok(Resolved::Ready(identity))
118 }
119
120 pub(super) fn compute<P: AsnDigest<'a>, S: Source>(
121 &self,
122 provider: &'a P,
123 parent: &Reader<'a>,
124 source: &mut S,
125 identity: P::Identity,
126 ) -> Result<ImprintAgreement, ImprintError<S::Error, P::Error>> {
127 let field = self.fields().hashed;
128 let at = self.hashed().span().start;
129 let joined;
130 let expected = if let Some(bytes) = self.hashed().as_one() {
132 bytes
133 } else {
134 joined = self
135 .hashed()
136 .copy_in(parent, field, at)
137 .map_err(ImprintError::Processing)?;
138 &*joined
139 };
140 let execution = parent.execution();
141 let mut identities = execution.vector();
142 identities
143 .try_push(identity)
144 .map_err(|reason| ImprintError::Processing(Error::resource(reason, field, at)))?;
145 let batch = DigestBatch::prepare(provider, identities.into_owned(), &execution, field, at)
146 .map_err(ImprintError::Digest)?;
147 let memo = batch.run(source, &execution).map_err(ImprintError::Pass)?;
148 let output = memo
149 .for_request(0, &execution)
150 .map_err(ImprintError::Digest)?
151 .ok_or(ImprintError::LostRequest)?;
152 let matches = crate::binding::matches_digest(
153 provider,
154 output.finished(),
155 expected,
156 &execution,
157 field,
158 self.hashed().span(),
159 )
160 .map_err(ImprintError::Comparison)?;
161 Ok(match matches {
162 crate::binding::DigestBinding::Matches => ImprintAgreement::Matches,
163 crate::binding::DigestBinding::Differs => ImprintAgreement::Differs,
164 crate::binding::DigestBinding::Malformed(_) => ImprintAgreement::MalformedHash,
165 })
166 }
167}