1use super::{
4 EvidenceRecord, FIELD, encoding,
5 input::{Hasher, InputError},
6 syntax,
7};
8use crate::encoding::{FeedError, Form, Projection, Rules};
9use crate::{Error, ErrorCode, Result};
10use structured_asn1::{
11 Class, Reader,
12 length::DerLength,
13 memory::{OwnedVec, Work},
14};
15use structured_pkix::algorithm::digest::AsnDigest;
16
17pub struct PriorSequence<'record, 'document> {
24 record: &'record EvidenceRecord<'document>,
25 before: usize,
26 length: u64,
27 projected: Prefix<'record, 'document>,
28}
29enum Prefix<'r, 'd> {
30 Owned(OwnedVec<Projection<'d>>),
31 Borrowed(&'r [Projection<'d>]),
32}
33impl<'d> Prefix<'_, 'd> {
34 fn values(&self) -> &[Projection<'d>] {
35 match self {
36 Self::Owned(values) => values,
37 Self::Borrowed(values) => values,
38 }
39 }
40}
41impl<'r, 'd> PriorSequence<'r, 'd> {
42 pub fn new(
44 record: &'r EvidenceRecord<'d>,
45 before_chain: usize,
46 operation: &Reader<'d>,
47 ) -> Result<Self> {
48 operation.charge(1).map_err(encoding)?;
49 if before_chain == 0 || before_chain >= record.chains.len() {
50 return Err(syntax(
51 ErrorCode::InvalidLocation,
52 record.original.element.span(),
53 ));
54 }
55 let projected = Self::project(record, before_chain, operation)?;
56 let length = prefix_length(
57 &projected,
58 &operation.execution(),
59 record.original.element.span().start,
60 )?;
61 Ok(Self {
62 record,
63 before: before_chain,
64 length,
65 projected: Prefix::Owned(projected),
66 })
67 }
68 pub(super) fn all(
69 record: &EvidenceRecord<'d>,
70 operation: &Reader<'d>,
71 ) -> Result<OwnedVec<Projection<'d>>> {
72 Self::project(record, record.chains.len() - 1, operation)
73 }
74 pub(super) fn borrowed(
75 record: &'r EvidenceRecord<'d>,
76 before: usize,
77 projected: &'r [Projection<'d>],
78 operation: &Reader<'_>,
79 ) -> Result<Self> {
80 let values = &projected[..before];
81 let length = prefix_length(
82 values,
83 &operation.execution(),
84 record.original.element.span().start,
85 )?;
86 Ok(Self {
87 record,
88 before,
89 length,
90 projected: Prefix::Borrowed(values),
91 })
92 }
93 fn project(
94 record: &EvidenceRecord<'d>,
95 count: usize,
96 operation: &Reader<'d>,
97 ) -> Result<OwnedVec<Projection<'d>>> {
98 let origin = record.original.reader_in(operation)?;
99 let work = origin.execution_query(operation);
100 let mut rules = Rules::new(&work);
101 for stamp in &record.timestamps[..record
104 .chains
105 .get(count)
106 .map_or(record.timestamps.len(), |chain| chain.first)]
107 {
108 work.charge_work(1).map_err(|cause| {
109 Error::resource(cause, FIELD, stamp.original.element.span().start)
110 })?;
111 if let Some(span) = stamp.attributes_span {
112 rules.insert(span, Form::Set, &work)?;
113 }
114 if let super::TimeStamp::Rfc3161(token) = &stamp.token {
115 let message = token.message();
116 for span in [message.certificate_field(), message.revocation_field()]
117 .into_iter()
118 .flatten()
119 {
120 rules.insert(span, Form::Set, &work)?;
121 }
122 for certificate in message.certificates() {
123 for identifier in [
124 certificate.signature_algorithm(),
125 certificate.tbs().signature(),
126 certificate.tbs().public_key().algorithm(),
127 ] {
128 rules.algorithm(identifier, &work)?;
129 }
130 }
131 for signer in message.signers() {
132 work.charge_work(1)
133 .map_err(|cause| Error::resource(cause, FIELD, signer.span().start))?;
134 for attrs in [signer.signed_attributes(), signer.unsigned_attributes()]
135 .into_iter()
136 .flatten()
137 {
138 rules.insert(attrs.element().span(), Form::Set, &work)?;
139 }
140 for identifier in [
141 signer.digest_algorithm().identifier(),
142 signer.signature_algorithm().identifier(),
143 ]
144 .into_iter()
145 .flatten()
146 {
147 rules.algorithm(identifier, &work)?;
148 }
149 let sid = signer.fields().identity[1];
150 if sid.tag().class() == Class::ContextSpecific {
151 rules.insert(sid.span(), Form::Octets, &work)?;
152 }
153 }
154 }
155 }
156 let mut values = work.vector();
157 values
158 .try_reserve_exact(count)
159 .map_err(|cause| Error::resource(cause, FIELD, record.original.element.span().start))?;
160 for chain in &record.chains[..count] {
161 let parent = chain.original.reader_in(operation)?;
162 values
163 .try_push(Projection::new(&parent, chain.original.element, &rules)?)
164 .map_err(|cause| {
165 Error::resource(cause, FIELD, chain.original.element.span().start)
166 })?;
167 }
168 Ok(values.into_owned())
169 }
170 #[must_use]
172 pub fn before_chain(&self) -> usize {
173 self.before
174 }
175 pub(super) fn contains(&self, stamp: &super::ArchiveTimeStamp<'_>) -> bool {
176 core::ptr::eq(
177 stamp,
178 &raw const self.record.timestamps[self.record.chains[self.before].first],
179 )
180 }
181 pub(super) fn hash<'p, P: AsnDigest<'p>, W: Work, SE>(
182 &self,
183 hasher: &Hasher<'p, '_, P, W>,
184 ) -> core::result::Result<P::Output, InputError<SE, P::Error>> {
185 let mut state = hasher.start()?;
186 hasher.update(&mut state, &[0x30])?;
187 hasher.update(&mut state, DerLength::new(self.length).as_bytes())?;
188 for chain in self.projected.values() {
189 chain
190 .feed(&hasher.work, |bytes| hasher.update(&mut state, bytes))
191 .map_err(|cause| match cause {
192 FeedError::Resource(cause) => hasher.resource(cause),
193 FeedError::Callback(cause) => cause,
194 })?;
195 }
196 hasher.finish(state)
197 }
198}
199fn prefix_length<W: Work>(values: &[Projection<'_>], work: &W, at: u64) -> Result<u64> {
200 let mut length = 0u64;
201 for value in values {
202 work.charge_work(1)
203 .map_err(|cause| Error::resource(cause, FIELD, at))?;
204 length = length
205 .checked_add(value.len())
206 .ok_or_else(|| Error::schema(ErrorCode::LengthOverflow, FIELD, at))?;
207 }
208 Ok(length)
209}