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}