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}