Coverage Report

Created: 2026-04-01 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}