portable_rustls/crypto/
hash.rs

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