Skip to content

Commit 8f93676

Browse files
authored
slh-dsa: remove allocations (#860)
1 parent f46f4a3 commit 8f93676

File tree

8 files changed

+32
-26
lines changed

8 files changed

+32
-26
lines changed

slh-dsa/src/hashes.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ pub(crate) trait HashSuite: Sized + Clone + Debug + PartialEq + Eq {
2323
fn prf_msg(
2424
sk_prf: &SkPrf<Self::N>,
2525
opt_rand: &Array<u8, Self::N>,
26-
msg: impl AsRef<[u8]>,
26+
msg: &[impl AsRef<[u8]>],
2727
) -> Array<u8, Self::N>;
2828

2929
/// Hashes a message using a given randomizer
3030
fn h_msg(
3131
rand: &Array<u8, Self::N>,
3232
pk_seed: &PkSeed<Self::N>,
3333
pk_root: &Array<u8, Self::N>,
34-
msg: impl AsRef<[u8]>,
34+
msg: &[impl AsRef<[u8]>],
3535
) -> Array<u8, Self::M>;
3636

3737
/// PRF that is used to generate the secret values in WOTS+ and FORS private keys.
@@ -76,7 +76,7 @@ mod tests {
7676
let opt_rand = Array::<u8, H::N>::from_fn(|_| 1);
7777
let msg = [2u8; 32];
7878

79-
let result = H::prf_msg(&sk_prf, &opt_rand, msg);
79+
let result = H::prf_msg(&sk_prf, &opt_rand, &[msg]);
8080

8181
assert_eq!(result.as_slice(), expected);
8282
}
@@ -87,7 +87,7 @@ mod tests {
8787
let pk_root = Array::<u8, H::N>::from_fn(|_| 2);
8888
let msg = [3u8; 32];
8989

90-
let result = H::h_msg(&rand, &pk_seed, &pk_root, msg);
90+
let result = H::h_msg(&rand, &pk_seed, &pk_root, &[msg]);
9191

9292
assert_eq!(result.as_slice(), expected);
9393
}

slh-dsa/src/hashes/sha2.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@ where
6060
fn prf_msg(
6161
sk_prf: &SkPrf<Self::N>,
6262
opt_rand: &Array<u8, Self::N>,
63-
msg: impl AsRef<[u8]>,
63+
msg: &[impl AsRef<[u8]>],
6464
) -> Array<u8, Self::N> {
6565
let mut mac = Hmac::<Sha256>::new_from_slice(sk_prf.as_ref()).unwrap();
6666
mac.update(opt_rand.as_slice());
67-
mac.update(msg.as_ref());
67+
msg.iter()
68+
.for_each(|msg_part| mac.update(msg_part.as_ref()));
6869
let result = mac.finalize().into_bytes();
6970
Array::clone_from_slice(&result[..Self::N::USIZE])
7071
}
@@ -73,13 +74,13 @@ where
7374
rand: &Array<u8, Self::N>,
7475
pk_seed: &PkSeed<Self::N>,
7576
pk_root: &Array<u8, Self::N>,
76-
msg: impl AsRef<[u8]>,
77+
msg: &[impl AsRef<[u8]>],
7778
) -> Array<u8, Self::M> {
7879
let mut h = Sha256::new();
7980
h.update(rand);
8081
h.update(pk_seed);
8182
h.update(pk_root);
82-
h.update(msg.as_ref());
83+
msg.iter().for_each(|msg_part| h.update(msg_part.as_ref()));
8384
let result = Array(h.finalize().into());
8485
let seed = rand.clone().concat(pk_seed.0.clone()).concat(result);
8586
mgf1::<Sha256, Self::M>(&seed)
@@ -220,11 +221,12 @@ where
220221
fn prf_msg(
221222
sk_prf: &SkPrf<Self::N>,
222223
opt_rand: &Array<u8, Self::N>,
223-
msg: impl AsRef<[u8]>,
224+
msg: &[impl AsRef<[u8]>],
224225
) -> Array<u8, Self::N> {
225226
let mut mac = Hmac::<Sha512>::new_from_slice(sk_prf.as_ref()).unwrap();
226227
mac.update(opt_rand.as_slice());
227-
mac.update(msg.as_ref());
228+
msg.iter()
229+
.for_each(|msg_part| mac.update(msg_part.as_ref()));
228230
let result = mac.finalize().into_bytes();
229231
Array::clone_from_slice(&result[..Self::N::USIZE])
230232
}
@@ -233,13 +235,13 @@ where
233235
rand: &Array<u8, Self::N>,
234236
pk_seed: &PkSeed<Self::N>,
235237
pk_root: &Array<u8, Self::N>,
236-
msg: impl AsRef<[u8]>,
238+
msg: &[impl AsRef<[u8]>],
237239
) -> Array<u8, Self::M> {
238240
let mut h = Sha512::new();
239241
h.update(rand);
240242
h.update(pk_seed);
241243
h.update(pk_root);
242-
h.update(msg.as_ref());
244+
msg.iter().for_each(|msg_part| h.update(msg_part.as_ref()));
243245
let result = Array(h.finalize().into());
244246
let seed = rand.clone().concat(pk_seed.0.clone()).concat(result);
245247
mgf1::<Sha512, Self::M>(&seed)

slh-dsa/src/hashes/shake.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ where
3434
fn prf_msg(
3535
sk_prf: &SkPrf<Self::N>,
3636
opt_rand: &Array<u8, Self::N>,
37-
msg: impl AsRef<[u8]>,
37+
msg: &[impl AsRef<[u8]>],
3838
) -> Array<u8, Self::N> {
3939
let mut hasher = Shake256::default();
4040
hasher.update(sk_prf.as_ref());
4141
hasher.update(opt_rand.as_slice());
42-
hasher.update(msg.as_ref());
42+
msg.iter()
43+
.for_each(|msg_part| hasher.update(msg_part.as_ref()));
4344
let mut output = Array::<u8, Self::N>::default();
4445
hasher.finalize_xof_into(&mut output);
4546
output
@@ -49,13 +50,14 @@ where
4950
rand: &Array<u8, Self::N>,
5051
pk_seed: &PkSeed<Self::N>,
5152
pk_root: &Array<u8, Self::N>,
52-
msg: impl AsRef<[u8]>,
53+
msg: &[impl AsRef<[u8]>],
5354
) -> Array<u8, Self::M> {
5455
let mut hasher = Shake256::default();
5556
hasher.update(rand.as_slice());
5657
hasher.update(pk_seed.as_ref());
5758
hasher.update(pk_root.as_ref());
58-
hasher.update(msg.as_ref());
59+
msg.iter()
60+
.for_each(|msg_part| hasher.update(msg_part.as_ref()));
5961
let mut output = Array::<u8, Self::M>::default();
6062
hasher.finalize_xof_into(&mut output);
6163
output
@@ -267,7 +269,7 @@ mod tests {
267269

268270
let expected = hex!("bc5c062307df0a41aeeae19ad655f7b2");
269271

270-
let result = H::prf_msg(&sk_prf, &opt_rand, msg);
272+
let result = H::prf_msg(&sk_prf, &opt_rand, &[msg]);
271273

272274
assert_eq!(result.as_slice(), expected);
273275
}

slh-dsa/src/signing_key.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl<P: ParameterSet> SigningKey<P> {
103103
/// Implements [slh_sign_internal] as defined in FIPS-205.
104104
/// Published for KAT validation purposes but not intended for general use.
105105
/// opt_rand must be a P::N length slice, panics otherwise.
106-
pub fn slh_sign_internal(&self, msg: &[u8], opt_rand: Option<&[u8]>) -> Signature<P> {
106+
pub fn slh_sign_internal(&self, msg: &[&[u8]], opt_rand: Option<&[u8]>) -> Signature<P> {
107107
let rand = opt_rand
108108
.unwrap_or(&self.verifying_key.pk_seed.0)
109109
.try_into()
@@ -142,8 +142,7 @@ impl<P: ParameterSet> SigningKey<P> {
142142
let ctx_len = u8::try_from(ctx.len()).map_err(|_| Error::new())?;
143143
let ctx_len_bytes = ctx_len.to_be_bytes();
144144

145-
// TODO - figure out what to do about this allocation. Maybe pass a chained iterator to slh_sign_internal?
146-
let ctx_msg = [&[0], &ctx_len_bytes, ctx, msg].concat();
145+
let ctx_msg = [&[0], &ctx_len_bytes, ctx, msg];
147146
Ok(self.slh_sign_internal(&ctx_msg, opt_rand))
148147
}
149148

slh-dsa/src/verifying_key.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ impl<P: ParameterSet + VerifyingKeyLen> VerifyingKey<P> {
5050
/// Verify a raw message (without context).
5151
/// Implements [slh_verify_internal] as defined in FIPS-205.
5252
/// Published for KAT validation purposes but not intended for general use.
53-
pub fn slh_verify_internal(&self, msg: &[u8], signature: &Signature<P>) -> Result<(), Error> {
53+
pub fn slh_verify_internal(
54+
&self,
55+
msg: &[&[u8]],
56+
signature: &Signature<P>,
57+
) -> Result<(), Error> {
5458
let pk_seed = &self.pk_seed;
5559
let randomizer = &signature.randomizer;
5660
let fors_sig = &signature.fors_sig;
@@ -79,8 +83,7 @@ impl<P: ParameterSet + VerifyingKeyLen> VerifyingKey<P> {
7983
let ctx_len = u8::try_from(ctx.len()).map_err(|_| Error::new())?;
8084
let ctx_len_bytes = ctx_len.to_be_bytes();
8185

82-
// TODO - figure out what to do about this allocation. Maybe pass a chained iterator to slh_sign_internal?
83-
let ctx_msg = [&[0], &ctx_len_bytes, ctx, msg].concat();
86+
let ctx_msg = [&[0], &ctx_len_bytes, ctx, msg];
8487
self.slh_verify_internal(&ctx_msg, signature) // TODO - context processing
8588
}
8689

slh-dsa/tests/acvp_sig.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ macro_rules! parameter_case {
3939
.additionalRandomness
4040
.as_ref()
4141
.map(|x| x.data.as_slice());
42-
let sig = sk.slh_sign_internal($test_case.message.data.as_slice(), opt_rand);
42+
let sig = sk.slh_sign_internal(&[$test_case.message.data.as_slice()], opt_rand);
4343
assert_eq!(sig.to_vec(), $test_case.signature.data);
4444
}};
4545
}

slh-dsa/tests/acvp_ver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ macro_rules! parameter_case {
3636
($param:ident, $test_case:expr) => {{
3737
let sk = VerifyingKey::<$param>::try_from($test_case.pk.data.as_slice()).unwrap();
3838
if let Ok(sig) = $test_case.signature.data.as_slice().try_into() {
39-
let success = sk.slh_verify_internal($test_case.message.data.as_slice(), &sig);
39+
let success = sk.slh_verify_internal(&[$test_case.message.data.as_slice()], &sig);
4040
assert_eq!($test_case.testPassed, success.is_ok());
4141
} else {
4242
assert!(!$test_case.testPassed);

slh-dsa/tests/known_answer_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ where
133133
let mut opt_rand = vec![0; P::VkLen::USIZE / 2];
134134
rng.fill_bytes(opt_rand.as_mut());
135135

136-
let sig = sk.slh_sign_internal(msg, Some(&opt_rand)).to_bytes();
136+
let sig = sk.slh_sign_internal(&[msg], Some(&opt_rand)).to_bytes();
137137
writeln!(resp, "smlen = {}", sig.as_slice().len() + msg.len()).unwrap();
138138
writeln!(
139139
resp,

0 commit comments

Comments
 (0)