libcrux_blake2/
impl_digest_trait.rs1use crate::impl_hacl::*;
2use libcrux_traits::digest::{
3 arrayref, slice, DigestIncrementalBase, Hasher, InitializeDigestState, UpdateError,
4};
5
6use crate::impl_hacl::SupportsOutLen;
7
8macro_rules! impl_digest_traits {
9 ($out_size:ident, $type:ty, $blake2:ty, $hasher:ty, $set:ty, $builder:ty) => {
10 impl<const $out_size: usize> InitializeDigestState for $blake2
12 where
13 $set: SupportsOutLen<$out_size>,
15 {
16 fn new() -> Self {
17 <$builder>::new_unkeyed().build_const_digest_len().into()
18 }
19 }
20
21 impl<const $out_size: usize> arrayref::Hash<$out_size> for $type
23 where
24 $set: SupportsOutLen<$out_size>,
26 {
27 fn hash(
28 digest: &mut [u8; $out_size],
29 payload: &[u8],
30 ) -> Result<(), arrayref::HashError> {
31 let mut digest_state = <$blake2>::new();
32 <Self as DigestIncrementalBase>::update(&mut digest_state, payload).map_err(
33 |e| match e {
34 UpdateError::InvalidPayloadLength | UpdateError::MaximumLengthExceeded => {
35 arrayref::HashError::InvalidPayloadLength
36 }
37 UpdateError::Unknown => arrayref::HashError::Unknown,
38 },
39 )?;
40 <Self as arrayref::DigestIncremental<$out_size>>::finish(&mut digest_state, digest);
41
42 Ok(())
43 }
44 }
45 impl<const $out_size: usize> slice::Hash for $type
47 where
48 $set: SupportsOutLen<$out_size>,
50 {
51 fn hash(digest: &mut [u8], payload: &[u8]) -> Result<usize, slice::HashError> {
52 let digest: &mut [u8; $out_size] = digest
53 .try_into()
54 .map_err(|_| slice::HashError::InvalidDigestLength)?;
55
56 <Self as arrayref::Hash<$out_size>>::hash(digest, payload)?;
57
58 Ok($out_size)
59 }
60 }
61
62 impl<const $out_size: usize> DigestIncrementalBase for $type
64 where
65 $set: SupportsOutLen<$out_size>,
67 {
68 type IncrementalState = $blake2;
69
70 fn update(state: &mut Self::IncrementalState, chunk: &[u8]) -> Result<(), UpdateError> {
71 state.update(chunk).map_err(|e| match e {
73 Error::InvalidChunkLength => UpdateError::InvalidPayloadLength,
74 Error::MaximumLengthExceeded => UpdateError::MaximumLengthExceeded,
75 _ => UpdateError::Unknown,
76 })
77 }
78 fn reset(state: &mut Self::IncrementalState) {
79 state.reset()
80 }
81 }
82
83 impl<const $out_size: usize> slice::DigestIncremental for $type
85 where
86 $set: SupportsOutLen<$out_size>,
88 {
89 fn finish(
90 state: &mut Self::IncrementalState,
91 digest: &mut [u8],
92 ) -> Result<usize, slice::FinishError> {
93 let digest: &mut [u8; $out_size] = digest
94 .try_into()
95 .map_err(|_| slice::FinishError::InvalidDigestLength)?;
96 <Self as arrayref::DigestIncremental<$out_size>>::finish(state, digest);
97
98 Ok($out_size)
99 }
100 }
101
102 impl<const $out_size: usize> arrayref::DigestIncremental<$out_size> for $type
104 where
105 $set: SupportsOutLen<$out_size>,
107 {
108 fn finish(state: &mut Self::IncrementalState, dst: &mut [u8; $out_size]) {
109 state.finalize(dst)
110 }
111 }
112
113 impl<const $out_size: usize> From<$blake2> for $hasher
115 where
116 $set: SupportsOutLen<$out_size>,
118 {
119 fn from(state: $blake2) -> Self {
120 Self { state }
121 }
122 }
123 };
124}
125
126pub struct Blake2bHash<const OUT_SIZE: usize>;
130
131impl_digest_traits!(
132 OUT_SIZE,
133 Blake2bHash<OUT_SIZE>,
134 Blake2b<ConstKeyLenConstDigestLen<0, OUT_SIZE>>,
135 Blake2bHasher<OUT_SIZE>,
136 Blake2b<LengthBounds>,
137 Blake2bBuilder<'_, &()>
138);
139
140pub type Blake2bHasher<const OUT_SIZE: usize> = Hasher<OUT_SIZE, Blake2bHash<OUT_SIZE>>;
142
143pub struct Blake2sHash<const OUT_SIZE: usize>;
147impl_digest_traits!(
148 OUT_SIZE,
149 Blake2sHash<OUT_SIZE>,
150 Blake2s<ConstKeyLenConstDigestLen<0, OUT_SIZE>>,
151 Blake2sHasher<OUT_SIZE>,
152 Blake2s<LengthBounds>,
153 Blake2sBuilder<'_, &()>
154);
155
156pub type Blake2sHasher<const OUT_SIZE: usize> = Hasher<OUT_SIZE, Blake2sHash<OUT_SIZE>>;