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 fn check_content<P: AsnDigest<'a>, S: Source>(
65 &self,
66 provider: &'a P,
67 parent: &Reader<'a>,
68 source: &mut S,
69 ) -> Result<ImprintAgreement, ImprintError<S::Error, P::Error>> {
70 self.check_input(provider, parent, &mut super::RawInput::new(source))
71 }
72
73 pub fn check_input<P, I>(
79 &self,
80 provider: &'a P,
81 parent: &Reader<'a>,
82 input: &mut I,
83 ) -> Result<ImprintAgreement, ImprintError<I::Error, P::Error>>
84 where
85 P: AsnDigest<'a>,
86 I: super::ComputedInput<P, P::Error>,
87 {
88 let resolved = self
89 .resolve(provider, parent)
90 .map_err(ImprintError::Processing)?;
91 match resolved {
92 Resolved::Ready(identity) => self.compute_input(provider, parent, input, identity),
93 Resolved::Unusable(answer) => Ok(answer),
94 }
95 }
96
97 pub(super) fn require_session(&self, parent: &Reader<'_>) -> crate::Result<()> {
98 if !core::ptr::eq(self.hashed().parser(), parent.parser()) {
99 return Err(Error::pkix(structured_pkix::Error::new(
100 structured_pkix::ErrorCode::ForeignReader,
101 self.fields().enclosing,
102 self.span().start,
103 )));
104 }
105 Ok(())
106 }
107
108 pub(super) fn resolve<P: AsnDigest<'a>>(
109 &self,
110 provider: &'a P,
111 parent: &Reader<'a>,
112 ) -> crate::Result<Resolved<P::Identity>> {
113 crate::provider::require_instance(provider, self.fields().enclosing, self.span().start)?;
114 self.require_session(parent)?;
115 if !self.faults().is_empty() {
116 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
117 }
118 let HashAlgorithmReading::Identifier(identifier) = self.algorithm() else {
119 return Ok(Resolved::Unusable(ImprintAgreement::MalformedImprint));
120 };
121 let identity = match crate::provider::resolve_digest(
122 provider,
123 DigestAlgorithm::Written(*identifier),
124 parent,
125 )? {
126 Resolution::Supported(identity) => identity,
127 Resolution::Malformed => {
128 return Ok(Resolved::Unusable(ImprintAgreement::MalformedAlgorithm));
129 }
130 Resolution::Unsupported => {
131 return Ok(Resolved::Unusable(ImprintAgreement::Unsupported));
132 }
133 };
134 if let Some(width) = provider.width(&identity)
135 && self.hashed().len() != width
136 {
137 return Ok(Resolved::Unusable(ImprintAgreement::MalformedHash));
138 }
139 Ok(Resolved::Ready(identity))
140 }
141
142 pub(super) fn compute_input<P, I>(
143 &self,
144 provider: &'a P,
145 parent: &Reader<'a>,
146 input: &mut I,
147 identity: P::Identity,
148 ) -> Result<ImprintAgreement, ImprintError<I::Error, P::Error>>
149 where
150 P: AsnDigest<'a>,
151 I: super::ComputedInput<P, P::Error>,
152 {
153 super::computed::compute(self, provider, parent, input, identity)
154 }
155}