From 46fac2863db476587dff63c5d8672690fd49d02b Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Mon, 20 Oct 2025 16:49:01 +0200 Subject: [PATCH 1/5] [SHA3] Match mainline APIs --- libcrux-iot/Cargo.toml | 2 + libcrux-iot/sha3/Cargo.toml | 3 +- libcrux-iot/sha3/src/impl_digest_trait.rs | 53 +++++++++++++++++++++++ libcrux-iot/sha3/src/lib.rs | 4 ++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 libcrux-iot/sha3/src/impl_digest_trait.rs diff --git a/libcrux-iot/Cargo.toml b/libcrux-iot/Cargo.toml index 05019c31..84f77c15 100644 --- a/libcrux-iot/Cargo.toml +++ b/libcrux-iot/Cargo.toml @@ -14,6 +14,8 @@ readme = "README.md" [workspace.dependencies] libcrux-secrets = { version = "0.0.3" } libcrux-macros = { version = "0.0.3" } +libcrux-traits = { git = "https://github.com/cryspen/libcrux" } + cavp = { version = "0.0.2" } hax-lib = { version = "0.3.2" } diff --git a/libcrux-iot/sha3/Cargo.toml b/libcrux-iot/sha3/Cargo.toml index 277d738d..5f1c404a 100644 --- a/libcrux-iot/sha3/Cargo.toml +++ b/libcrux-iot/sha3/Cargo.toml @@ -17,6 +17,7 @@ bench = false # so libtest doesn't eat the arguments to criterion [dependencies] libcrux-secrets.workspace = true +libcrux-traits.workspace = true # This is only required for verification. # The hax config is set by the hax toolchain. @@ -25,7 +26,7 @@ hax-lib = { version = "0.3.0", git = "https://github.com/hacspec/hax/" } [features] full-unroll = [] -check-secret-independence = ["libcrux-secrets/check-secret-independence"] +check-secret-independence = ["libcrux-secrets/check-secret-independence", "libcrux-traits/check-secret-independence"] [dev-dependencies] criterion = "0.5.1" diff --git a/libcrux-iot/sha3/src/impl_digest_trait.rs b/libcrux-iot/sha3/src/impl_digest_trait.rs new file mode 100644 index 00000000..dda45b01 --- /dev/null +++ b/libcrux-iot/sha3/src/impl_digest_trait.rs @@ -0,0 +1,53 @@ +use crate::*; + +const SHA3_224_LEN: usize = 28; +const SHA3_256_LEN: usize = 32; +const SHA3_384_LEN: usize = 48; +const SHA3_512_LEN: usize = 64; + +macro_rules! impl_hash_traits { + ($type:ident, $hasher:ident, $len:expr, $method:expr) => { + #[doc = concat!("A struct that implements [`libcrux_traits::digest`] traits.")] + #[doc = concat!("\n\n")] + #[doc = concat!("[`",stringify!($hasher), "`] is a convenient hasher for this struct.")] + pub struct $type; + + #[doc = concat!("A hasher for [`",stringify!($type), "`].")] + pub type $hasher = libcrux_traits::digest::Hasher<$len, $type>; + + impl libcrux_traits::digest::arrayref::Hash<$len> for $type { + #[inline(always)] + fn hash( + digest: &mut [u8; $len], + payload: &[u8], + ) -> Result<(), libcrux_traits::digest::arrayref::HashError> { + use libcrux_traits::libcrux_secrets::ClassifyRefMut; + + if payload.len() > u32::MAX as usize { + return Err(libcrux_traits::digest::arrayref::HashError::InvalidPayloadLength); + } + + $method(digest.as_mut_slice().classify_ref_mut(), payload); + + Ok(()) + } + } + }; +} + +impl_hash_traits!(Sha3_224, Sha3_224Hasher, SHA3_224_LEN, portable::sha224); +impl_hash_traits!(Sha3_256, Sha3_256Hasher, SHA3_256_LEN, portable::sha256); +impl_hash_traits!(Sha3_384, Sha3_384Hasher, SHA3_384_LEN, portable::sha384); +impl_hash_traits!(Sha3_512, Sha3_512Hasher, SHA3_512_LEN, portable::sha512); + +// Implement the slice hash trait +// This is excluded for the hax extraction +#[cfg_attr(hax, hax_lib::exclude)] +mod slice { + use super::*; + + libcrux_traits::digest::slice::impl_hash_trait!(Sha3_224 => SHA3_224_LEN); + libcrux_traits::digest::slice::impl_hash_trait!(Sha3_256 => SHA3_256_LEN); + libcrux_traits::digest::slice::impl_hash_trait!(Sha3_384 => SHA3_384_LEN); + libcrux_traits::digest::slice::impl_hash_trait!(Sha3_512 => SHA3_512_LEN); +} diff --git a/libcrux-iot/sha3/src/lib.rs b/libcrux-iot/sha3/src/lib.rs index 2c443787..152959c1 100644 --- a/libcrux-iot/sha3/src/lib.rs +++ b/libcrux-iot/sha3/src/lib.rs @@ -10,6 +10,10 @@ mod keccak; mod lane; mod state; +#[cfg(not(any(hax, eurydice)))] +mod impl_digest_trait; +#[cfg(not(any(hax, eurydice)))] +pub use impl_digest_trait::*; /// A SHA3 224 Digest pub type Sha3_224Digest = [U8; 28]; From 017ab8b3fceb13b61a03b168be23fe1810600d3f Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Mon, 20 Oct 2025 16:55:45 +0200 Subject: [PATCH 2/5] Move `libcrux-secrets` to git dependency for now --- libcrux-iot/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrux-iot/Cargo.toml b/libcrux-iot/Cargo.toml index 84f77c15..0e7fd9cf 100644 --- a/libcrux-iot/Cargo.toml +++ b/libcrux-iot/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/cryspen/libcrux-iot" readme = "README.md" [workspace.dependencies] -libcrux-secrets = { version = "0.0.3" } +libcrux-secrets = { git = "https://github.com/cryspen/libcrux" } libcrux-macros = { version = "0.0.3" } libcrux-traits = { git = "https://github.com/cryspen/libcrux" } From 731cb3347c045a7dbd768842047b3e05b64e3781 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Mon, 24 Nov 2025 14:53:14 +0100 Subject: [PATCH 3/5] Depend on released `libcrux-traits` --- libcrux-iot/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrux-iot/Cargo.toml b/libcrux-iot/Cargo.toml index 9149f371..7452efc8 100644 --- a/libcrux-iot/Cargo.toml +++ b/libcrux-iot/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" [workspace.dependencies] libcrux-secrets = { version = "0.0.4" } libcrux-macros = { version = "0.0.3" } -libcrux-traits = { git = "https://github.com/cryspen/libcrux" } +libcrux-traits = { version = "0.0.4" } cavp = { version = "0.0.2" } hax-lib = { version = "0.3.2" } From bbc9130f816a37f40949bea0e39c249820a3ff55 Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Mon, 24 Nov 2025 15:08:12 +0100 Subject: [PATCH 4/5] Fix nRF52810 builds --- libcrux-nrf52810/src/bin/mldsa_keygen.rs | 4 ++++ libcrux-nrf52810/src/bin/mldsa_sign.rs | 4 ++++ libcrux-nrf52810/src/bin/mldsa_verify.rs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/libcrux-nrf52810/src/bin/mldsa_keygen.rs b/libcrux-nrf52810/src/bin/mldsa_keygen.rs index 7c0dcebc..27b177b1 100644 --- a/libcrux-nrf52810/src/bin/mldsa_keygen.rs +++ b/libcrux-nrf52810/src/bin/mldsa_keygen.rs @@ -2,9 +2,13 @@ #![no_std] #![cfg(feature = "mldsa87")] +use embedded_alloc::LlffHeap as Heap; use libcrux_iot_ml_dsa::ml_dsa_87 as mldsa; use libcrux_nrf52810 as board; // global logger + panicking-behavior + memory layout +#[global_allocator] +static HEAP: Heap = Heap::empty(); + #[cortex_m_rt::entry] fn main() -> ! { let randomness_gen = [1u8; 32]; diff --git a/libcrux-nrf52810/src/bin/mldsa_sign.rs b/libcrux-nrf52810/src/bin/mldsa_sign.rs index dca84b45..65b661d6 100644 --- a/libcrux-nrf52810/src/bin/mldsa_sign.rs +++ b/libcrux-nrf52810/src/bin/mldsa_sign.rs @@ -4,8 +4,12 @@ use libcrux_nrf52810 as board; // global logger + panicking-behavior + memory layout +use embedded_alloc::LlffHeap as Heap; use libcrux_iot_ml_dsa::ml_dsa_87 as mldsa; +#[global_allocator] +static HEAP: Heap = Heap::empty(); + static SK: [u8; 4896] = [ 158, 41, 234, 146, 185, 41, 27, 225, 46, 178, 46, 248, 151, 40, 73, 59, 147, 27, 116, 81, 248, 8, 158, 148, 78, 73, 68, 45, 224, 13, 255, 41, 95, 188, 191, 236, 222, 219, 178, 26, 88, 255, diff --git a/libcrux-nrf52810/src/bin/mldsa_verify.rs b/libcrux-nrf52810/src/bin/mldsa_verify.rs index 4baea0b6..03db78a6 100644 --- a/libcrux-nrf52810/src/bin/mldsa_verify.rs +++ b/libcrux-nrf52810/src/bin/mldsa_verify.rs @@ -2,9 +2,13 @@ #![no_std] #![cfg(feature = "mldsa87")] +use embedded_alloc::LlffHeap as Heap; use libcrux_iot_ml_dsa::ml_dsa_87 as mldsa; use libcrux_nrf52810 as board; // global logger + panicking-behavior + memory layout +#[global_allocator] +static HEAP: Heap = Heap::empty(); + static SIGNATURE: [u8; 4627] = [ 154, 87, 4, 180, 140, 33, 3, 215, 213, 217, 228, 43, 218, 42, 215, 237, 7, 157, 76, 158, 95, 99, 76, 148, 89, 217, 144, 153, 38, 64, 136, 242, 52, 135, 216, 113, 40, 160, 202, 2, 182, 152, From f1c2c7869ff5a45cca722ffe554da44780538deb Mon Sep 17 00:00:00 2001 From: Jonas Schneider-Bensch Date: Tue, 16 Dec 2025 14:23:49 +0100 Subject: [PATCH 5/5] Classify SHA3 inputs in digest API --- libcrux-iot/sha3/src/impl_digest_trait.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libcrux-iot/sha3/src/impl_digest_trait.rs b/libcrux-iot/sha3/src/impl_digest_trait.rs index dda45b01..2cabc461 100644 --- a/libcrux-iot/sha3/src/impl_digest_trait.rs +++ b/libcrux-iot/sha3/src/impl_digest_trait.rs @@ -21,13 +21,16 @@ macro_rules! impl_hash_traits { digest: &mut [u8; $len], payload: &[u8], ) -> Result<(), libcrux_traits::digest::arrayref::HashError> { - use libcrux_traits::libcrux_secrets::ClassifyRefMut; + use libcrux_traits::libcrux_secrets::{ClassifyRef, ClassifyRefMut}; if payload.len() > u32::MAX as usize { return Err(libcrux_traits::digest::arrayref::HashError::InvalidPayloadLength); } - $method(digest.as_mut_slice().classify_ref_mut(), payload); + $method( + digest.as_mut_slice().classify_ref_mut(), + payload.classify_ref(), + ); Ok(()) }