Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.8/src/digest.rs
Line
Count
Source (jump to first uncovered line)
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 AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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
// Note on why are we doing things the hard way: It would be easy to implement
22
// this using the C `EVP_MD`/`EVP_MD_CTX` interface. However, if we were to do
23
// things that way, we'd have a hard dependency on `malloc` and other overhead.
24
// The goal for this implementation is to drive the overhead as close to zero
25
// as possible.
26
27
use crate::{c, cpu, debug, polyfill};
28
use core::num::Wrapping;
29
30
mod sha1;
31
mod sha2;
32
33
#[derive(Clone)]
34
pub(crate) struct BlockContext {
35
    state: State,
36
37
    // Note that SHA-512 has a 128-bit input bit counter, but this
38
    // implementation only supports up to 2^64-1 input bits for all algorithms,
39
    // so a 64-bit counter is more than sufficient.
40
    completed_data_blocks: u64,
41
42
    /// The context's algorithm.
43
    pub algorithm: &'static Algorithm,
44
}
45
46
impl BlockContext {
47
0
    pub(crate) fn new(algorithm: &'static Algorithm) -> Self {
48
0
        Self {
49
0
            state: algorithm.initial_state,
50
0
            completed_data_blocks: 0,
51
0
            algorithm,
52
0
        }
53
0
    }
54
55
    #[inline]
56
0
    pub(crate) fn update(&mut self, input: &[u8]) {
57
0
        let num_blocks = input.len() / self.algorithm.block_len;
58
0
        assert_eq!(num_blocks * self.algorithm.block_len, input.len());
59
60
0
        if num_blocks > 0 {
61
0
            unsafe {
62
0
                self.block_data_order(input.as_ptr(), num_blocks, cpu::features());
63
0
            }
64
0
            self.completed_data_blocks = self
65
0
                .completed_data_blocks
66
0
                .checked_add(polyfill::u64_from_usize(num_blocks))
67
0
                .unwrap();
68
0
        }
69
0
    }
70
71
0
    pub(crate) fn finish(mut self, pending: &mut [u8], num_pending: usize) -> Digest {
72
0
        let block_len = self.algorithm.block_len;
73
0
        assert_eq!(pending.len(), block_len);
74
0
        assert!(num_pending <= pending.len());
75
76
0
        let mut padding_pos = num_pending;
77
0
        pending[padding_pos] = 0x80;
78
0
        padding_pos += 1;
79
0
80
0
        if padding_pos > block_len - self.algorithm.len_len {
81
0
            pending[padding_pos..block_len].fill(0);
82
0
            unsafe { self.block_data_order(pending.as_ptr(), 1, cpu::features()) };
83
0
            // We don't increase |self.completed_data_blocks| because the
84
0
            // padding isn't data, and so it isn't included in the data length.
85
0
            padding_pos = 0;
86
0
        }
87
88
0
        pending[padding_pos..(block_len - 8)].fill(0);
89
0
90
0
        // Output the length, in bits, in big endian order.
91
0
        let completed_data_bits = self
92
0
            .completed_data_blocks
93
0
            .checked_mul(polyfill::u64_from_usize(block_len))
94
0
            .unwrap()
95
0
            .checked_add(polyfill::u64_from_usize(num_pending))
96
0
            .unwrap()
97
0
            .checked_mul(8)
98
0
            .unwrap();
99
0
        pending[(block_len - 8)..block_len].copy_from_slice(&u64::to_be_bytes(completed_data_bits));
100
0
101
0
        unsafe { self.block_data_order(pending.as_ptr(), 1, cpu::features()) };
102
0
103
0
        Digest {
104
0
            algorithm: self.algorithm,
105
0
            value: (self.algorithm.format_output)(self.state),
106
0
        }
107
0
    }
108
109
0
    unsafe fn block_data_order(
110
0
        &mut self,
111
0
        pending: *const u8,
112
0
        num_blocks: usize,
113
0
        _cpu_features: cpu::Features,
114
0
    ) {
115
0
        // CPU features are inspected by assembly implementations.
116
0
        unsafe {
117
0
            (self.algorithm.block_data_order)(&mut self.state, pending, num_blocks);
118
0
        }
119
0
    }
120
}
121
122
/// A context for multi-step (Init-Update-Finish) digest calculations.
123
///
124
/// # Examples
125
///
126
/// ```
127
/// use ring::digest;
128
///
129
/// let one_shot = digest::digest(&digest::SHA384, b"hello, world");
130
///
131
/// let mut ctx = digest::Context::new(&digest::SHA384);
132
/// ctx.update(b"hello");
133
/// ctx.update(b", ");
134
/// ctx.update(b"world");
135
/// let multi_part = ctx.finish();
136
///
137
/// assert_eq!(&one_shot.as_ref(), &multi_part.as_ref());
138
/// ```
139
#[derive(Clone)]
140
pub struct Context {
141
    block: BlockContext,
142
    // TODO: More explicitly force 64-bit alignment for |pending|.
143
    pending: [u8; MAX_BLOCK_LEN],
144
    num_pending: usize,
145
}
146
147
impl Context {
148
    /// Constructs a new context.
149
0
    pub fn new(algorithm: &'static Algorithm) -> Self {
150
0
        Self {
151
0
            block: BlockContext::new(algorithm),
152
0
            pending: [0u8; MAX_BLOCK_LEN],
153
0
            num_pending: 0,
154
0
        }
155
0
    }
156
157
0
    pub(crate) fn clone_from(block: &BlockContext) -> Self {
158
0
        Self {
159
0
            block: block.clone(),
160
0
            pending: [0u8; MAX_BLOCK_LEN],
161
0
            num_pending: 0,
162
0
        }
163
0
    }
164
165
    /// Updates the digest with all the data in `data`.
166
0
    pub fn update(&mut self, data: &[u8]) {
167
0
        let block_len = self.block.algorithm.block_len;
168
0
        if data.len() < block_len - self.num_pending {
169
0
            self.pending[self.num_pending..(self.num_pending + data.len())].copy_from_slice(data);
170
0
            self.num_pending += data.len();
171
0
            return;
172
0
        }
173
0
174
0
        let mut remaining = data;
175
0
        if self.num_pending > 0 {
176
0
            let to_copy = block_len - self.num_pending;
177
0
            self.pending[self.num_pending..block_len].copy_from_slice(&data[..to_copy]);
178
0
            self.block.update(&self.pending[..block_len]);
179
0
            remaining = &remaining[to_copy..];
180
0
            self.num_pending = 0;
181
0
        }
182
183
0
        let num_blocks = remaining.len() / block_len;
184
0
        let num_to_save_for_later = remaining.len() % block_len;
185
0
        self.block.update(&remaining[..(num_blocks * block_len)]);
186
0
        if num_to_save_for_later > 0 {
187
0
            self.pending[..num_to_save_for_later]
188
0
                .copy_from_slice(&remaining[(remaining.len() - num_to_save_for_later)..]);
189
0
            self.num_pending = num_to_save_for_later;
190
0
        }
191
0
    }
192
193
    /// Finalizes the digest calculation and returns the digest value.
194
    ///
195
    /// `finish` consumes the context so it cannot be (mis-)used after `finish`
196
    /// has been called.
197
0
    pub fn finish(mut self) -> Digest {
198
0
        let block_len = self.block.algorithm.block_len;
199
0
        self.block
200
0
            .finish(&mut self.pending[..block_len], self.num_pending)
201
0
    }
202
203
    /// The algorithm that this context is using.
204
    #[inline(always)]
205
0
    pub fn algorithm(&self) -> &'static Algorithm {
206
0
        self.block.algorithm
207
0
    }
208
}
209
210
/// Returns the digest of `data` using the given digest algorithm.
211
///
212
/// # Examples:
213
///
214
/// ```
215
/// # #[cfg(feature = "alloc")]
216
/// # {
217
/// use ring::{digest, test};
218
/// let expected_hex = "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b";
219
/// let expected: Vec<u8> = test::from_hex(expected_hex).unwrap();
220
/// let actual = digest::digest(&digest::SHA256, b"hello, world");
221
///
222
/// assert_eq!(&expected, &actual.as_ref());
223
/// # }
224
/// ```
225
0
pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
226
0
    let mut ctx = Context::new(algorithm);
227
0
    ctx.update(data);
228
0
    ctx.finish()
229
0
}
230
231
/// A calculated digest value.
232
///
233
/// Use [`Self::as_ref`] to get the value as a `&[u8]`.
234
#[derive(Clone, Copy)]
235
pub struct Digest {
236
    value: Output,
237
    algorithm: &'static Algorithm,
238
}
239
240
impl Digest {
241
    /// The algorithm that was used to calculate the digest value.
242
    #[inline(always)]
243
0
    pub fn algorithm(&self) -> &'static Algorithm {
244
0
        self.algorithm
245
0
    }
246
}
247
248
impl AsRef<[u8]> for Digest {
249
    #[inline(always)]
250
0
    fn as_ref(&self) -> &[u8] {
251
0
        &self.value.0[..self.algorithm.output_len]
252
0
    }
253
}
254
255
impl core::fmt::Debug for Digest {
256
0
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
257
0
        write!(fmt, "{:?}:", self.algorithm)?;
258
0
        debug::write_hex_bytes(fmt, self.as_ref())
259
0
    }
260
}
261
262
/// A digest algorithm.
263
pub struct Algorithm {
264
    output_len: usize,
265
    chaining_len: usize,
266
    block_len: usize,
267
268
    /// The length of the length in the padding.
269
    len_len: usize,
270
271
    block_data_order: unsafe extern "C" fn(state: &mut State, data: *const u8, num: c::size_t),
272
    format_output: fn(input: State) -> Output,
273
274
    initial_state: State,
275
276
    id: AlgorithmID,
277
}
278
279
#[derive(Debug, Eq, PartialEq)]
280
enum AlgorithmID {
281
    SHA1,
282
    SHA256,
283
    SHA384,
284
    SHA512,
285
    SHA512_256,
286
}
287
288
impl PartialEq for Algorithm {
289
0
    fn eq(&self, other: &Self) -> bool {
290
0
        self.id == other.id
291
0
    }
292
}
293
294
impl Eq for Algorithm {}
295
296
derive_debug_via_id!(Algorithm);
297
298
impl Algorithm {
299
    /// The internal block length.
300
0
    pub fn block_len(&self) -> usize {
301
0
        self.block_len
302
0
    }
303
304
    /// The size of the chaining value of the digest function, in bytes.
305
    ///
306
    /// For non-truncated algorithms (SHA-1, SHA-256, SHA-512), this is equal
307
    /// to [`Self::output_len()`]. For truncated algorithms (e.g. SHA-384,
308
    /// SHA-512/256), this is equal to the length before truncation. This is
309
    /// mostly helpful for determining the size of an HMAC key that is
310
    /// appropriate for the digest algorithm.
311
0
    pub fn chaining_len(&self) -> usize {
312
0
        self.chaining_len
313
0
    }
314
315
    /// The length of a finalized digest.
316
0
    pub fn output_len(&self) -> usize {
317
0
        self.output_len
318
0
    }
319
}
320
321
/// SHA-1 as specified in [FIPS 180-4]. Deprecated.
322
///
323
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
324
pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
325
    output_len: sha1::OUTPUT_LEN,
326
    chaining_len: sha1::CHAINING_LEN,
327
    block_len: sha1::BLOCK_LEN,
328
    len_len: 64 / 8,
329
    block_data_order: sha1::block_data_order,
330
    format_output: sha256_format_output,
331
    initial_state: State {
332
        as32: [
333
            Wrapping(0x67452301u32),
334
            Wrapping(0xefcdab89u32),
335
            Wrapping(0x98badcfeu32),
336
            Wrapping(0x10325476u32),
337
            Wrapping(0xc3d2e1f0u32),
338
            Wrapping(0),
339
            Wrapping(0),
340
            Wrapping(0),
341
        ],
342
    },
343
    id: AlgorithmID::SHA1,
344
};
345
346
/// SHA-256 as specified in [FIPS 180-4].
347
///
348
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
349
pub static SHA256: Algorithm = Algorithm {
350
    output_len: SHA256_OUTPUT_LEN,
351
    chaining_len: SHA256_OUTPUT_LEN,
352
    block_len: 512 / 8,
353
    len_len: 64 / 8,
354
    block_data_order: sha2::sha256_block_data_order,
355
    format_output: sha256_format_output,
356
    initial_state: State {
357
        as32: [
358
            Wrapping(0x6a09e667u32),
359
            Wrapping(0xbb67ae85u32),
360
            Wrapping(0x3c6ef372u32),
361
            Wrapping(0xa54ff53au32),
362
            Wrapping(0x510e527fu32),
363
            Wrapping(0x9b05688cu32),
364
            Wrapping(0x1f83d9abu32),
365
            Wrapping(0x5be0cd19u32),
366
        ],
367
    },
368
    id: AlgorithmID::SHA256,
369
};
370
371
/// SHA-384 as specified in [FIPS 180-4].
372
///
373
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
374
pub static SHA384: Algorithm = Algorithm {
375
    output_len: SHA384_OUTPUT_LEN,
376
    chaining_len: SHA512_OUTPUT_LEN,
377
    block_len: SHA512_BLOCK_LEN,
378
    len_len: SHA512_LEN_LEN,
379
    block_data_order: sha2::sha512_block_data_order,
380
    format_output: sha512_format_output,
381
    initial_state: State {
382
        as64: [
383
            Wrapping(0xcbbb9d5dc1059ed8),
384
            Wrapping(0x629a292a367cd507),
385
            Wrapping(0x9159015a3070dd17),
386
            Wrapping(0x152fecd8f70e5939),
387
            Wrapping(0x67332667ffc00b31),
388
            Wrapping(0x8eb44a8768581511),
389
            Wrapping(0xdb0c2e0d64f98fa7),
390
            Wrapping(0x47b5481dbefa4fa4),
391
        ],
392
    },
393
    id: AlgorithmID::SHA384,
394
};
395
396
/// SHA-512 as specified in [FIPS 180-4].
397
///
398
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
399
pub static SHA512: Algorithm = Algorithm {
400
    output_len: SHA512_OUTPUT_LEN,
401
    chaining_len: SHA512_OUTPUT_LEN,
402
    block_len: SHA512_BLOCK_LEN,
403
    len_len: SHA512_LEN_LEN,
404
    block_data_order: sha2::sha512_block_data_order,
405
    format_output: sha512_format_output,
406
    initial_state: State {
407
        as64: [
408
            Wrapping(0x6a09e667f3bcc908),
409
            Wrapping(0xbb67ae8584caa73b),
410
            Wrapping(0x3c6ef372fe94f82b),
411
            Wrapping(0xa54ff53a5f1d36f1),
412
            Wrapping(0x510e527fade682d1),
413
            Wrapping(0x9b05688c2b3e6c1f),
414
            Wrapping(0x1f83d9abfb41bd6b),
415
            Wrapping(0x5be0cd19137e2179),
416
        ],
417
    },
418
    id: AlgorithmID::SHA512,
419
};
420
421
/// SHA-512/256 as specified in [FIPS 180-4].
422
///
423
/// This is *not* the same as just truncating the output of SHA-512, as
424
/// SHA-512/256 has its own initial state distinct from SHA-512's initial
425
/// state.
426
///
427
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
428
pub static SHA512_256: Algorithm = Algorithm {
429
    output_len: SHA512_256_OUTPUT_LEN,
430
    chaining_len: SHA512_OUTPUT_LEN,
431
    block_len: SHA512_BLOCK_LEN,
432
    len_len: SHA512_LEN_LEN,
433
    block_data_order: sha2::sha512_block_data_order,
434
    format_output: sha512_format_output,
435
    initial_state: State {
436
        as64: [
437
            Wrapping(0x22312194fc2bf72c),
438
            Wrapping(0x9f555fa3c84c64c2),
439
            Wrapping(0x2393b86b6f53b151),
440
            Wrapping(0x963877195940eabd),
441
            Wrapping(0x96283ee2a88effe3),
442
            Wrapping(0xbe5e1e2553863992),
443
            Wrapping(0x2b0199fc2c85b8aa),
444
            Wrapping(0x0eb72ddc81c52ca2),
445
        ],
446
    },
447
    id: AlgorithmID::SHA512_256,
448
};
449
450
#[derive(Clone, Copy)] // XXX: Why do we need to be `Copy`?
451
#[repr(C)]
452
union State {
453
    as64: [Wrapping<u64>; sha2::CHAINING_WORDS],
454
    as32: [Wrapping<u32>; sha2::CHAINING_WORDS],
455
}
456
457
#[derive(Clone, Copy)]
458
struct Output([u8; MAX_OUTPUT_LEN]);
459
460
/// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms
461
/// in this module.
462
pub const MAX_BLOCK_LEN: usize = 1024 / 8;
463
464
/// The maximum output length ([`Algorithm::output_len()`]) of all the
465
/// algorithms in this module.
466
pub const MAX_OUTPUT_LEN: usize = 512 / 8;
467
468
/// The maximum chaining length ([`Algorithm::chaining_len()`]) of all the
469
/// algorithms in this module.
470
pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN;
471
472
0
fn sha256_format_output(input: State) -> Output {
473
0
    let input = unsafe { input.as32 };
474
0
    format_output::<_, _, { core::mem::size_of::<u32>() }>(input, u32::to_be_bytes)
475
0
}
476
477
0
fn sha512_format_output(input: State) -> Output {
478
0
    let input = unsafe { input.as64 };
479
0
    format_output::<_, _, { core::mem::size_of::<u64>() }>(input, u64::to_be_bytes)
480
0
}
481
482
#[inline]
483
0
fn format_output<T, F, const N: usize>(input: [Wrapping<T>; sha2::CHAINING_WORDS], f: F) -> Output
484
0
where
485
0
    F: Fn(T) -> [u8; N],
486
0
    T: Copy,
487
0
{
488
0
    let mut output = Output([0; MAX_OUTPUT_LEN]);
489
0
    output
490
0
        .0
491
0
        .chunks_mut(N)
492
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}
493
0
        .for_each(|(o, i)| {
494
0
            o.copy_from_slice(&i);
495
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}
496
0
    output
497
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>
498
499
/// The length of the output of SHA-1, in bytes.
500
pub const SHA1_OUTPUT_LEN: usize = sha1::OUTPUT_LEN;
501
502
/// The length of the output of SHA-256, in bytes.
503
pub const SHA256_OUTPUT_LEN: usize = 256 / 8;
504
505
/// The length of the output of SHA-384, in bytes.
506
pub const SHA384_OUTPUT_LEN: usize = 384 / 8;
507
508
/// The length of the output of SHA-512, in bytes.
509
pub const SHA512_OUTPUT_LEN: usize = 512 / 8;
510
511
/// The length of the output of SHA-512/256, in bytes.
512
pub const SHA512_256_OUTPUT_LEN: usize = 256 / 8;
513
514
/// The length of a block for SHA-512-based algorithms, in bytes.
515
const SHA512_BLOCK_LEN: usize = 1024 / 8;
516
517
/// The length of the length field for SHA-512-based algorithms, in bytes.
518
const SHA512_LEN_LEN: usize = 128 / 8;
519
520
#[cfg(test)]
521
mod tests {
522
    mod max_input {
523
        extern crate alloc;
524
        use super::super::super::digest;
525
        use crate::polyfill;
526
        use alloc::vec;
527
528
        macro_rules! max_input_tests {
529
            ( $algorithm_name:ident ) => {
530
                mod $algorithm_name {
531
                    use super::super::super::super::digest;
532
533
                    #[test]
534
                    fn max_input_test() {
535
                        super::max_input_test(&digest::$algorithm_name);
536
                    }
537
538
                    #[test]
539
                    #[should_panic]
540
                    fn too_long_input_test_block() {
541
                        super::too_long_input_test_block(&digest::$algorithm_name);
542
                    }
543
544
                    #[test]
545
                    #[should_panic]
546
                    fn too_long_input_test_byte() {
547
                        super::too_long_input_test_byte(&digest::$algorithm_name);
548
                    }
549
                }
550
            };
551
        }
552
553
        fn max_input_test(alg: &'static digest::Algorithm) {
554
            let mut context = nearly_full_context(alg);
555
            let next_input = vec![0u8; alg.block_len - 1];
556
            context.update(&next_input);
557
            let _ = context.finish(); // no panic
558
        }
559
560
        fn too_long_input_test_block(alg: &'static digest::Algorithm) {
561
            let mut context = nearly_full_context(alg);
562
            let next_input = vec![0u8; alg.block_len];
563
            context.update(&next_input);
564
            let _ = context.finish(); // should panic
565
        }
566
567
        fn too_long_input_test_byte(alg: &'static digest::Algorithm) {
568
            let mut context = nearly_full_context(alg);
569
            let next_input = vec![0u8; alg.block_len - 1];
570
            context.update(&next_input); // no panic
571
            context.update(&[0]);
572
            let _ = context.finish(); // should panic
573
        }
574
575
        fn nearly_full_context(alg: &'static digest::Algorithm) -> digest::Context {
576
            // All implementations currently support up to 2^64-1 bits
577
            // of input; according to the spec, SHA-384 and SHA-512
578
            // support up to 2^128-1, but that's not implemented yet.
579
            let max_bytes = 1u64 << (64 - 3);
580
            let max_blocks = max_bytes / polyfill::u64_from_usize(alg.block_len);
581
            digest::Context {
582
                block: digest::BlockContext {
583
                    state: alg.initial_state,
584
                    completed_data_blocks: max_blocks - 1,
585
                    algorithm: alg,
586
                },
587
                pending: [0u8; digest::MAX_BLOCK_LEN],
588
                num_pending: 0,
589
            }
590
        }
591
592
        max_input_tests!(SHA1_FOR_LEGACY_USE_ONLY);
593
        max_input_tests!(SHA256);
594
        max_input_tests!(SHA384);
595
        max_input_tests!(SHA512);
596
    }
597
}