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
15use super::{format_output, sha1, sha2, Output};
16use crate::{cpu, polyfill::slice};
17use core::mem::size_of;
18
19// Invariant: When constructed with `new32` (resp. `new64`), `As32` (resp.
20// `As64`) is the active variant.
21// Invariant: The active variant never changes after initialization.
22#[derive(Clone)]
23pub(super) enum DynState {
24 As64(sha2::State64),
25 As32(sha2::State32),
26}
27
28impl DynState {
29 pub const fn new32(initial_state: sha2::State32) -> Self {
30 Self::As32(initial_state)
31 }
32
33 pub const fn new64(initial_state: sha2::State64) -> Self {
34 Self::As64(initial_state)
35 }
36
37 pub fn format_output(self) -> Output {
38 match self {
39 Self::As64(state: [Wrapping; 8]) => {
40 format_output::<_, _, { size_of::<u64>() }>(input:state, f:u64::to_be_bytes)
41 }
42 Self::As32(state: [Wrapping; 8]) => {
43 format_output::<_, _, { size_of::<u32>() }>(input:state, f:u32::to_be_bytes)
44 }
45 }
46 }
47}
48
49pub(super) fn sha1_block_data_order<'d>(
50 state: &mut DynState,
51 data: &'d [u8],
52 _cpu_features: cpu::Features,
53) -> (usize, &'d [u8]) {
54 let state: &mut [Wrapping; 8] = match state {
55 DynState::As32(state: &mut [Wrapping; 8]) => state,
56 _ => {
57 unreachable!();
58 }
59 };
60
61 let (full_blocks: AsChunks<'_, u8, _>, leftover: &[u8]) = slice::as_chunks(slice:data);
62 sha1::sha1_block_data_order(state, data:full_blocks);
63 (full_blocks.as_flattened().len(), leftover)
64}
65
66pub(super) fn sha256_block_data_order<'d>(
67 state: &mut DynState,
68 data: &'d [u8],
69 cpu_features: cpu::Features,
70) -> (usize, &'d [u8]) {
71 let state: &mut [Wrapping; 8] = match state {
72 DynState::As32(state: &mut [Wrapping; 8]) => state,
73 _ => {
74 unreachable!();
75 }
76 };
77
78 let (full_blocks: AsChunks<'_, u8, _>, leftover: &[u8]) = slice::as_chunks(slice:data);
79 sha2::block_data_order_32(state, data:full_blocks, cpu_features);
80 (full_blocks.len() * sha2::SHA256_BLOCK_LEN.into(), leftover)
81}
82
83pub(super) fn sha512_block_data_order<'d>(
84 state: &mut DynState,
85 data: &'d [u8],
86 cpu_features: cpu::Features,
87) -> (usize, &'d [u8]) {
88 let state: &mut [Wrapping; 8] = match state {
89 DynState::As64(state: &mut [Wrapping; 8]) => state,
90 _ => {
91 unreachable!();
92 }
93 };
94
95 let (full_blocks: AsChunks<'_, u8, _>, leftover: &[u8]) = slice::as_chunks(slice:data);
96 sha2::block_data_order_64(state, data:full_blocks, cpu_features);
97 (full_blocks.len() * sha2::SHA512_BLOCK_LEN.into(), leftover)
98}
99