From be1785e6708764632e56318a3db1650ee3ddd062 Mon Sep 17 00:00:00 2001 From: Mike Ounsworth Date: Thu, 27 Aug 2026 16:37:39 -0500 Subject: [PATCH] sha3, rng: use core:: imports, copy Copy types, drop a redundant zeroize Mechanical cleanups, no behaviour change. * std::marker::PhantomData -> core:: in sha3.rs, and std::fmt -> core:: in hash_drbg80090a.rs. Neither needs std; both crates are working towards no_std. * KeyType and SecurityStrength are Copy, so min()/max() results are dereferenced rather than .clone()d. This also lets the surrounding expressions be formatted as single calls. * Hash::hash_out() and XOF::hash_xof_out() called output.fill(0) before delegating to a path that zeroizes the buffer itself (do_final_out() and squeeze_out() respectively, per the trait contract). Dropped the outer fill; hash_out() no longer needs `mut output` or a reborrow. Co-Authored-By: Claude Opus 5 (1M context) --- alpha_0.1.3_release_notes.md | 6 ++++++ crypto/rng/src/hash_drbg80090a.rs | 2 +- crypto/sha3/src/sha3.rs | 34 +++++++++++++++---------------- crypto/sha3/src/shake.rs | 20 ++++++++---------- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/alpha_0.1.3_release_notes.md b/alpha_0.1.3_release_notes.md index 210a5aeb..82db87c2 100644 --- a/alpha_0.1.3_release_notes.md +++ b/alpha_0.1.3_release_notes.md @@ -3,3 +3,9 @@ ## Major features ## Minor features / bug fixes + +Housekeeping: + +* `no_std` progress: `std::marker::PhantomData` and `std::fmt` replaced with their `core::` equivalents in the SHA-3 + and Hash_DRBG crates, and the `Copy` types `KeyType` / `SecurityStrength` are now copied rather than `.clone()`d. + Removed a redundant second zeroization of the caller's output buffer in `Hash::hash_out()` / `XOF::hash_xof_out()`. diff --git a/crypto/rng/src/hash_drbg80090a.rs b/crypto/rng/src/hash_drbg80090a.rs index be70cb8d..7b45cc2a 100644 --- a/crypto/rng/src/hash_drbg80090a.rs +++ b/crypto/rng/src/hash_drbg80090a.rs @@ -13,7 +13,7 @@ use bouncycastle_core::traits::{Hash, HashAlgParams, RNG, SecurityStrength}; use bouncycastle_sha2::{SHA256, SHA512}; use bouncycastle_utils::{min, secret::Secret}; -use std::fmt::{Display, Formatter}; +use core::fmt::{Display, Formatter}; enum SupportedHash { SHA256, diff --git a/crypto/sha3/src/sha3.rs b/crypto/sha3/src/sha3.rs index 3da20b0b..918ee974 100644 --- a/crypto/sha3/src/sha3.rs +++ b/crypto/sha3/src/sha3.rs @@ -15,7 +15,7 @@ use bouncycastle_utils::{max, min}; /// provided and NIST-approved parameters. #[derive(Clone)] pub struct SHA3Internal { - _params: std::marker::PhantomData, + _params: core::marker::PhantomData, keccak: KeccakInternal, kdf_key_type: KeyType, kdf_security_strength: SecurityStrength, @@ -28,7 +28,7 @@ impl SHA3Internal { /// Get a new SHA3 instance, ready for use. pub fn new() -> Self { Self { - _params: std::marker::PhantomData, + _params: core::marker::PhantomData, keccak: KeccakInternal::new(PARAMS::SIZE), kdf_key_type: KeyType::Zeroized, kdf_security_strength: SecurityStrength::None, @@ -52,12 +52,11 @@ impl SHA3Internal { if key.is_full_entropy() { self.kdf_entropy += key.key_len(); self.kdf_security_strength = - max(&self.kdf_security_strength, &key.security_strength()).clone(); - self.kdf_security_strength = min( + *max(&self.kdf_security_strength, &key.security_strength()); + self.kdf_security_strength = *min( &self.kdf_security_strength, &SecurityStrength::from_bits(PARAMS::OUTPUT_LEN * 8 / 2), - ) - .clone(); + ); } self.do_update(key.ref_to_bytes()) @@ -82,14 +81,14 @@ impl SHA3Internal { // it requires full-entropy input that is at least block length. // TODO: citation needed (NIST) if self.kdf_entropy < PARAMS::OUTPUT_LEN { - self.kdf_key_type = min(&self.kdf_key_type, &KeyType::Unknown).clone(); + self.kdf_key_type = *min(&self.kdf_key_type, &KeyType::Unknown); self.kdf_security_strength = SecurityStrength::None; // BytesLowEntropy can't have a securtiy level. } self.do_update(additional_input); - let mut key_type = self.kdf_key_type.clone(); - let output_security_strength = self.kdf_security_strength.clone(); + let mut key_type = self.kdf_key_type; + let output_security_strength = self.kdf_security_strength; let mut bytes_written: usize = 0; key_material::do_hazardous_operations(output_key, |output_key| { bytes_written = self.do_final_out(output_key.ref_to_bytes_mut()?); @@ -107,16 +106,17 @@ impl SHA3Internal { } key_material::do_hazardous_operations(&mut *output_key, |output_key| { output_key.set_key_type(key_type)?; - output_key.set_security_strength( - min(&output_security_strength, &SecurityStrength::from_bits(bytes_written * 8)).clone(), - ) + output_key.set_security_strength(*min( + &output_security_strength, + &SecurityStrength::from_bits(bytes_written * 8), + )) }) .expect( "both set_key_type() and set_security_strength() should be infallible within a hazop block", ); output_key - .set_key_len(min(&output_key.key_len(), &PARAMS::OUTPUT_LEN).clone()) + .set_key_len(*min(&output_key.key_len(), &PARAMS::OUTPUT_LEN)) .expect("should be infallible to truncate key length"); Ok(bytes_written) } @@ -150,10 +150,8 @@ impl Hash for SHA3Internal { output } - fn hash_out(self, data: &[u8], mut output: &mut [u8]) -> usize { - output.fill(0); - - self.hash_internal(data, &mut output) + fn hash_out(self, data: &[u8], output: &mut [u8]) -> usize { + self.hash_internal(data, output) } fn do_update(&mut self, data: &[u8]) { @@ -321,7 +319,7 @@ impl Suspendable for SHA3Internal< deserialize_sha3_family_state(input, PARAMS::STATE_TAG, rate)?; Ok(SHA3Internal { - _params: std::marker::PhantomData, + _params: core::marker::PhantomData, keccak, kdf_key_type, kdf_security_strength, diff --git a/crypto/sha3/src/shake.rs b/crypto/sha3/src/shake.rs index 6ba2a882..f3b45317 100644 --- a/crypto/sha3/src/shake.rs +++ b/crypto/sha3/src/shake.rs @@ -76,12 +76,11 @@ impl SHAKEInternal { if key.is_full_entropy() { self.kdf_entropy += key.key_len(); self.kdf_security_strength = - max(&self.kdf_security_strength, &key.security_strength()).clone(); - self.kdf_security_strength = min( + *max(&self.kdf_security_strength, &key.security_strength()); + self.kdf_security_strength = *min( &self.kdf_security_strength, &SecurityStrength::from_bits(PARAMS::SIZE as usize), - ) - .clone(); + ); } // Infallible: mix_key_internal is only called during the absorb phase, before any squeeze. @@ -117,7 +116,7 @@ impl SHAKEInternal { // TODO: The intuition behind this is that SHAKE256 and SHA3-256 are both KECCAK[512], and SHAKE128 is KECCAK[256], // TODO: However, it is necessary to find an actual reference for this "fully-seeded" threshold. if self.kdf_entropy < 2 * (PARAMS::SIZE as usize) / 8 { - self.kdf_key_type = min(&self.kdf_key_type, &KeyType::Unknown).clone(); + self.kdf_key_type = *min(&self.kdf_key_type, &KeyType::Unknown); self.kdf_security_strength = SecurityStrength::None; // BytesLowEntropy can't have a securtiy level. } @@ -139,10 +138,10 @@ impl SHAKEInternal { } key_material::do_hazardous_operations(output_key, |output_key| { output_key.set_key_type(self.kdf_key_type)?; - output_key.set_security_strength( - min(&self.kdf_security_strength, &SecurityStrength::from_bits(bytes_written * 8)) - .clone(), - ) + output_key.set_security_strength(*min( + &self.kdf_security_strength, + &SecurityStrength::from_bits(bytes_written * 8), + )) })?; Ok(bytes_written) } @@ -270,8 +269,7 @@ impl XOF for SHAKEInternal { } fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize { - output.fill(0); - + // hash_internal_out zeroizes `output` before writing. self.hash_internal_out(data, output) }