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 fn fips(&self) -> bool {
24 false
25 }
26}
27
28/// A hash output, stored as a value.
29pub struct Output {
30 buf: [u8; Self::MAX_LEN],
31 used: usize,
32}
33
34impl Output {
35 /// Build a `hash::Output` from a slice of no more than `Output::MAX_LEN` bytes.
36 pub fn new(bytes: &[u8]) -> Self {
37 let mut output = Self {
38 buf: [0u8; Self::MAX_LEN],
39 used: bytes.len(),
40 };
41 debug_assert!(bytes.len() <= Self::MAX_LEN);
42 output.buf[..bytes.len()].copy_from_slice(bytes);
43 output
44 }
45
46 /// Maximum supported hash output size: supports up to SHA512.
47 pub const MAX_LEN: usize = 64;
48}
49
50impl AsRef<[u8]> for Output {
51 fn as_ref(&self) -> &[u8] {
52 &self.buf[..self.used]
53 }
54}
55
56/// How to incrementally compute a hash.
57pub trait Context: Send + Sync {
58 /// Finish the computation, returning the resulting output.
59 ///
60 /// The computation remains valid, and more data can be added later with
61 /// [`Context::update()`].
62 ///
63 /// Compare with [`Context::finish()`] which consumes the computation
64 /// and prevents any further data being added. This can be more efficient
65 /// because it avoids a hash context copy to apply Merkle-Damgård padding
66 /// (if required).
67 fn fork_finish(&self) -> Output;
68
69 /// Fork the computation, producing another context that has the
70 /// same prefix as this one.
71 fn fork(&self) -> Box<dyn Context>;
72
73 /// Terminate and finish the computation, returning the resulting output.
74 ///
75 /// Further data cannot be added after this, because the context is consumed.
76 /// Compare [`Context::fork_finish()`].
77 fn finish(self: Box<Self>) -> Output;
78
79 /// Add `data` to computation.
80 fn update(&mut self, data: &[u8]);
81}