From 3ea964d3d976dc4330a882ea18945a14e65993dc Mon Sep 17 00:00:00 2001 From: JohnE Date: Wed, 11 Mar 2026 21:34:31 -0700 Subject: [PATCH] MOD: cleanup move tests out of reg classes --- .vscode/settings.json | 10 +- crates/ccc-crypto-core/src/registry.rs | 180 +----------------- crates/ccc-crypto-core/src/registry_tests.rs | 172 +++++++++++++++++ crates/ccc-crypto-wolfssl/src/capabilities.rs | 12 +- crates/ccc-crypto-wolfssl/src/mac.rs | 22 +-- crates/ccc-crypto-wolfssl/src/mac_tests.rs | 18 ++ 6 files changed, 214 insertions(+), 200 deletions(-) create mode 100644 crates/ccc-crypto-core/src/registry_tests.rs create mode 100644 crates/ccc-crypto-wolfssl/src/mac_tests.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 71111c0..82a484d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,8 @@ { + "[rust]": { + "editor.formatOnSave": false, + "editor.formatOnPaste": false + }, "cmake.configureOnOpen": false, "dart.analysisExcludedFolders": [ "flutter_src", @@ -15,6 +19,10 @@ "AllBlockComments" ], "chat.tools.terminal.autoApprove": { - "cargo search": true + "cargo search": true, + "/^source \"\\$HOME/\\.cargo/env\" && cd /Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust && python3 -c \"\n# Self-test AES-GCM vector\nkey = 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308'\nnonce = 'cafebabefacedbaddecaf888'\naad = ''\npt = 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255'\nct_tag = '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad'\n\nprint\\('Self-test AES-GCM:'\\)\nprint\\(f' PT bytes: \\{len\\(pt\\)//2\\}'\\)\nprint\\(f' CT_TAG bytes: \\{len\\(ct_tag\\)//2\\}'\\)\nprint\\(f' Expected \\(PT \\+ 16 tag\\): \\{len\\(pt\\)//2 \\+ 16\\}'\\)\nprint\\(f' ct_tag IS ciphertext-only \\(no tag\\): \\{len\\(ct_tag\\)//2 == len\\(pt\\)//2\\}'\\)\nprint\\(\\)\n\n# Conformance AES-GCM vector \\(different: has AAD, shorter PT\\)\npt2 = 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'\nct_tag2 = '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d551b'\nprint\\('Conformance AES-GCM TC16:'\\)\nprint\\(f' PT bytes: \\{len\\(pt2\\)//2\\}'\\)\nprint\\(f' CT_TAG bytes: \\{len\\(ct_tag2\\)//2\\}'\\)\nprint\\(f' CT_TAG == PT \\+ 16: \\{len\\(ct_tag2\\)//2 == len\\(pt2\\)//2 \\+ 16\\}'\\)\nprint\\(\\)\n\n# Self-test ChaCha vector\npt3 = '4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f6620273939'\nct_tag3 = 'd31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116'\nprint\\('Self-test ChaCha:'\\)\nprint\\(f' PT bytes: \\{len\\(pt3\\)//2\\}'\\)\nprint\\(f' CT_TAG bytes: \\{len\\(ct_tag3\\)//2\\}'\\)\nprint\\(f' CT_TAG == PT \\+ 16: \\{len\\(ct_tag3\\)//2 == len\\(pt3\\)//2 \\+ 16\\}'\\)\nprint\\(f' Ratio: CT_TAG is \\{len\\(ct_tag3\\)//2 - len\\(pt3\\)//2\\} bytes longer than PT'\\)\n\"\n$/": { + "approve": true, + "matchCommandLine": true + } } } \ No newline at end of file diff --git a/crates/ccc-crypto-core/src/registry.rs b/crates/ccc-crypto-core/src/registry.rs index 33ccc46..26ff5af 100644 --- a/crates/ccc-crypto-core/src/registry.rs +++ b/crates/ccc-crypto-core/src/registry.rs @@ -94,182 +94,6 @@ impl ProviderRegistry { } } -// ────────────────────────────────────────────────────────────────────────────── -// Tests -// ────────────────────────────────────────────────────────────────────────────── - #[cfg(test)] -mod tests { - //! Registry unit tests use a stub provider to avoid any native dependency. - - use super::*; - use crate::{ - algorithms::{AeadAlgorithm, HashAlgorithm, KdfAlgorithm, MacAlgorithm}, - capabilities::ProviderCapabilities, - error::CryptoError, - provider::{AeadProvider, CryptoProvider, HashProvider, KdfProvider, MacProvider}, - types::{AlgoBenchResult, AlgoTestResult, BenchmarkReport, SelfTestReport}, - }; - use zeroize::Zeroizing; - - // ── Stub provider ────────────────────────────────────────────────────────── - - struct StubProvider; - - impl AeadProvider for StubProvider { - fn encrypt_aead( - &self, - _a: AeadAlgorithm, - _k: &[u8], - _n: &[u8], - pt: &[u8], - _aad: &[u8], - ) -> Result, CryptoError> { - Ok(pt.to_vec()) - } - fn decrypt_aead( - &self, - _a: AeadAlgorithm, - _k: &[u8], - _n: &[u8], - ct: &[u8], - _aad: &[u8], - ) -> Result, CryptoError> { - Ok(ct.to_vec()) - } - } - - impl KdfProvider for StubProvider { - fn derive_key( - &self, - _a: KdfAlgorithm, - _ikm: &[u8], - _salt: &[u8], - _info: &[u8], - length: usize, - ) -> Result>, CryptoError> { - Ok(Zeroizing::new(vec![0u8; length])) - } - } - - impl MacProvider for StubProvider { - fn compute_mac( - &self, - _a: MacAlgorithm, - _k: &[u8], - _data: &[u8], - ) -> Result, CryptoError> { - Ok(vec![0u8; 32]) - } - fn verify_mac( - &self, - _a: MacAlgorithm, - _k: &[u8], - _data: &[u8], - _mac: &[u8], - ) -> Result { - Ok(true) - } - } - - impl HashProvider for StubProvider { - fn hash(&self, _a: HashAlgorithm, data: &[u8]) -> Result, CryptoError> { - Ok(data.to_vec()) - } - } - - impl CryptoProvider for StubProvider { - fn provider_name(&self) -> &'static str { - "stub" - } - fn capabilities(&self) -> ProviderCapabilities { - ProviderCapabilities::empty("stub") - } - fn self_test(&self) -> SelfTestReport { - SelfTestReport::finalise( - "stub", - vec![AlgoTestResult { - algo_id: 12, - algo_name: "stub".into(), - passed: true, - error_message: None, - }], - ) - } - fn benchmark(&self) -> BenchmarkReport { - BenchmarkReport { - provider_name: "stub".into(), - results: vec![AlgoBenchResult { - algo_id: 12, - algo_name: "stub".into(), - throughput_mbps: 999.0, - efficiency_score: 100, - }], - } - } - } - - // ── Tests ────────────────────────────────────────────────────────────────── - - fn fresh_registry() -> ProviderRegistry { - ProviderRegistry { - inner: Mutex::new(HashMap::new()), - } - } - - #[test] - fn register_and_get() { - let reg = fresh_registry(); - assert!(reg.get("stub").is_none()); - reg.register("stub", Box::new(StubProvider)); - assert!(reg.get("stub").is_some()); - } - - #[test] - fn list_providers() { - let reg = fresh_registry(); - assert!(reg.list().is_empty()); - reg.register("stub", Box::new(StubProvider)); - let names = reg.list(); - assert_eq!(names.len(), 1); - assert_eq!(names[0], "stub"); - } - - #[test] - fn contains_and_unregister() { - let reg = fresh_registry(); - reg.register("stub", Box::new(StubProvider)); - assert!(reg.contains("stub")); - reg.unregister("stub"); - assert!(!reg.contains("stub")); - } - - #[test] - fn register_replaces_existing() { - let reg = fresh_registry(); - reg.register("stub", Box::new(StubProvider)); - reg.register("stub", Box::new(StubProvider)); // replace - assert_eq!(reg.list().len(), 1); - } - - #[test] - fn stub_provider_roundtrip() { - let reg = fresh_registry(); - reg.register("stub", Box::new(StubProvider)); - let provider = reg.get("stub").unwrap(); - let plaintext = b"hello world"; - let ct = provider - .encrypt_aead( - AeadAlgorithm::AesGcm256, - &[0u8; 32], - &[0u8; 12], - plaintext, - b"", - ) - .unwrap(); - let pt = provider - .decrypt_aead(AeadAlgorithm::AesGcm256, &[0u8; 32], &[0u8; 12], &ct, b"") - .unwrap(); - assert_eq!(pt, plaintext); - } -} +#[path = "registry_tests.rs"] +mod tests; diff --git a/crates/ccc-crypto-core/src/registry_tests.rs b/crates/ccc-crypto-core/src/registry_tests.rs new file mode 100644 index 0000000..7a4a084 --- /dev/null +++ b/crates/ccc-crypto-core/src/registry_tests.rs @@ -0,0 +1,172 @@ +//! Registry unit tests — use a stub provider to avoid any native dependency. + +use super::*; +use crate::{ + algorithms::{AeadAlgorithm, HashAlgorithm, KdfAlgorithm, MacAlgorithm}, + capabilities::ProviderCapabilities, + error::CryptoError, + provider::{AeadProvider, CryptoProvider, HashProvider, KdfProvider, MacProvider}, + types::{AlgoBenchResult, AlgoTestResult, BenchmarkReport, SelfTestReport}, +}; +use zeroize::Zeroizing; + +// ── Stub provider ────────────────────────────────────────────────────────── + +struct StubProvider; + +impl AeadProvider for StubProvider { + fn encrypt_aead( + &self, + _a: AeadAlgorithm, + _k: &[u8], + _n: &[u8], + pt: &[u8], + _aad: &[u8], + ) -> Result, CryptoError> { + Ok(pt.to_vec()) + } + fn decrypt_aead( + &self, + _a: AeadAlgorithm, + _k: &[u8], + _n: &[u8], + ct: &[u8], + _aad: &[u8], + ) -> Result, CryptoError> { + Ok(ct.to_vec()) + } +} + +impl KdfProvider for StubProvider { + fn derive_key( + &self, + _a: KdfAlgorithm, + _ikm: &[u8], + _salt: &[u8], + _info: &[u8], + length: usize, + ) -> Result>, CryptoError> { + Ok(Zeroizing::new(vec![0u8; length])) + } +} + +impl MacProvider for StubProvider { + fn compute_mac( + &self, + _a: MacAlgorithm, + _k: &[u8], + _data: &[u8], + ) -> Result, CryptoError> { + Ok(vec![0u8; 32]) + } + fn verify_mac( + &self, + _a: MacAlgorithm, + _k: &[u8], + _data: &[u8], + _mac: &[u8], + ) -> Result { + Ok(true) + } +} + +impl HashProvider for StubProvider { + fn hash(&self, _a: HashAlgorithm, data: &[u8]) -> Result, CryptoError> { + Ok(data.to_vec()) + } +} + +impl CryptoProvider for StubProvider { + fn provider_name(&self) -> &'static str { + "stub" + } + fn capabilities(&self) -> ProviderCapabilities { + ProviderCapabilities::empty("stub") + } + fn self_test(&self) -> SelfTestReport { + SelfTestReport::finalise( + "stub", + vec![AlgoTestResult { + algo_id: 12, + algo_name: "stub".into(), + passed: true, + error_message: None, + }], + ) + } + fn benchmark(&self) -> BenchmarkReport { + BenchmarkReport { + provider_name: "stub".into(), + results: vec![AlgoBenchResult { + algo_id: 12, + algo_name: "stub".into(), + throughput_mbps: 999.0, + efficiency_score: 100, + }], + } + } +} + +// ── Tests ────────────────────────────────────────────────────────────────── + +fn fresh_registry() -> ProviderRegistry { + ProviderRegistry { + inner: Mutex::new(HashMap::new()), + } +} + +#[test] +fn register_and_get() { + let reg = fresh_registry(); + assert!(reg.get("stub").is_none()); + reg.register("stub", Box::new(StubProvider)); + assert!(reg.get("stub").is_some()); +} + +#[test] +fn list_providers() { + let reg = fresh_registry(); + assert!(reg.list().is_empty()); + reg.register("stub", Box::new(StubProvider)); + let names = reg.list(); + assert_eq!(names.len(), 1); + assert_eq!(names[0], "stub"); +} + +#[test] +fn contains_and_unregister() { + let reg = fresh_registry(); + reg.register("stub", Box::new(StubProvider)); + assert!(reg.contains("stub")); + reg.unregister("stub"); + assert!(!reg.contains("stub")); +} + +#[test] +fn register_replaces_existing() { + let reg = fresh_registry(); + reg.register("stub", Box::new(StubProvider)); + reg.register("stub", Box::new(StubProvider)); // replace + assert_eq!(reg.list().len(), 1); +} + +#[test] +fn stub_provider_roundtrip() { + let reg = fresh_registry(); + reg.register("stub", Box::new(StubProvider)); + let provider = reg.get("stub").unwrap(); + let plaintext = b"hello world"; + let ct = provider + .encrypt_aead( + AeadAlgorithm::AesGcm256, + &[0u8; 32], + &[0u8; 12], + plaintext, + b"", + ) + .unwrap(); + let pt = provider + .decrypt_aead(AeadAlgorithm::AesGcm256, &[0u8; 32], &[0u8; 12], &ct, b"") + .unwrap(); + assert_eq!(pt, plaintext); +} diff --git a/crates/ccc-crypto-wolfssl/src/capabilities.rs b/crates/ccc-crypto-wolfssl/src/capabilities.rs index 1a21bf2..2b62e4e 100644 --- a/crates/ccc-crypto-wolfssl/src/capabilities.rs +++ b/crates/ccc-crypto-wolfssl/src/capabilities.rs @@ -58,7 +58,11 @@ pub fn probe_capabilities(benchmarks: Option<&BenchmarkReport>) -> ProviderCapab caps = caps.with_aead(AeadAlgorithm::Ascon128a, AlgorithmCapability::unavailable()); // ── KDF ────────────────────────────────────────────────────────────────── - for algo in [KdfAlgorithm::Sha256, KdfAlgorithm::Sha384, KdfAlgorithm::Sha512] { + for algo in [ + KdfAlgorithm::Sha256, + KdfAlgorithm::Sha384, + KdfAlgorithm::Sha512, + ] { let available = crate::kdf::derive_key(algo, b"key", b"salt", b"info", 32).is_ok(); caps = caps.with_kdf( algo, @@ -94,7 +98,11 @@ pub fn probe_capabilities(benchmarks: Option<&BenchmarkReport>) -> ProviderCapab caps = caps.with_kdf(KdfAlgorithm::Kmac256, AlgorithmCapability::unavailable()); // ── MAC ────────────────────────────────────────────────────────────────── - for algo in [MacAlgorithm::HmacSha256, MacAlgorithm::HmacSha384, MacAlgorithm::HmacSha512] { + for algo in [ + MacAlgorithm::HmacSha256, + MacAlgorithm::HmacSha384, + MacAlgorithm::HmacSha512, + ] { let available = crate::mac::compute_mac(algo, b"key", b"data").is_ok(); caps = caps.with_mac( algo, diff --git a/crates/ccc-crypto-wolfssl/src/mac.rs b/crates/ccc-crypto-wolfssl/src/mac.rs index 0ec9d59..c78232e 100644 --- a/crates/ccc-crypto-wolfssl/src/mac.rs +++ b/crates/ccc-crypto-wolfssl/src/mac.rs @@ -23,7 +23,7 @@ pub fn compute_mac(algo: MacAlgorithm, key: &[u8], data: &[u8]) -> Result hmac(WC_HASH_TYPE_SHA384, key, data, 48), MacAlgorithm::HmacSha512 => hmac(WC_HASH_TYPE_SHA512, key, data, 64), MacAlgorithm::Blake2bMac => blake2b_mac(key, data), - MacAlgorithm::Poly1305 => Err(CryptoError::UnsupportedAlgorithm( + MacAlgorithm::Poly1305 => Err(CryptoError::UnsupportedAlgorithm( "Poly1305 standalone MAC is not exposed in this Phase".into(), )), } @@ -197,21 +197,5 @@ fn constant_time_eq(a: &[u8], b: &[u8]) -> bool { } #[cfg(test)] -mod tests { - use super::constant_time_eq; - - #[test] - fn ct_eq_same() { - assert!(constant_time_eq(b"hello", b"hello")); - } - - #[test] - fn ct_eq_different() { - assert!(!constant_time_eq(b"hello", b"Hello")); - } - - #[test] - fn ct_eq_different_lengths() { - assert!(!constant_time_eq(b"hi", b"hello")); - } -} +#[path = "mac_tests.rs"] +mod tests; diff --git a/crates/ccc-crypto-wolfssl/src/mac_tests.rs b/crates/ccc-crypto-wolfssl/src/mac_tests.rs new file mode 100644 index 0000000..8a286f7 --- /dev/null +++ b/crates/ccc-crypto-wolfssl/src/mac_tests.rs @@ -0,0 +1,18 @@ +//! Unit tests for constant-time comparison in the MAC module. + +use super::constant_time_eq; + +#[test] +fn ct_eq_same() { + assert!(constant_time_eq(b"hello", b"hello")); +} + +#[test] +fn ct_eq_different() { + assert!(!constant_time_eq(b"hello", b"Hello")); +} + +#[test] +fn ct_eq_different_lengths() { + assert!(!constant_time_eq(b"hi", b"hello")); +}