Skip to content

Commit 8f9f392

Browse files
committed
Migrate to newtype macros
1 parent 50ea2ee commit 8f9f392

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+3718
-3451
lines changed

.github/workflows/sha3.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
toolchain: ${{ matrix.rust }}
4343
targets: ${{ matrix.target }}
4444
- uses: RustCrypto/actions/cargo-hack-install@master
45-
- run: cargo hack build --target ${{ matrix.target }} --each-feature --exclude-features default,std,asm
45+
- run: cargo hack build --target ${{ matrix.target }} --each-feature --exclude-features default,asm
4646

4747
test:
4848
needs: set-msrv

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ opt-level = 2
3131

3232
[patch.crates-io]
3333
# https://github.com/RustCrypto/traits/pull/1787
34-
digest = { git = "https://github.com/RustCrypto/traits" }
34+
# https://github.com/RustCrypto/traits/pull/1799
35+
digest = { git = "https://github.com/RustCrypto/traits", branch = "digest/newtype" }

ascon-hash/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ hex-literal = "1"
2626
base16ct = { version = "0.2", features = ["alloc"] }
2727

2828
[features]
29-
default = ["std"]
30-
std = ["digest/std"]
29+
default = ["alloc"]
30+
alloc = ["digest/alloc"]
3131
zeroize = ["ascon/zeroize", "digest/zeroize"]
3232

3333
[package.metadata.docs.rs]

belt-hash/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ hex-literal = "1"
2222
base16ct = { version = "0.2", features = ["alloc"] }
2323

2424
[features]
25-
default = ["oid", "std"]
26-
std = ["digest/std"]
25+
default = ["alloc", "oid"]
26+
alloc = ["digest/alloc"]
2727
oid = ["digest/oid"]
2828
zeroize = ["digest/zeroize"]
2929

belt-hash/src/block_api.rs

+232
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
use belt_block::belt_block_raw;
2+
use core::fmt;
3+
use digest::{
4+
HashMarker, Output,
5+
block_buffer::Eager,
6+
core_api::{
7+
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore,
8+
OutputSizeUser, Reset, UpdateCore,
9+
},
10+
crypto_common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
11+
typenum::{U32, U64, Unsigned},
12+
};
13+
14+
const H0: [u32; 8] = [
15+
0xC8BA94B1, 0x3BF5080A, 0x8E006D36, 0xE45D4A58, 0x9DFA0485, 0xACC7B61B, 0xC2722E25, 0x0DCEFD02,
16+
];
17+
18+
/// Core BelT hasher state.
19+
#[derive(Clone)]
20+
pub struct BeltHashCore {
21+
r: u128,
22+
s: [u32; 4],
23+
h: [u32; 8],
24+
}
25+
26+
impl BeltHashCore {
27+
fn compress_block(&mut self, block: &Block<Self>) {
28+
let x1 = read_u32s(&block[..16]);
29+
let x2 = read_u32s(&block[16..]);
30+
let (t, h) = belt_compress(x1, x2, self.h);
31+
self.h = h;
32+
self.s = xor(self.s, t);
33+
}
34+
}
35+
36+
impl HashMarker for BeltHashCore {}
37+
38+
impl BlockSizeUser for BeltHashCore {
39+
type BlockSize = U32;
40+
}
41+
42+
impl BufferKindUser for BeltHashCore {
43+
type BufferKind = Eager;
44+
}
45+
46+
impl OutputSizeUser for BeltHashCore {
47+
type OutputSize = U32;
48+
}
49+
50+
impl UpdateCore for BeltHashCore {
51+
#[inline]
52+
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
53+
self.r = self.r.wrapping_add(blocks.len() as u128);
54+
for block in blocks {
55+
self.compress_block(block);
56+
}
57+
}
58+
}
59+
60+
impl FixedOutputCore for BeltHashCore {
61+
#[inline]
62+
fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
63+
let pos = buffer.get_pos();
64+
if pos != 0 {
65+
let block = buffer.pad_with_zeros();
66+
self.compress_block(&block);
67+
}
68+
let bs = Self::BlockSize::USIZE as u128;
69+
let r = encode_r(8 * ((bs * self.r) + pos as u128));
70+
let (_, y) = belt_compress(r, self.s, self.h);
71+
write_u32s(&y, out);
72+
}
73+
}
74+
75+
impl Default for BeltHashCore {
76+
#[inline]
77+
fn default() -> Self {
78+
Self {
79+
r: 0,
80+
s: [0; 4],
81+
h: H0,
82+
}
83+
}
84+
}
85+
86+
impl Reset for BeltHashCore {
87+
#[inline]
88+
fn reset(&mut self) {
89+
*self = Default::default();
90+
}
91+
}
92+
93+
impl AlgorithmName for BeltHashCore {
94+
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
95+
f.write_str("BeltHash")
96+
}
97+
}
98+
99+
impl fmt::Debug for BeltHashCore {
100+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101+
f.write_str("BeltHashCore { ... }")
102+
}
103+
}
104+
105+
impl Drop for BeltHashCore {
106+
fn drop(&mut self) {
107+
#[cfg(feature = "zeroize")]
108+
{
109+
use digest::zeroize::Zeroize;
110+
self.r.zeroize();
111+
self.s.zeroize();
112+
self.h.zeroize();
113+
}
114+
}
115+
}
116+
117+
#[cfg(feature = "zeroize")]
118+
impl digest::zeroize::ZeroizeOnDrop for BeltHashCore {}
119+
120+
impl SerializableState for BeltHashCore {
121+
type SerializedStateSize = U64;
122+
123+
fn serialize(&self) -> SerializedState<Self> {
124+
let mut dst = SerializedState::<Self>::default();
125+
126+
let (r_dst, tail) = dst.split_at_mut(16);
127+
let (s_dst, h_dst) = tail.split_at_mut(16);
128+
129+
r_dst.copy_from_slice(&self.r.to_le_bytes());
130+
write_u32s(&self.s, s_dst);
131+
write_u32s(&self.h, h_dst);
132+
133+
dst
134+
}
135+
136+
fn deserialize(
137+
serialized_state: &SerializedState<Self>,
138+
) -> Result<Self, DeserializeStateError> {
139+
let (r_src, tail) = serialized_state.split_at(16);
140+
let (s_src, h_src) = tail.split_at(16);
141+
142+
Ok(Self {
143+
r: u128::from_le_bytes(r_src.try_into().unwrap()),
144+
s: read_u32s(s_src),
145+
h: read_u32s(h_src),
146+
})
147+
}
148+
}
149+
150+
/// Compression function described in the section 6.3.2
151+
#[inline(always)]
152+
pub fn belt_compress(x1: [u32; 4], x2: [u32; 4], x34: [u32; 8]) -> ([u32; 4], [u32; 8]) {
153+
let x3 = [x34[0], x34[1], x34[2], x34[3]];
154+
let x4 = [x34[4], x34[5], x34[6], x34[7]];
155+
156+
// Step 2
157+
let t1 = belt_block_raw(xor(x3, x4), &concat(x1, x2));
158+
let s = xor(xor(t1, x3), x4);
159+
// Step 3
160+
let t2 = belt_block_raw(x1, &concat(s, x4));
161+
let y1 = xor(t2, x1);
162+
// Step 4
163+
let t3 = belt_block_raw(x2, &concat(s.map(|v| !v), x3));
164+
let y2 = xor(t3, x2);
165+
// Step 5
166+
(s, concat(y1, y2))
167+
}
168+
169+
#[inline(always)]
170+
fn xor(a: [u32; 4], b: [u32; 4]) -> [u32; 4] {
171+
[a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]]
172+
}
173+
174+
#[inline(always)]
175+
fn concat(a: [u32; 4], b: [u32; 4]) -> [u32; 8] {
176+
[a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]]
177+
}
178+
179+
#[inline(always)]
180+
fn read_u32s<const N: usize>(src: &[u8]) -> [u32; N] {
181+
assert_eq!(src.len(), 4 * N);
182+
183+
let mut dst = [0u32; N];
184+
for (dst, src) in dst.iter_mut().zip(src.chunks_exact(4)) {
185+
*dst = u32::from_le_bytes(src.try_into().unwrap());
186+
}
187+
dst
188+
}
189+
190+
#[inline(always)]
191+
fn write_u32s(src: &[u32], dst: &mut [u8]) {
192+
assert_eq!(4 * src.len(), dst.len());
193+
for (src, dst) in src.iter().zip(dst.chunks_exact_mut(4)) {
194+
dst.copy_from_slice(&src.to_le_bytes());
195+
}
196+
}
197+
198+
#[inline(always)]
199+
fn encode_r(r: u128) -> [u32; 4] {
200+
core::array::from_fn(|i| (r >> (32 * i)) as u32)
201+
}
202+
203+
#[cfg(test)]
204+
mod tests {
205+
use super::{belt_compress, read_u32s};
206+
use hex_literal::hex;
207+
208+
/// Test vectors for the `belt-compress` functions from the
209+
/// specification (Table A.8).
210+
#[test]
211+
fn compress() {
212+
let x = &hex!(
213+
"B194BAC8 0A08F53B 366D008E 584A5DE4"
214+
"8504FA9D 1BB6C7AC 252E72C2 02FDCE0D"
215+
"5BE3D612 17B96181 FE6786AD 716B890B"
216+
"5CB0C0FF 33C356B8 35C405AE D8E07F99"
217+
);
218+
let expected_s = &hex!("46FE7425 C9B181EB 41DFEE3E 72163D5A");
219+
let expected_y = &hex!(
220+
"ED2F5481 D593F40D 87FCE37D 6BC1A2E1"
221+
"B7D1A2CC 975C82D3 C0497488 C90D99D8"
222+
);
223+
let x1 = read_u32s(&x[..16]);
224+
let x2 = read_u32s(&x[16..32]);
225+
let x34 = read_u32s(&x[32..]);
226+
227+
let (s, y) = belt_compress(x1, x2, x34);
228+
229+
assert_eq!(s, read_u32s(expected_s));
230+
assert_eq!(y, read_u32s(expected_y));
231+
}
232+
}

0 commit comments

Comments
 (0)