/src/MigTD/deps/td-shim/library/ring/src/digest.rs
Line | Count | Source |
1 | | // Copyright 2015-2019 Brian Smith. |
2 | | // |
3 | | // Permission to use, copy, modify, and/or distribute this software for any |
4 | | // purpose with or without fee is hereby granted, provided that the above |
5 | | // copyright notice and this permission notice appear in all copies. |
6 | | // |
7 | | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
8 | | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
10 | | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | | |
15 | | //! SHA-2 and the legacy SHA-1 digest algorithm. |
16 | | //! |
17 | | //! If all the data is available in a single contiguous slice then the `digest` |
18 | | //! function should be used. Otherwise, the digest can be calculated in |
19 | | //! multiple steps using `Context`. |
20 | | |
21 | | use self::{ |
22 | | dynstate::DynState, |
23 | | sha2::{SHA256_BLOCK_LEN, SHA512_BLOCK_LEN}, |
24 | | }; |
25 | | use crate::{ |
26 | | bits::{BitLength, FromByteLen as _}, |
27 | | cpu, debug, error, |
28 | | polyfill::{self, slice, sliceutil}, |
29 | | }; |
30 | | use core::num::Wrapping; |
31 | | |
32 | | extern crate alloc; |
33 | | |
34 | | pub(crate) use self::finish_error::FinishError; |
35 | | |
36 | | mod dynstate; |
37 | | mod sha1; |
38 | | mod sha2; |
39 | | |
40 | | #[derive(Clone)] |
41 | | pub(crate) struct BlockContext { |
42 | | state: DynState, |
43 | | |
44 | | // Note that SHA-512 has a 128-bit input bit counter, but this |
45 | | // implementation only supports up to 2^64-1 input bits for all algorithms, |
46 | | // so a 64-bit counter is more than sufficient. |
47 | | completed_bytes: u64, |
48 | | |
49 | | /// The context's algorithm. |
50 | | pub algorithm: &'static Algorithm, |
51 | | } |
52 | | |
53 | | impl BlockContext { |
54 | 0 | pub(crate) fn new(algorithm: &'static Algorithm) -> Self { |
55 | 0 | Self { |
56 | 0 | state: algorithm.initial_state.clone(), |
57 | 0 | completed_bytes: 0, |
58 | 0 | algorithm, |
59 | 0 | } |
60 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::new Unexecuted instantiation: <ring::digest::BlockContext>::new |
61 | | |
62 | | /// Processes all the full blocks in `input`, returning the partial block |
63 | | /// at the end, which may be empty. |
64 | 0 | pub(crate) fn update<'i>(&mut self, input: &'i [u8], cpu_features: cpu::Features) -> &'i [u8] { |
65 | 0 | let (completed_bytes, leftover) = self.block_data_order(input, cpu_features); |
66 | | // Using saturated addition here allows `update` to be infallible and |
67 | | // panic-free. If we were to reach the maximum value here then `finish` |
68 | | // will detect that we processed too much data when it converts this to |
69 | | // a bit length. |
70 | 0 | self.completed_bytes = self |
71 | 0 | .completed_bytes |
72 | 0 | .saturating_add(polyfill::u64_from_usize(completed_bytes)); |
73 | 0 | leftover |
74 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::update Unexecuted instantiation: <ring::digest::BlockContext>::update |
75 | | |
76 | | // On input, `block[..num_pending]` is the (possibly-empty) last *partial* |
77 | | // chunk of input. It *must* be partial; that is, it is required that |
78 | | // `num_pending < self.algorithm.block_len`. |
79 | | // |
80 | | // `block` may be arbitrarily overwritten. |
81 | 0 | pub(crate) fn try_finish( |
82 | 0 | mut self, |
83 | 0 | block: &mut [u8; MAX_BLOCK_LEN], |
84 | 0 | num_pending: usize, |
85 | 0 | cpu_features: cpu::Features, |
86 | 0 | ) -> Result<Digest, FinishError> { |
87 | 0 | let completed_bits = self |
88 | 0 | .completed_bytes |
89 | 0 | .checked_add(polyfill::u64_from_usize(num_pending)) |
90 | 0 | .ok_or_else(|| { |
91 | | // Choosing self.completed_bytes here is lossy & somewhat arbitrary. |
92 | 0 | InputTooLongError::new(self.completed_bytes) |
93 | 0 | }) Unexecuted instantiation: <ring::digest::BlockContext>::try_finish::{closure#0}Unexecuted instantiation: <ring::digest::BlockContext>::try_finish::{closure#0} |
94 | 0 | .and_then(BitLength::from_byte_len) |
95 | 0 | .map_err(FinishError::input_too_long)?; |
96 | | |
97 | 0 | let block_len = self.algorithm.block_len(); |
98 | 0 | let block = &mut block[..block_len]; |
99 | | |
100 | 0 | let padding = match block.get_mut(num_pending..) { |
101 | 0 | Some([separator, padding @ ..]) => { |
102 | 0 | *separator = 0x80; |
103 | 0 | padding |
104 | | } |
105 | | // Precondition violated. |
106 | 0 | unreachable => { |
107 | 0 | return Err(FinishError::pending_not_a_partial_block( |
108 | 0 | unreachable.as_deref(), |
109 | 0 | )); |
110 | | } |
111 | | }; |
112 | | |
113 | 0 | let padding = match padding |
114 | 0 | .len() |
115 | 0 | .checked_sub(self.algorithm.block_len.len_len()) |
116 | | { |
117 | 0 | Some(_) => padding, |
118 | | None => { |
119 | 0 | padding.fill(0); |
120 | 0 | let (completed_bytes, leftover) = self.block_data_order(block, cpu_features); |
121 | 0 | debug_assert_eq!((completed_bytes, leftover.len()), (block_len, 0)); |
122 | | // We don't increase |self.completed_bytes| because the padding |
123 | | // isn't data, and so it isn't included in the data length. |
124 | 0 | &mut block[..] |
125 | | } |
126 | | }; |
127 | | |
128 | 0 | let (to_zero, len) = padding.split_at_mut(padding.len() - 8); |
129 | 0 | to_zero.fill(0); |
130 | 0 | len.copy_from_slice(&completed_bits.to_be_bytes()); |
131 | | |
132 | 0 | let (completed_bytes, leftover) = self.block_data_order(block, cpu_features); |
133 | 0 | debug_assert_eq!((completed_bytes, leftover.len()), (block_len, 0)); |
134 | | |
135 | 0 | Ok(Digest { |
136 | 0 | algorithm: self.algorithm, |
137 | 0 | value: self.state.format_output(), |
138 | 0 | }) |
139 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::try_finish Unexecuted instantiation: <ring::digest::BlockContext>::try_finish |
140 | | |
141 | | #[must_use] |
142 | 0 | fn block_data_order<'d>( |
143 | 0 | &mut self, |
144 | 0 | data: &'d [u8], |
145 | 0 | cpu_features: cpu::Features, |
146 | 0 | ) -> (usize, &'d [u8]) { |
147 | 0 | (self.algorithm.block_data_order)(&mut self.state, data, cpu_features) |
148 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::block_data_order Unexecuted instantiation: <ring::digest::BlockContext>::block_data_order |
149 | | |
150 | | /// Serialize the BlockContext to bytes. |
151 | | /// Format: [algorithm_id (1 byte)] [completed_bytes (8 bytes)] [state (32 or 64 bytes)] |
152 | 0 | pub(crate) fn to_bytes(&self) -> alloc::vec::Vec<u8> { |
153 | 0 | let mut bytes = alloc::vec::Vec::new(); |
154 | | |
155 | | // Serialize algorithm ID |
156 | 0 | let alg_id: u8 = match self.algorithm.id { |
157 | 0 | AlgorithmID::SHA1 => 1, |
158 | 0 | AlgorithmID::SHA256 => 2, |
159 | 0 | AlgorithmID::SHA384 => 3, |
160 | 0 | AlgorithmID::SHA512 => 4, |
161 | 0 | AlgorithmID::SHA512_256 => 5, |
162 | | }; |
163 | 0 | bytes.push(alg_id); |
164 | | |
165 | | // Serialize completed_bytes |
166 | 0 | bytes.extend_from_slice(&self.completed_bytes.to_le_bytes()); |
167 | | |
168 | | // Serialize state |
169 | 0 | bytes.extend_from_slice(&self.state.to_bytes()); |
170 | | |
171 | 0 | bytes |
172 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::to_bytes Unexecuted instantiation: <ring::digest::BlockContext>::to_bytes |
173 | | |
174 | | /// Deserialize a BlockContext from bytes. |
175 | 0 | pub(crate) fn from_bytes(bytes: &[u8]) -> Result<Self, ()> { |
176 | 0 | if bytes.len() < 9 { |
177 | 0 | return Err(()); |
178 | 0 | } |
179 | | |
180 | | // Deserialize algorithm ID |
181 | 0 | let alg_id = bytes[0]; |
182 | 0 | let algorithm: &'static Algorithm = match alg_id { |
183 | 0 | 1 => &SHA1_FOR_LEGACY_USE_ONLY, |
184 | 0 | 2 => &SHA256, |
185 | 0 | 3 => &SHA384, |
186 | 0 | 4 => &SHA512, |
187 | 0 | 5 => &SHA512_256, |
188 | 0 | _ => return Err(()), |
189 | | }; |
190 | | |
191 | | // Deserialize completed_bytes |
192 | 0 | let completed_bytes = u64::from_le_bytes([ |
193 | 0 | bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], |
194 | 0 | ]); |
195 | | |
196 | | // Deserialize state |
197 | 0 | let state = DynState::from_bytes(&bytes[9..])?; |
198 | | |
199 | 0 | Ok(Self { |
200 | 0 | state, |
201 | 0 | completed_bytes, |
202 | 0 | algorithm, |
203 | 0 | }) |
204 | 0 | } Unexecuted instantiation: <ring::digest::BlockContext>::from_bytes Unexecuted instantiation: <ring::digest::BlockContext>::from_bytes |
205 | | } |
206 | | |
207 | | pub(crate) type InputTooLongError = error::InputTooLongError<u64>; |
208 | | |
209 | | cold_exhaustive_error! { |
210 | | enum finish_error::FinishError { |
211 | | input_too_long => InputTooLong(InputTooLongError), |
212 | | pending_not_a_partial_block_inner => PendingNotAPartialBlock(usize), |
213 | | } |
214 | | } |
215 | | |
216 | | impl FinishError { |
217 | | #[cold] |
218 | | #[inline(never)] |
219 | 0 | fn pending_not_a_partial_block(padding: Option<&[u8]>) -> Self { |
220 | 0 | match padding { |
221 | 0 | None => Self::pending_not_a_partial_block_inner(0), |
222 | 0 | Some(padding) => Self::pending_not_a_partial_block_inner(padding.len()), |
223 | | } |
224 | 0 | } Unexecuted instantiation: <ring::digest::finish_error::FinishError>::pending_not_a_partial_block Unexecuted instantiation: <ring::digest::finish_error::FinishError>::pending_not_a_partial_block |
225 | | } |
226 | | |
227 | | /// A context for multi-step (Init-Update-Finish) digest calculations. |
228 | | /// |
229 | | /// # Examples |
230 | | /// |
231 | | /// ``` |
232 | | /// use ring::digest; |
233 | | /// |
234 | | /// let one_shot = digest::digest(&digest::SHA384, b"hello, world"); |
235 | | /// |
236 | | /// let mut ctx = digest::Context::new(&digest::SHA384); |
237 | | /// ctx.update(b"hello"); |
238 | | /// ctx.update(b", "); |
239 | | /// ctx.update(b"world"); |
240 | | /// let multi_part = ctx.finish(); |
241 | | /// |
242 | | /// assert_eq!(&one_shot.as_ref(), &multi_part.as_ref()); |
243 | | /// ``` |
244 | | #[derive(Clone)] |
245 | | pub struct Context { |
246 | | block: BlockContext, |
247 | | // TODO: More explicitly force 64-bit alignment for |pending|. |
248 | | pending: [u8; MAX_BLOCK_LEN], |
249 | | |
250 | | // Invariant: `self.num_pending < self.block.algorithm.block_len`. |
251 | | num_pending: usize, |
252 | | } |
253 | | |
254 | | impl Context { |
255 | | /// Constructs a new context. |
256 | 0 | pub fn new(algorithm: &'static Algorithm) -> Self { |
257 | 0 | Self { |
258 | 0 | block: BlockContext::new(algorithm), |
259 | 0 | pending: [0u8; MAX_BLOCK_LEN], |
260 | 0 | num_pending: 0, |
261 | 0 | } |
262 | 0 | } Unexecuted instantiation: <ring::digest::Context>::new Unexecuted instantiation: <ring::digest::Context>::new |
263 | | |
264 | 0 | pub(crate) fn clone_from(block: &BlockContext) -> Self { |
265 | 0 | Self { |
266 | 0 | block: block.clone(), |
267 | 0 | pending: [0u8; MAX_BLOCK_LEN], |
268 | 0 | num_pending: 0, |
269 | 0 | } |
270 | 0 | } Unexecuted instantiation: <ring::digest::Context>::clone_from Unexecuted instantiation: <ring::digest::Context>::clone_from |
271 | | |
272 | | /// Updates the digest with all the data in `data`. |
273 | 0 | pub fn update(&mut self, data: &[u8]) { |
274 | 0 | let cpu_features = cpu::features(); |
275 | | |
276 | 0 | let block_len = self.block.algorithm.block_len(); |
277 | 0 | let buffer = &mut self.pending[..block_len]; |
278 | | |
279 | 0 | let to_digest = if self.num_pending == 0 { |
280 | 0 | data |
281 | | } else { |
282 | 0 | let buffer_to_fill = match buffer.get_mut(self.num_pending..) { |
283 | 0 | Some(buffer_to_fill) => buffer_to_fill, |
284 | | None => { |
285 | | // Impossible because of the invariant. |
286 | 0 | unreachable!(); |
287 | | } |
288 | | }; |
289 | 0 | sliceutil::overwrite_at_start(buffer_to_fill, data); |
290 | 0 | match slice::split_at_checked(data, buffer_to_fill.len()) { |
291 | 0 | Some((just_copied, to_digest)) => { |
292 | 0 | debug_assert_eq!(buffer_to_fill.len(), just_copied.len()); |
293 | 0 | debug_assert_eq!(self.num_pending + just_copied.len(), block_len); |
294 | 0 | let leftover = self.block.update(buffer, cpu_features); |
295 | 0 | debug_assert_eq!(leftover.len(), 0); |
296 | 0 | self.num_pending = 0; |
297 | 0 | to_digest |
298 | | } |
299 | | None => { |
300 | 0 | self.num_pending += data.len(); |
301 | | // If `data` isn't enough to complete a block, buffer it and stop. |
302 | 0 | debug_assert!(self.num_pending < block_len); |
303 | 0 | return; |
304 | | } |
305 | | } |
306 | | }; |
307 | | |
308 | 0 | let leftover = self.block.update(to_digest, cpu_features); |
309 | 0 | sliceutil::overwrite_at_start(buffer, leftover); |
310 | 0 | self.num_pending = leftover.len(); |
311 | 0 | debug_assert!(self.num_pending < block_len); |
312 | 0 | } Unexecuted instantiation: <ring::digest::Context>::update Unexecuted instantiation: <ring::digest::Context>::update |
313 | | |
314 | | /// Finalizes the digest calculation and returns the digest value. |
315 | | /// |
316 | | /// `finish` consumes the context so it cannot be (mis-)used after `finish` |
317 | | /// has been called. |
318 | 0 | pub fn finish(self) -> Digest { |
319 | 0 | let cpu = cpu::features(); |
320 | 0 | self.try_finish(cpu) |
321 | 0 | .map_err(error::erase::<InputTooLongError>) |
322 | 0 | .unwrap() |
323 | 0 | } Unexecuted instantiation: <ring::digest::Context>::finish Unexecuted instantiation: <ring::digest::Context>::finish |
324 | | |
325 | 0 | pub(crate) fn try_finish( |
326 | 0 | mut self, |
327 | 0 | cpu_features: cpu::Features, |
328 | 0 | ) -> Result<Digest, InputTooLongError> { |
329 | 0 | self.block |
330 | 0 | .try_finish(&mut self.pending, self.num_pending, cpu_features) |
331 | 0 | .map_err(|err| match err { |
332 | 0 | FinishError::InputTooLong(i) => i, |
333 | | FinishError::PendingNotAPartialBlock(_) => { |
334 | | // Due to invariant. |
335 | 0 | unreachable!() |
336 | | } |
337 | 0 | }) Unexecuted instantiation: <ring::digest::Context>::try_finish::{closure#0}Unexecuted instantiation: <ring::digest::Context>::try_finish::{closure#0} |
338 | 0 | } Unexecuted instantiation: <ring::digest::Context>::try_finish Unexecuted instantiation: <ring::digest::Context>::try_finish |
339 | | |
340 | | /// The algorithm that this context is using. |
341 | | #[inline(always)] |
342 | 0 | pub fn algorithm(&self) -> &'static Algorithm { |
343 | 0 | self.block.algorithm |
344 | 0 | } Unexecuted instantiation: <ring::digest::Context>::algorithm Unexecuted instantiation: <ring::digest::Context>::algorithm |
345 | | |
346 | | /// Serialize the Context to bytes. |
347 | | /// Format: [BlockContext bytes] [num_pending (8 bytes)] [pending buffer (num_pending bytes)] |
348 | 0 | pub fn to_bytes(&self) -> alloc::vec::Vec<u8> { |
349 | 0 | let mut bytes = self.block.to_bytes(); |
350 | | |
351 | | // Serialize num_pending |
352 | 0 | bytes.extend_from_slice(&(self.num_pending as u64).to_le_bytes()); |
353 | | |
354 | | // Serialize pending buffer (only the bytes that are actually pending) |
355 | 0 | bytes.extend_from_slice(&self.pending[..self.num_pending]); |
356 | | |
357 | 0 | bytes |
358 | 0 | } Unexecuted instantiation: <ring::digest::Context>::to_bytes Unexecuted instantiation: <ring::digest::Context>::to_bytes |
359 | | |
360 | | /// Deserialize a Context from bytes. |
361 | 0 | pub fn from_bytes(bytes: &[u8]) -> Result<Self, ()> { |
362 | | // Need at least: 1 (alg_id) + 8 (completed_bytes) + 32 (min state) + 8 (num_pending) |
363 | 0 | if bytes.len() < 49 { |
364 | 0 | return Err(()); |
365 | 0 | } |
366 | | |
367 | | // Find where BlockContext ends by determining state size |
368 | | // Algorithm ID is at bytes[0] |
369 | 0 | let state_size = match bytes[0] { |
370 | 0 | 1 | 2 => 32, // SHA1, SHA256 use 32-byte state |
371 | 0 | 3 | 4 | 5 => 64, // SHA384, SHA512, SHA512_256 use 64-byte state |
372 | 0 | _ => return Err(()), |
373 | | }; |
374 | | |
375 | 0 | let block_ctx_size = 1 + 8 + state_size; // alg_id + completed_bytes + state |
376 | | |
377 | 0 | if bytes.len() < block_ctx_size + 8 { |
378 | 0 | return Err(()); |
379 | 0 | } |
380 | | |
381 | | // Deserialize BlockContext |
382 | 0 | let block = BlockContext::from_bytes(&bytes[..block_ctx_size])?; |
383 | | |
384 | | // Deserialize num_pending |
385 | 0 | let num_pending_bytes = &bytes[block_ctx_size..block_ctx_size + 8]; |
386 | 0 | let num_pending = u64::from_le_bytes([ |
387 | 0 | num_pending_bytes[0], |
388 | 0 | num_pending_bytes[1], |
389 | 0 | num_pending_bytes[2], |
390 | 0 | num_pending_bytes[3], |
391 | 0 | num_pending_bytes[4], |
392 | 0 | num_pending_bytes[5], |
393 | 0 | num_pending_bytes[6], |
394 | 0 | num_pending_bytes[7], |
395 | 0 | ]) as usize; |
396 | | |
397 | | // Validate num_pending |
398 | 0 | let block_len = block.algorithm.block_len(); |
399 | 0 | if num_pending >= block_len { |
400 | 0 | return Err(()); |
401 | 0 | } |
402 | | |
403 | 0 | if bytes.len() < block_ctx_size + 8 + num_pending { |
404 | 0 | return Err(()); |
405 | 0 | } |
406 | | |
407 | | // Deserialize pending buffer |
408 | 0 | let mut pending = [0u8; MAX_BLOCK_LEN]; |
409 | 0 | pending[..num_pending] |
410 | 0 | .copy_from_slice(&bytes[block_ctx_size + 8..block_ctx_size + 8 + num_pending]); |
411 | | |
412 | 0 | Ok(Self { |
413 | 0 | block, |
414 | 0 | pending, |
415 | 0 | num_pending, |
416 | 0 | }) |
417 | 0 | } Unexecuted instantiation: <ring::digest::Context>::from_bytes Unexecuted instantiation: <ring::digest::Context>::from_bytes |
418 | | } |
419 | | |
420 | | /// Returns the digest of `data` using the given digest algorithm. |
421 | 0 | pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest { |
422 | 0 | let cpu = cpu::features(); |
423 | 0 | Digest::compute_from(algorithm, data, cpu) |
424 | 0 | .map_err(error::erase::<InputTooLongError>) |
425 | 0 | .unwrap() |
426 | 0 | } Unexecuted instantiation: ring::digest::digest Unexecuted instantiation: ring::digest::digest |
427 | | |
428 | | /// A calculated digest value. |
429 | | /// |
430 | | /// Use [`Self::as_ref`] to get the value as a `&[u8]`. |
431 | | #[derive(Clone, Copy)] |
432 | | pub struct Digest { |
433 | | value: Output, |
434 | | algorithm: &'static Algorithm, |
435 | | } |
436 | | |
437 | | impl Digest { |
438 | 0 | pub(crate) fn compute_from( |
439 | 0 | algorithm: &'static Algorithm, |
440 | 0 | data: &[u8], |
441 | 0 | cpu: cpu::Features, |
442 | 0 | ) -> Result<Self, InputTooLongError> { |
443 | 0 | let mut ctx = Context::new(algorithm); |
444 | 0 | ctx.update(data); |
445 | 0 | ctx.try_finish(cpu) |
446 | 0 | } Unexecuted instantiation: <ring::digest::Digest>::compute_from Unexecuted instantiation: <ring::digest::Digest>::compute_from |
447 | | |
448 | | /// The algorithm that was used to calculate the digest value. |
449 | | #[inline(always)] |
450 | 0 | pub fn algorithm(&self) -> &'static Algorithm { |
451 | 0 | self.algorithm |
452 | 0 | } Unexecuted instantiation: <ring::digest::Digest>::algorithm Unexecuted instantiation: <ring::digest::Digest>::algorithm |
453 | | } |
454 | | |
455 | | impl AsRef<[u8]> for Digest { |
456 | | #[inline(always)] |
457 | 0 | fn as_ref(&self) -> &[u8] { |
458 | 0 | &self.value.0[..self.algorithm.output_len()] |
459 | 0 | } Unexecuted instantiation: <ring::digest::Digest as core::convert::AsRef<[u8]>>::as_ref Unexecuted instantiation: <ring::digest::Digest as core::convert::AsRef<[u8]>>::as_ref |
460 | | } |
461 | | |
462 | | impl core::fmt::Debug for Digest { |
463 | 0 | fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { |
464 | 0 | write!(fmt, "{:?}:", self.algorithm)?; |
465 | 0 | debug::write_hex_bytes(fmt, self.as_ref()) |
466 | 0 | } Unexecuted instantiation: <ring::digest::Digest as core::fmt::Debug>::fmt Unexecuted instantiation: <ring::digest::Digest as core::fmt::Debug>::fmt |
467 | | } |
468 | | |
469 | | /// A digest algorithm. |
470 | | pub struct Algorithm { |
471 | | output_len: OutputLen, |
472 | | chaining_len: usize, |
473 | | block_len: BlockLen, |
474 | | |
475 | | /// `block_data_order` processes all the full blocks of data in `data`. It |
476 | | /// returns the number of bytes processed and the unprocessed data, which |
477 | | /// is guaranteed to be less than `block_len` bytes long. |
478 | | block_data_order: for<'d> fn( |
479 | | state: &mut DynState, |
480 | | data: &'d [u8], |
481 | | cpu_features: cpu::Features, |
482 | | ) -> (usize, &'d [u8]), |
483 | | |
484 | | initial_state: DynState, |
485 | | |
486 | | id: AlgorithmID, |
487 | | } |
488 | | |
489 | | #[derive(Debug, Eq, PartialEq)] |
490 | | enum AlgorithmID { |
491 | | SHA1, |
492 | | SHA256, |
493 | | SHA384, |
494 | | SHA512, |
495 | | SHA512_256, |
496 | | } |
497 | | |
498 | | impl PartialEq for Algorithm { |
499 | 0 | fn eq(&self, other: &Self) -> bool { |
500 | 0 | self.id == other.id |
501 | 0 | } Unexecuted instantiation: <ring::digest::Algorithm as core::cmp::PartialEq>::eq Unexecuted instantiation: <ring::digest::Algorithm as core::cmp::PartialEq>::eq |
502 | | } |
503 | | |
504 | | impl Eq for Algorithm {} |
505 | | |
506 | | derive_debug_via_id!(Algorithm); |
507 | | |
508 | | impl Algorithm { |
509 | | /// The internal block length. |
510 | 0 | pub fn block_len(&self) -> usize { |
511 | 0 | self.block_len.into() |
512 | 0 | } Unexecuted instantiation: <ring::digest::Algorithm>::block_len Unexecuted instantiation: <ring::digest::Algorithm>::block_len |
513 | | |
514 | | /// The size of the chaining value of the digest function, in bytes. |
515 | | /// |
516 | | /// For non-truncated algorithms (SHA-1, SHA-256, SHA-512), this is equal |
517 | | /// to [`Self::output_len()`]. For truncated algorithms (e.g. SHA-384, |
518 | | /// SHA-512/256), this is equal to the length before truncation. This is |
519 | | /// mostly helpful for determining the size of an HMAC key that is |
520 | | /// appropriate for the digest algorithm. |
521 | 0 | pub fn chaining_len(&self) -> usize { |
522 | 0 | self.chaining_len |
523 | 0 | } Unexecuted instantiation: <ring::digest::Algorithm>::chaining_len Unexecuted instantiation: <ring::digest::Algorithm>::chaining_len |
524 | | |
525 | | /// The length of a finalized digest. |
526 | 0 | pub fn output_len(&self) -> usize { |
527 | 0 | self.output_len.into() |
528 | 0 | } Unexecuted instantiation: <ring::digest::Algorithm>::output_len Unexecuted instantiation: <ring::digest::Algorithm>::output_len |
529 | | } |
530 | | |
531 | | /// SHA-1 as specified in [FIPS 180-4]. Deprecated. |
532 | | /// |
533 | | /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
534 | | pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm { |
535 | | output_len: sha1::OUTPUT_LEN, |
536 | | chaining_len: sha1::CHAINING_LEN, |
537 | | block_len: sha1::BLOCK_LEN, |
538 | | block_data_order: dynstate::sha1_block_data_order, |
539 | | initial_state: DynState::new32([ |
540 | | Wrapping(0x67452301u32), |
541 | | Wrapping(0xefcdab89u32), |
542 | | Wrapping(0x98badcfeu32), |
543 | | Wrapping(0x10325476u32), |
544 | | Wrapping(0xc3d2e1f0u32), |
545 | | Wrapping(0), |
546 | | Wrapping(0), |
547 | | Wrapping(0), |
548 | | ]), |
549 | | id: AlgorithmID::SHA1, |
550 | | }; |
551 | | |
552 | | /// SHA-256 as specified in [FIPS 180-4]. |
553 | | /// |
554 | | /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
555 | | pub static SHA256: Algorithm = Algorithm { |
556 | | output_len: OutputLen::_256, |
557 | | chaining_len: SHA256_OUTPUT_LEN, |
558 | | block_len: SHA256_BLOCK_LEN, |
559 | | block_data_order: dynstate::sha256_block_data_order, |
560 | | initial_state: DynState::new32([ |
561 | | Wrapping(0x6a09e667u32), |
562 | | Wrapping(0xbb67ae85u32), |
563 | | Wrapping(0x3c6ef372u32), |
564 | | Wrapping(0xa54ff53au32), |
565 | | Wrapping(0x510e527fu32), |
566 | | Wrapping(0x9b05688cu32), |
567 | | Wrapping(0x1f83d9abu32), |
568 | | Wrapping(0x5be0cd19u32), |
569 | | ]), |
570 | | id: AlgorithmID::SHA256, |
571 | | }; |
572 | | |
573 | | /// SHA-384 as specified in [FIPS 180-4]. |
574 | | /// |
575 | | /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
576 | | pub static SHA384: Algorithm = Algorithm { |
577 | | output_len: OutputLen::_384, |
578 | | chaining_len: SHA512_OUTPUT_LEN, |
579 | | block_len: SHA512_BLOCK_LEN, |
580 | | block_data_order: dynstate::sha512_block_data_order, |
581 | | initial_state: DynState::new64([ |
582 | | Wrapping(0xcbbb9d5dc1059ed8), |
583 | | Wrapping(0x629a292a367cd507), |
584 | | Wrapping(0x9159015a3070dd17), |
585 | | Wrapping(0x152fecd8f70e5939), |
586 | | Wrapping(0x67332667ffc00b31), |
587 | | Wrapping(0x8eb44a8768581511), |
588 | | Wrapping(0xdb0c2e0d64f98fa7), |
589 | | Wrapping(0x47b5481dbefa4fa4), |
590 | | ]), |
591 | | id: AlgorithmID::SHA384, |
592 | | }; |
593 | | |
594 | | /// SHA-512 as specified in [FIPS 180-4]. |
595 | | /// |
596 | | /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
597 | | pub static SHA512: Algorithm = Algorithm { |
598 | | output_len: OutputLen::_512, |
599 | | chaining_len: SHA512_OUTPUT_LEN, |
600 | | block_len: SHA512_BLOCK_LEN, |
601 | | block_data_order: dynstate::sha512_block_data_order, |
602 | | initial_state: DynState::new64([ |
603 | | Wrapping(0x6a09e667f3bcc908), |
604 | | Wrapping(0xbb67ae8584caa73b), |
605 | | Wrapping(0x3c6ef372fe94f82b), |
606 | | Wrapping(0xa54ff53a5f1d36f1), |
607 | | Wrapping(0x510e527fade682d1), |
608 | | Wrapping(0x9b05688c2b3e6c1f), |
609 | | Wrapping(0x1f83d9abfb41bd6b), |
610 | | Wrapping(0x5be0cd19137e2179), |
611 | | ]), |
612 | | id: AlgorithmID::SHA512, |
613 | | }; |
614 | | |
615 | | /// SHA-512/256 as specified in [FIPS 180-4]. |
616 | | /// |
617 | | /// This is *not* the same as just truncating the output of SHA-512, as |
618 | | /// SHA-512/256 has its own initial state distinct from SHA-512's initial |
619 | | /// state. |
620 | | /// |
621 | | /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf |
622 | | pub static SHA512_256: Algorithm = Algorithm { |
623 | | output_len: OutputLen::_256, |
624 | | chaining_len: SHA512_OUTPUT_LEN, |
625 | | block_len: SHA512_BLOCK_LEN, |
626 | | block_data_order: dynstate::sha512_block_data_order, |
627 | | initial_state: DynState::new64([ |
628 | | Wrapping(0x22312194fc2bf72c), |
629 | | Wrapping(0x9f555fa3c84c64c2), |
630 | | Wrapping(0x2393b86b6f53b151), |
631 | | Wrapping(0x963877195940eabd), |
632 | | Wrapping(0x96283ee2a88effe3), |
633 | | Wrapping(0xbe5e1e2553863992), |
634 | | Wrapping(0x2b0199fc2c85b8aa), |
635 | | Wrapping(0x0eb72ddc81c52ca2), |
636 | | ]), |
637 | | id: AlgorithmID::SHA512_256, |
638 | | }; |
639 | | |
640 | | #[derive(Clone, Copy)] |
641 | | struct Output([u8; MAX_OUTPUT_LEN]); |
642 | | |
643 | | /// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms |
644 | | /// in this module. |
645 | | pub const MAX_BLOCK_LEN: usize = BlockLen::MAX.into(); |
646 | | |
647 | | /// The maximum output length ([`Algorithm::output_len()`]) of all the |
648 | | /// algorithms in this module. |
649 | | pub const MAX_OUTPUT_LEN: usize = OutputLen::MAX.into(); |
650 | | |
651 | | /// The maximum chaining length ([`Algorithm::chaining_len()`]) of all the |
652 | | /// algorithms in this module. |
653 | | pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN; |
654 | | |
655 | | #[inline] |
656 | 0 | fn format_output<T, F, const N: usize>(input: [Wrapping<T>; sha2::CHAINING_WORDS], f: F) -> Output |
657 | 0 | where |
658 | 0 | F: Fn(T) -> [u8; N], |
659 | 0 | T: Copy, |
660 | | { |
661 | 0 | let mut output = Output([0; MAX_OUTPUT_LEN]); |
662 | 0 | output |
663 | 0 | .0 |
664 | 0 | .chunks_mut(N) |
665 | 0 | .zip(input.iter().copied().map(|Wrapping(w)| f(w))) Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4>::{closure#0}Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8>::{closure#0}Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4>::{closure#0}Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8>::{closure#0} |
666 | 0 | .for_each(|(o, i)| { |
667 | 0 | o.copy_from_slice(&i); |
668 | 0 | }); Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4>::{closure#1}Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8>::{closure#1}Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4>::{closure#1}Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8>::{closure#1} |
669 | 0 | output |
670 | 0 | } Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4> Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8> Unexecuted instantiation: ring::digest::format_output::<u32, <u32>::to_be_bytes, 4> Unexecuted instantiation: ring::digest::format_output::<u64, <u64>::to_be_bytes, 8> |
671 | | |
672 | | /// The length of the output of SHA-1, in bytes. |
673 | | pub const SHA1_OUTPUT_LEN: usize = sha1::OUTPUT_LEN.into(); |
674 | | |
675 | | /// The length of the output of SHA-256, in bytes. |
676 | | pub const SHA256_OUTPUT_LEN: usize = OutputLen::_256.into(); |
677 | | |
678 | | /// The length of the output of SHA-384, in bytes. |
679 | | pub const SHA384_OUTPUT_LEN: usize = OutputLen::_384.into(); |
680 | | |
681 | | /// The length of the output of SHA-512, in bytes. |
682 | | pub const SHA512_OUTPUT_LEN: usize = OutputLen::_512.into(); |
683 | | |
684 | | /// The length of the output of SHA-512/256, in bytes. |
685 | | pub const SHA512_256_OUTPUT_LEN: usize = OutputLen::_256.into(); |
686 | | |
687 | | #[derive(Clone, Copy)] |
688 | | enum BlockLen { |
689 | | _512 = 512 / 8, |
690 | | _1024 = 1024 / 8, // MAX |
691 | | } |
692 | | |
693 | | impl BlockLen { |
694 | | const MAX: Self = Self::_1024; |
695 | | #[inline(always)] |
696 | 0 | const fn into(self) -> usize { |
697 | 0 | self as usize |
698 | 0 | } Unexecuted instantiation: <ring::digest::BlockLen>::into Unexecuted instantiation: <ring::digest::BlockLen>::into |
699 | | |
700 | | #[inline(always)] |
701 | 0 | const fn len_len(self) -> usize { |
702 | 0 | let len_len = match self { |
703 | 0 | BlockLen::_512 => LenLen::_64, |
704 | 0 | BlockLen::_1024 => LenLen::_128, |
705 | | }; |
706 | 0 | len_len as usize |
707 | 0 | } Unexecuted instantiation: <ring::digest::BlockLen>::len_len Unexecuted instantiation: <ring::digest::BlockLen>::len_len |
708 | | } |
709 | | |
710 | | #[derive(Clone, Copy)] |
711 | | enum LenLen { |
712 | | _64 = 64 / 8, |
713 | | _128 = 128 / 8, |
714 | | } |
715 | | |
716 | | #[derive(Clone, Copy)] |
717 | | enum OutputLen { |
718 | | _160 = 160 / 8, |
719 | | _256 = 256 / 8, |
720 | | _384 = 384 / 8, |
721 | | _512 = 512 / 8, // MAX |
722 | | } |
723 | | |
724 | | impl OutputLen { |
725 | | const MAX: Self = Self::_512; |
726 | | |
727 | | #[inline(always)] |
728 | 0 | const fn into(self) -> usize { |
729 | 0 | self as usize |
730 | 0 | } Unexecuted instantiation: <ring::digest::OutputLen>::into Unexecuted instantiation: <ring::digest::OutputLen>::into |
731 | | } |
732 | | |
733 | | #[cfg(test)] |
734 | | mod tests { |
735 | | mod max_input { |
736 | | extern crate alloc; |
737 | | use super::super::super::digest; |
738 | | use crate::polyfill::u64_from_usize; |
739 | | use alloc::vec; |
740 | | |
741 | | macro_rules! max_input_tests { |
742 | | ( $algorithm_name:ident ) => { |
743 | | mod $algorithm_name { |
744 | | use super::super::super::super::digest; |
745 | | |
746 | | #[test] |
747 | | fn max_input_test() { |
748 | | super::max_input_test(&digest::$algorithm_name); |
749 | | } |
750 | | |
751 | | #[test] |
752 | | #[should_panic] |
753 | | fn too_long_input_test_block() { |
754 | | super::too_long_input_test_block(&digest::$algorithm_name); |
755 | | } |
756 | | |
757 | | #[test] |
758 | | #[should_panic] |
759 | | fn too_long_input_test_byte() { |
760 | | super::too_long_input_test_byte(&digest::$algorithm_name); |
761 | | } |
762 | | } |
763 | | }; |
764 | | } |
765 | | |
766 | | fn max_input_test(alg: &'static digest::Algorithm) { |
767 | | let mut context = nearly_full_context(alg); |
768 | | let next_input = vec![0u8; alg.block_len() - 1]; |
769 | | context.update(&next_input); |
770 | | let _ = context.finish(); // no panic |
771 | | } |
772 | | |
773 | | fn too_long_input_test_block(alg: &'static digest::Algorithm) { |
774 | | let mut context = nearly_full_context(alg); |
775 | | let next_input = vec![0u8; alg.block_len()]; |
776 | | context.update(&next_input); |
777 | | let _ = context.finish(); // should panic |
778 | | } |
779 | | |
780 | | fn too_long_input_test_byte(alg: &'static digest::Algorithm) { |
781 | | let mut context = nearly_full_context(alg); |
782 | | let next_input = vec![0u8; alg.block_len() - 1]; |
783 | | context.update(&next_input); |
784 | | context.update(&[0]); |
785 | | let _ = context.finish(); // should panic |
786 | | } |
787 | | |
788 | | fn nearly_full_context(alg: &'static digest::Algorithm) -> digest::Context { |
789 | | // All implementations currently support up to 2^64-1 bits |
790 | | // of input; according to the spec, SHA-384 and SHA-512 |
791 | | // support up to 2^128-1, but that's not implemented yet. |
792 | | let max_bytes = 1u64 << (64 - 3); |
793 | | let max_blocks = max_bytes / u64_from_usize(alg.block_len()); |
794 | | let completed_bytes = (max_blocks - 1) * u64_from_usize(alg.block_len()); |
795 | | digest::Context { |
796 | | block: digest::BlockContext { |
797 | | state: alg.initial_state.clone(), |
798 | | completed_bytes, |
799 | | algorithm: alg, |
800 | | }, |
801 | | pending: [0u8; digest::MAX_BLOCK_LEN], |
802 | | num_pending: 0, |
803 | | } |
804 | | } |
805 | | |
806 | | max_input_tests!(SHA1_FOR_LEGACY_USE_ONLY); |
807 | | max_input_tests!(SHA256); |
808 | | max_input_tests!(SHA384); |
809 | | max_input_tests!(SHA512); |
810 | | } |
811 | | } |