Skip to main content

rustls/crypto/
hash.rs

1use alloc::boxed::Box;
2
3use pki_types::FipsStatus;
4
5use super::enums::HashAlgorithm;
6
7/// Describes a single cryptographic hash function.
8///
9/// This interface can do both one-shot and incremental hashing, using
10/// [`Hash::hash()`] and [`Hash::start()`] respectively.
11pub trait Hash: Send + Sync {
12    /// Start an incremental hash computation.
13    fn start(&self) -> Box<dyn Context>;
14
15    /// Return the output of this hash function with input `data`.
16    fn hash(&self, data: &[u8]) -> Output;
17
18    /// The length in bytes of this hash function's output.
19    fn output_len(&self) -> usize;
20
21    /// Which hash function this is, eg, `HashAlgorithm::SHA256`.
22    fn algorithm(&self) -> HashAlgorithm;
23
24    /// Return the FIPS validation status of this implementation.
25    fn fips(&self) -> FipsStatus {
26        FipsStatus::Unvalidated
27    }
28}
29
30/// A hash output, stored as a value.
31pub struct Output {
32    buf: [u8; Self::MAX_LEN],
33    used: usize,
34}
35
36impl Output {
37    /// Build a `hash::Output` from a slice of no more than `Output::MAX_LEN` bytes.
38    pub fn new(bytes: &[u8]) -> Self {
39        let mut output = Self {
40            buf: [0u8; Self::MAX_LEN],
41            used: bytes.len(),
42        };
43        debug_assert!(bytes.len() <= Self::MAX_LEN);
44        output.buf[..bytes.len()].copy_from_slice(bytes);
45        output
46    }
47
48    /// Maximum supported hash output size: supports up to SHA512.
49    pub const MAX_LEN: usize = 64;
50}
51
52impl AsRef<[u8]> for Output {
53    fn as_ref(&self) -> &[u8] {
54        &self.buf[..self.used]
55    }
56}
57
58/// How to incrementally compute a hash.
59pub trait Context: Send + Sync {
60    /// Finish the computation, returning the resulting output.
61    ///
62    /// The computation remains valid, and more data can be added later with
63    /// [`Context::update()`].
64    ///
65    /// Compare with [`Context::finish()`] which consumes the computation
66    /// and prevents any further data being added.  This can be more efficient
67    /// because it avoids a hash context copy to apply Merkle-Damgård padding
68    /// (if required).
69    fn fork_finish(&self) -> Output;
70
71    /// Fork the computation, producing another context that has the
72    /// same prefix as this one.
73    fn fork(&self) -> Box<dyn Context>;
74
75    /// Terminate and finish the computation, returning the resulting output.
76    ///
77    /// Further data cannot be added after this, because the context is consumed.
78    /// Compare [`Context::fork_finish()`].
79    fn finish(self: Box<Self>) -> Output;
80
81    /// Add `data` to computation.
82    fn update(&mut self, data: &[u8]);
83}