Skip to main content

embedded_cal/plumbing/hash/
sha2short.rs

1// SPDX-FileCopyrightText: Inria-AIO, Cryspen, and Christian Amsüss
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4#[derive(PartialEq, Eq, Copy, Clone)]
5pub enum Sha2ShortVariant {
6    Sha244,
7    Sha256,
8}
9
10/// Trait indicating that there is hardware support for SHA2.
11///
12/// The assumptions on the hardware so far are:
13/// * It takes *most* data in chunks that are the block size.
14/// * The first chunk size may be different. (Yes that is odd; nonetheless, that is how the
15///   STM32WB55 works).
16/// * It may or may not add the padding. If it does add the padding, an incomplete block may be
17///   sent at finalization.
18/// * All those decisions are known at build time, and expressed in constants.
19pub trait Sha2Short {
20    /// Whether this trait is actually supported. See [`Plumbing`][super::super::Plumbing] docs for
21    /// rationale..
22    const SUPPORTED: bool;
23
24    /// If true, the user needs to send all the padding data into the implementation through the
25    /// [`Self::update()`] function.
26    const SEND_PADDING: bool;
27
28    /// Size of the first chunk to be sent to [`Self::update()`], if it differs from the block size.
29    ///
30    /// Implementations that do not need this special handling should set this to 0.
31    const FIRST_CHUNK_SIZE: usize;
32    /// If true, the [`Self::update()`] function can be passed data from consecutive blocks.
33    const UPDATE_MULTICHUNK: bool;
34
35    /// State containing an ongoing operation.
36    ///
37    /// Analogous to [`crate::HashProvider::State`].
38    type State: Sized + Clone;
39
40    /// Initiates a [`Self::State`] according to the selected algorithm.
41    fn init(&mut self, variant: Sha2ShortVariant) -> Self::State;
42    /// Iteratively sends data to be hashed into the instance.
43    ///
44    /// If [`Self::SEND_PADDING`] is true, data needs to (eventually) include the SHA-2 padding;
45    /// otherwise, no padding must be added by the caller.
46    ///
47    /// Data must be sent in chunks as described by `*CHUNK*` associated constants: The first chunk
48    /// must be of size [`Self::FIRST_CHUNK_SIZE`] (unless that is 0, then that empty slice is not
49    /// sent), subsequent chunks of the block size. If [`Self::UPDATE_MULTICHUNK`] is given,
50    /// multiple chunks (first and/or subsequent) can be passed in together for efficiency.
51    ///
52    /// Note that for the `SEND_PADDING = false` case, some data may be left after sending whole
53    /// chunks; that data is passed in at finalization.
54    ///
55    /// # Panics
56    ///
57    /// … if data lengths do not adhere to the `CHUNKS` configuration.
58    ///
59    /// (There is no need for the implementation to panic: It may also just produce a wrong result).
60    fn update(&mut self, instance: &mut Self::State, data: &[u8]);
61    /// Extracts the hash into a target slice.
62    ///
63    /// Implementations must accept overly long slices, and may write the full 32 byte rather than
64    /// the 28 byte of a SHA-244 if the output is long enough.
65    ///
66    /// # Panics
67    ///
68    /// * if the target array is insufficient for the type of hash, or
69    /// * if the last chunk data is too large and should really have been sent through the update
70    ///   function. (In particular, for `SEND_PADDING = true` implementations, if the last_chunk is
71    ///   not empty).
72    ///
73    /// (There is no need for the implementation to panic: It may also just produce a wrong result).
74    // FIXME the constraints on who must and may do what are a current guess, we should re-evaluate
75    // them. Maybe passing a 32-byte target array works better.
76    //
77    // Same goes for the last chunk -- can we accept more? Probably not, leave it up to the higher
78    // layer to do this just as it should be done.
79    fn finalize(&mut self, instance: Self::State, last_chunk: &[u8], target: &mut [u8]);
80
81    // FIXME: For platforms with costly suspension, should we provide an init-update-finish
82    // all-in-one method?
83}