libcrux_traits/
digest.rs

1//! This module provides common interface traits for digest/hashing functionality.
2
3pub mod arrayref;
4pub mod owned;
5pub mod slice;
6
7#[cfg(feature = "generic-tests")]
8pub mod tests;
9
10/// Error indicating that updating the digest state failed.
11#[derive(Debug, PartialEq)]
12pub enum UpdateError {
13    /// The length of the provided payload is invalid.
14    InvalidPayloadLength,
15    ///The maximum input length is exceeded.
16    MaximumLengthExceeded,
17    /// Unknown error.
18    Unknown,
19}
20
21impl core::fmt::Display for UpdateError {
22    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23        let text = match self {
24            UpdateError::InvalidPayloadLength => "the length of the provided payload is invalid",
25            UpdateError::MaximumLengthExceeded => "the maximum input length is exceeded",
26            UpdateError::Unknown => "indicates an unknown error",
27        };
28
29        f.write_str(text)
30    }
31}
32
33#[cfg(feature = "error-in-core")]
34mod error_in_core {
35
36    impl core::error::Error for super::UpdateError {}
37}
38
39/// Base trait for incremental functionality.
40///
41/// Traits that are built on top of this trait:
42/// - [`slice::DigestIncremental`]
43/// - [`arrayref::DigestIncremental`]
44/// - [`owned::DigestIncremental`]
45pub trait DigestIncrementalBase {
46    /// The digest state.
47    type IncrementalState: InitializeDigestState;
48    /// Reset the digest state.
49    fn reset(state: &mut Self::IncrementalState);
50    /// Update the digest state with the `payload`.
51    fn update(state: &mut Self::IncrementalState, payload: &[u8]) -> Result<(), UpdateError>;
52}
53
54/// Base trait for digest state initialization.
55pub trait InitializeDigestState {
56    /// Initialize a new incremental digest state.
57    fn new() -> Self;
58}
59
60#[derive(Clone)]
61/// A generic hasher. This hasher maintains the incremental digest state.
62pub struct Hasher<const N: usize, D: DigestIncrementalBase> {
63    /// The digest state.
64    pub state: D::IncrementalState,
65}
66
67impl<const N: usize, D: arrayref::DigestIncremental<N>> Default for Hasher<N, D>
68where
69    D::IncrementalState: Default,
70{
71    fn default() -> Self {
72        Self {
73            state: Default::default(),
74        }
75    }
76}
77
78impl<const N: usize, D: DigestIncrementalBase + slice::Hash> Hasher<N, D> {
79    /// Oneshot API. Hash into a digest buffer, provided as a `&mut [u8]` slice.
80    pub fn hash_slice(digest: &mut [u8], payload: &[u8]) -> Result<usize, slice::HashError> {
81        D::hash(digest, payload)
82    }
83}
84
85impl<const N: usize, D: slice::DigestIncremental> Hasher<N, D> {
86    /// Finalize and write into a digest buffer, provided as a `&mut [u8]` slice.
87    pub fn finish_slice(&mut self, digest: &mut [u8]) -> Result<usize, slice::FinishError> {
88        D::finish(&mut self.state, digest)
89    }
90}
91
92impl<const N: usize, D: DigestIncrementalBase> Hasher<N, D> {
93    /// Update the digest state with the `payload`.
94    pub fn update(&mut self, payload: &[u8]) -> Result<(), UpdateError> {
95        D::update(&mut self.state, payload)
96    }
97    /// Reset the digest state.
98    pub fn reset(&mut self) {
99        D::reset(&mut self.state)
100    }
101
102    /// Initialize a hasher.
103    pub fn new() -> Self {
104        Self {
105            state: D::IncrementalState::new(),
106        }
107    }
108}
109
110impl<const N: usize, D: arrayref::DigestIncremental<N>> Hasher<N, D> {
111    /// Finalize and write into a digest buffer, provided as a `&mut [u8; N]` array reference.
112    pub fn finish(&mut self, digest: &mut [u8; N]) {
113        D::finish(&mut self.state, digest)
114    }
115    /// owned version of `finish()`
116    pub fn finish_to_owned(&mut self) -> [u8; N] {
117        <D as owned::DigestIncremental<N>>::finish(&mut self.state)
118    }
119}
120
121impl<const N: usize, D: DigestIncrementalBase + arrayref::Hash<N>> Hasher<N, D> {
122    /// Oneshot API. Hash into a digest buffer, provided as a `&mut [u8; N]` array reference.
123    pub fn hash(digest: &mut [u8; N], payload: &[u8]) -> Result<(), arrayref::HashError> {
124        D::hash(digest, payload)
125    }
126    /// owned version of `hash()`
127    pub fn hash_to_owned(payload: &[u8]) -> Result<[u8; N], arrayref::HashError> {
128        <D as owned::Hash<N>>::hash(payload)
129    }
130}