structured_cms/timestamp/
request_encoding.rs1use crate::{Error, ErrorCode};
4use structured_asn1::{
5 Encoding, Oid, Reader,
6 length::DerLength,
7 memory::{MemoryError, OwnedVec, Work},
8};
9use structured_pkix::AlgorithmIdentifier;
10
11const FIELD: &str = "timeStampReq.encoding";
12
13#[derive(Debug, Clone, Copy)]
16pub struct RequestExtension<'a> {
17 pub identifier: Oid<'a>,
19 pub critical: bool,
21 pub value: &'a [u8],
23}
24
25pub struct NewRequest<'a> {
33 pub algorithm: AlgorithmIdentifier<'a>,
35 pub hashed_message: &'a [u8],
37 pub policy: Option<Oid<'a>>,
39 pub nonce: Option<&'a [u8]>,
41 pub cert_req: bool,
43 pub extensions: &'a [RequestExtension<'a>],
45}
46
47#[derive(Debug)]
49pub enum RequestEncodingError {
50 Processing(Error),
52 Parameters(structured_pkix::Error),
54 Resource(MemoryError),
56}
57
58impl NewRequest<'_> {
59 pub fn encode_der(&self, parent: &Reader<'_>) -> Result<OwnedVec<u8>, RequestEncodingError> {
69 if !self.algorithm.same_session(parent) {
70 return Err(RequestEncodingError::Processing(Error::schema(
71 ErrorCode::InvalidLocation,
72 FIELD,
73 self.algorithm.offset(),
74 )));
75 }
76 let work = parent.execution();
77 work.charge_work(1)
78 .map_err(RequestEncodingError::Resource)?;
79 parameters_der(self.algorithm, parent)?;
80 let oid = self.algorithm.algorithm().as_bytes();
81 let parameters = self.algorithm.parameters().unwrap_or(&[]);
82 let algorithm = add(tlv(oid.len())?, parameters.len())?;
83 let imprint = add(tlv(algorithm)?, tlv(self.hashed_message.len())?)?;
84 let mut total = add(3, tlv(imprint)?)?;
85 if let Some(policy) = self.policy {
86 total = add(total, tlv(policy.as_bytes().len())?)?;
87 }
88 let nonce = if let Some(bytes) = self.nonce {
89 work.charge_work(bytes.len() as u64)
90 .map_err(RequestEncodingError::Resource)?;
91 let first = bytes.iter().position(|b| *b != 0).unwrap_or(bytes.len());
92 let bytes = &bytes[first..];
93 let pad = bytes.is_empty() || bytes[0] & 0x80 != 0;
94 total = add(total, tlv(add(bytes.len(), usize::from(pad))?)?)?;
95 Some((bytes, pad))
96 } else {
97 None
98 };
99 if self.cert_req {
100 total = add(total, 3)?;
101 }
102 let mut extensions_len = 0;
103 for (index, extension) in self.extensions.iter().enumerate() {
104 work.charge_work(1)
105 .map_err(RequestEncodingError::Resource)?;
106 for previous in &self.extensions[..index] {
107 work.charge_work(add(
108 previous.identifier.as_bytes().len(),
109 extension.identifier.as_bytes().len(),
110 )? as u64)
111 .map_err(RequestEncodingError::Resource)?;
112 if previous.identifier == extension.identifier {
113 return Err(RequestEncodingError::Processing(Error::schema(
114 ErrorCode::DuplicateField,
115 FIELD,
116 self.algorithm.offset(),
117 )));
118 }
119 }
120 extensions_len = add(extensions_len, tlv(extension_len(extension)?)?)?;
121 }
122 if !self.extensions.is_empty() {
123 total = add(total, tlv(extensions_len)?)?;
124 }
125 let length = tlv(total)?;
126 work.charge_work(length as u64)
127 .map_err(RequestEncodingError::Resource)?;
128 let mut bytes = work.vector();
129 bytes
130 .try_reserve_exact(length)
131 .map_err(RequestEncodingError::Resource)?;
132 header(&mut bytes, 0x30, total)?;
133 push(&mut bytes, &[2, 1, 1])?;
134 header(&mut bytes, 0x30, imprint)?;
135 header(&mut bytes, 0x30, algorithm)?;
136 value(&mut bytes, 6, oid)?;
137 push(&mut bytes, parameters)?;
138 value(&mut bytes, 4, self.hashed_message)?;
139 if let Some(policy) = self.policy {
140 value(&mut bytes, 6, policy.as_bytes())?;
141 }
142 if let Some((nonce, pad)) = nonce {
143 header(&mut bytes, 2, nonce.len() + usize::from(pad))?;
144 if pad {
145 push(&mut bytes, &[0])?;
146 }
147 push(&mut bytes, nonce)?;
148 }
149 if self.cert_req {
150 push(&mut bytes, &[1, 1, 255])?;
151 }
152 if !self.extensions.is_empty() {
153 header(&mut bytes, 0xa0, extensions_len)?;
154 for extension in self.extensions {
155 header(&mut bytes, 0x30, extension_len(extension)?)?;
156 value(&mut bytes, 6, extension.identifier.as_bytes())?;
157 if extension.critical {
158 push(&mut bytes, &[1, 1, 255])?;
159 }
160 value(&mut bytes, 4, extension.value)?;
161 }
162 }
163 debug_assert_eq!(bytes.len(), length);
164 Ok(bytes.into_owned())
165 }
166}
167
168fn parameters_der<'a, 'q>(
169 algorithm: AlgorithmIdentifier<'a>,
170 parent: &Reader<'q>,
171) -> Result<(), RequestEncodingError>
172where
173 'a: 'q,
174{
175 let Some(mut parameters) = algorithm
176 .parameters_reader_in(parent, FIELD)
177 .map_err(RequestEncodingError::Parameters)?
178 else {
179 return Ok(());
180 };
181 let element = parameters
182 .next_element()
183 .map_err(|e| RequestEncodingError::Processing(Error::encoding(e, FIELD)))?
184 .ok_or_else(|| {
185 RequestEncodingError::Processing(Error::schema(
186 ErrorCode::MissingField,
187 FIELD,
188 parameters.offset(),
189 ))
190 })?;
191 let mut strict = parameters
194 .reread(&element, Encoding::Der)
195 .map_err(|e| RequestEncodingError::Processing(Error::encoding(e, FIELD)))?;
196 let element = strict
197 .next_element()
198 .map_err(|e| RequestEncodingError::Processing(Error::encoding(e, FIELD)))?
199 .ok_or_else(|| {
200 RequestEncodingError::Processing(Error::schema(
201 ErrorCode::MissingField,
202 FIELD,
203 strict.offset(),
204 ))
205 })?;
206 structured_pkix::der::conforms(&strict, &element, FIELD)
207 .map_err(RequestEncodingError::Parameters)
208}
209
210fn extension_len(extension: &RequestExtension<'_>) -> Result<usize, RequestEncodingError> {
211 add(
212 add(
213 tlv(extension.identifier.as_bytes().len())?,
214 if extension.critical { 3 } else { 0 },
215 )?,
216 tlv(extension.value.len())?,
217 )
218}
219fn add(a: usize, b: usize) -> Result<usize, RequestEncodingError> {
220 a.checked_add(b)
221 .ok_or(RequestEncodingError::Resource(MemoryError::WorkExceeded))
222}
223fn tlv(content: usize) -> Result<usize, RequestEncodingError> {
224 add(
225 add(1, DerLength::new(content as u64).as_bytes().len())?,
226 content,
227 )
228}
229fn push<W: Work>(out: &mut OwnedVec<u8, W>, value: &[u8]) -> Result<(), RequestEncodingError> {
230 out.try_extend_from_slice(value)
231 .map_err(RequestEncodingError::Resource)
232}
233fn header<W: Work>(
234 out: &mut OwnedVec<u8, W>,
235 tag: u8,
236 content: usize,
237) -> Result<(), RequestEncodingError> {
238 out.try_push(tag).map_err(RequestEncodingError::Resource)?;
239 push(out, DerLength::new(content as u64).as_bytes())
240}
241fn value<W: Work>(
242 out: &mut OwnedVec<u8, W>,
243 tag: u8,
244 value: &[u8],
245) -> Result<(), RequestEncodingError> {
246 header(out, tag, value.len())?;
247 push(out, value)
248}