ring/digest/
dynstate.rs

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
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) => {
40                format_output::<_, _, { size_of::<u64>() }>(state, u64::to_be_bytes)
41            }
42            Self::As32(state) => {
43                format_output::<_, _, { size_of::<u32>() }>(state, 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 = match state {
55        DynState::As32(state) => state,
56        _ => {
57            unreachable!();
58        }
59    };
60
61    let (full_blocks, leftover) = slice::as_chunks(data);
62    sha1::sha1_block_data_order(state, 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 = match state {
72        DynState::As32(state) => state,
73        _ => {
74            unreachable!();
75        }
76    };
77
78    let (full_blocks, leftover) = slice::as_chunks(data);
79    sha2::block_data_order_32(state, 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 = match state {
89        DynState::As64(state) => state,
90        _ => {
91            unreachable!();
92        }
93    };
94
95    let (full_blocks, leftover) = slice::as_chunks(data);
96    sha2::block_data_order_64(state, full_blocks, cpu_features);
97    (full_blocks.len() * sha2::SHA512_BLOCK_LEN.into(), leftover)
98}