Skip to content

Commit ec417ab

Browse files
committed
kmac: Replace sha3 dependency with new cshake crate
1 parent 90b3da9 commit ec417ab

File tree

7 files changed

+166
-217
lines changed

7 files changed

+166
-217
lines changed

Cargo.lock

Lines changed: 10 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kmac/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ categories = ["cryptography", "no-std"]
1313
rust-version = "1.85"
1414

1515
[dependencies]
16+
cshake = { git = "https://github.com/RustCrypto/hashes", branch = "master" }
1617
digest = { version = "0.11.0", features = ["mac"] }
17-
sha3 = "0.11.0-rc.9"
1818

1919
[dev-dependencies]
2020
digest = { version = "0.11.0", features = ["dev"] }

kmac/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ use hex_literal::hex;
7878
let mut mac = Kmac256::new_customization(b"key material", b"customization").unwrap();
7979
mac.update(b"input message");
8080
let mut output = [0u8; 32];
81-
mac.finalize_into(&mut output);
81+
mac.finalize_into_buf(&mut output);
8282

8383
let expected = hex!("
8484
85fb77da3a35e4c4b0057c3151e6cc54

kmac/src/kmac.rs

Lines changed: 76 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,87 @@
11
use crate::encoding::{left_encode, right_encode};
2-
use crate::traits::{CShake, EagerHash};
3-
use core::fmt;
4-
use digest::block_api::{
5-
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, ExtendableOutputCore,
6-
FixedOutputCore, UpdateCore, XofReaderCore,
7-
};
2+
use cshake::CShake;
3+
use digest::block_api::BlockSizeUser;
84
use digest::common::KeySizeUser;
9-
use digest::{InvalidLength, Key, KeyInit, MacMarker, Output, OutputSizeUser};
5+
use digest::typenum::Unsigned;
6+
use digest::{ExtendableOutput, InvalidLength, Key, KeyInit, MacMarker, Update, XofReader};
107

11-
pub struct KmacCore<D: EagerHash> {
12-
digest: D::Core,
8+
/// Trait alias for CShake types usable with KMAC.
9+
pub trait CShakeUser: BlockSizeUser + Update + ExtendableOutput + Clone {
10+
fn new_kmac(customization: &[u8]) -> Self;
1311
}
1412

15-
impl<D: EagerHash> Clone for KmacCore<D> {
13+
impl CShakeUser for cshake::CShake128 {
14+
fn new_kmac(customization: &[u8]) -> Self {
15+
CShake::new_with_function_name(b"KMAC", customization)
16+
}
17+
}
18+
19+
impl CShakeUser for cshake::CShake256 {
20+
fn new_kmac(customization: &[u8]) -> Self {
21+
CShake::new_with_function_name(b"KMAC", customization)
22+
}
23+
}
24+
25+
pub struct KmacInner<D: CShakeUser> {
26+
cshake: D,
27+
}
28+
29+
impl<D: CShakeUser> Clone for KmacInner<D> {
1630
#[inline(always)]
1731
fn clone(&self) -> Self {
1832
Self {
19-
digest: self.digest.clone(),
33+
cshake: self.cshake.clone(),
2034
}
2135
}
2236
}
2337

24-
impl<D: EagerHash> MacMarker for KmacCore<D> {}
25-
26-
impl<D: EagerHash> BufferKindUser for KmacCore<D> {
27-
type BufferKind = Eager;
28-
}
38+
impl<D: CShakeUser> MacMarker for KmacInner<D> {}
2939

30-
impl<D: EagerHash> KeySizeUser for KmacCore<D> {
31-
type KeySize = <D::Core as BlockSizeUser>::BlockSize;
40+
impl<D: CShakeUser> KeySizeUser for KmacInner<D> {
41+
type KeySize = D::BlockSize;
3242
}
3343

34-
impl<D: EagerHash> BlockSizeUser for KmacCore<D> {
35-
type BlockSize = <D::Core as BlockSizeUser>::BlockSize;
44+
impl<D: CShakeUser> BlockSizeUser for KmacInner<D> {
45+
type BlockSize = D::BlockSize;
3646
}
3747

38-
impl<D: EagerHash> KmacCore<D> {
48+
impl<D: CShakeUser> KmacInner<D> {
3949
#[inline(always)]
4050
pub fn new_customization(key: &[u8], customisation: &[u8]) -> Self {
41-
// digest: bufpad(encode_string(K), bufsize) || X || right_encode(L)
42-
// where bufpad(X, w) = left_encode(len(w)) || X || zeros
43-
// where encode_string(K) = left_encode(len(K)) || K
44-
let mut digest = D::Core::new_cshake(customisation);
45-
let mut buffer = Buffer::<Self>::default();
51+
let mut cshake = D::new_kmac(customisation);
52+
let block_size = D::BlockSize::USIZE;
4653
let mut encode_buffer = [0u8; 9];
4754

48-
// bytepad, left_encode(w)
49-
buffer.digest_blocks(
50-
left_encode(D::block_size() as u64, &mut encode_buffer),
51-
|blocks| digest.update_blocks(blocks),
52-
);
53-
54-
// encode_string(K), left_encode(len(K)) -- length is in bits
55-
buffer.digest_blocks(
56-
left_encode(8 * key.len() as u64, &mut encode_buffer),
57-
|blocks| digest.update_blocks(blocks),
58-
);
59-
60-
// encode_string(K) copy K into blocks
61-
buffer.digest_blocks(key, |blocks| digest.update_blocks(blocks));
62-
63-
// bytepad, pad the key to the block size
64-
digest.update_blocks(&[buffer.pad_with_zeros()]);
55+
// bytepad: left_encode(w)
56+
let le_w = left_encode(block_size as u64, &mut encode_buffer);
57+
let mut total = le_w.len();
58+
cshake.update(le_w);
59+
60+
// encode_string(K): left_encode(8*len(K)) || K
61+
let le_k = left_encode(8 * key.len() as u64, &mut encode_buffer);
62+
total += le_k.len();
63+
cshake.update(le_k);
64+
65+
total += key.len();
66+
cshake.update(key);
67+
68+
// pad to block boundary
69+
let pad_len = (block_size - (total % block_size)) % block_size;
70+
if pad_len > 0 {
71+
let zeros = [0u8; 168]; // max block size
72+
let mut remaining = pad_len;
73+
while remaining > 0 {
74+
let chunk = core::cmp::min(remaining, zeros.len());
75+
cshake.update(&zeros[..chunk]);
76+
remaining -= chunk;
77+
}
78+
}
6579

66-
Self { digest }
80+
Self { cshake }
6781
}
6882
}
6983

70-
impl<D: EagerHash> KeyInit for KmacCore<D> {
84+
impl<D: CShakeUser> KeyInit for KmacInner<D> {
7185
#[inline]
7286
fn new(key: &Key<Self>) -> Self {
7387
Self::new_customization(key.as_slice(), &[])
@@ -79,68 +93,34 @@ impl<D: EagerHash> KeyInit for KmacCore<D> {
7993
}
8094
}
8195

82-
impl<D: EagerHash> UpdateCore for KmacCore<D> {
96+
impl<D: CShakeUser> Update for KmacInner<D> {
8397
#[inline(always)]
84-
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
85-
self.digest.update_blocks(blocks);
98+
fn update(&mut self, data: &[u8]) {
99+
self.cshake.update(data);
86100
}
87101
}
88102

89-
impl<D: EagerHash> KmacCore<D> {
90-
/// Finalizes the KMAC for any output array size.
103+
impl<D: CShakeUser> KmacInner<D> {
104+
/// Finalizes the KMAC for any output array size (fixed-length output).
91105
#[inline(always)]
92-
pub fn finalize_core(&mut self, buffer: &mut Buffer<Self>, out: &mut [u8]) {
106+
pub fn finalize_fixed_inner(mut self, out: &mut [u8]) {
93107
// right_encode(L), where L = output length in bits
94-
buffer.digest_blocks(
95-
right_encode(8 * out.len() as u64, &mut [0u8; 9]),
96-
|blocks| self.update_blocks(blocks),
97-
);
98-
99-
let mut reader = self.digest.finalize_xof_core(buffer);
100-
101-
let mut pos = 0;
102-
while pos < out.len() {
103-
let block = reader.read_block();
104-
let to_copy = core::cmp::min(out.len() - pos, block.len());
105-
out[pos..pos + to_copy].copy_from_slice(&block[..to_copy]);
106-
pos += to_copy;
107-
}
108-
}
109-
}
108+
let mut encode_buffer = [0u8; 9];
109+
let re = right_encode(8 * out.len() as u64, &mut encode_buffer);
110+
self.cshake.update(re);
110111

111-
impl<D: EagerHash> FixedOutputCore for KmacCore<D>
112-
where
113-
KmacCore<D>: OutputSizeUser,
114-
{
115-
#[inline(always)]
116-
fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
117-
self.finalize_core(buffer, out.as_mut_slice());
112+
let mut reader = self.cshake.finalize_xof();
113+
reader.read(out);
118114
}
119-
}
120-
121-
impl<D: EagerHash> ExtendableOutputCore for KmacCore<D> {
122-
type ReaderCore = <D::Core as ExtendableOutputCore>::ReaderCore;
123115

116+
/// Finalizes the KMAC for extendable output (XOF).
124117
#[inline(always)]
125-
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
118+
pub fn finalize_xof_inner(mut self) -> D::Reader {
126119
// right_encode(0), as L = 0 for extendable output
127-
buffer.digest_blocks(right_encode(0, &mut [0u8; 9]), |blocks| {
128-
self.update_blocks(blocks)
129-
});
130-
self.digest.finalize_xof_core(buffer)
131-
}
132-
}
133-
134-
impl<D: EagerHash + AlgorithmName> AlgorithmName for KmacCore<D> {
135-
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
136-
f.write_str("Kmac<")?;
137-
<D as AlgorithmName>::write_alg_name(f)?;
138-
f.write_str(">")
139-
}
140-
}
120+
let mut encode_buffer = [0u8; 9];
121+
let re = right_encode(0, &mut encode_buffer);
122+
self.cshake.update(re);
141123

142-
impl<D: EagerHash + fmt::Debug> fmt::Debug for KmacCore<D> {
143-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144-
f.write_str("KmacCore { ... }")
124+
self.cshake.finalize_xof()
145125
}
146126
}

0 commit comments

Comments
 (0)