MOD: cleanup move tests out of reg classes
This commit is contained in:
parent
cc72bb8919
commit
3ea964d3d9
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Vec<u8>, CryptoError> {
|
||||
Ok(pt.to_vec())
|
||||
}
|
||||
fn decrypt_aead(
|
||||
&self,
|
||||
_a: AeadAlgorithm,
|
||||
_k: &[u8],
|
||||
_n: &[u8],
|
||||
ct: &[u8],
|
||||
_aad: &[u8],
|
||||
) -> Result<Vec<u8>, CryptoError> {
|
||||
Ok(ct.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl KdfProvider for StubProvider {
|
||||
fn derive_key(
|
||||
&self,
|
||||
_a: KdfAlgorithm,
|
||||
_ikm: &[u8],
|
||||
_salt: &[u8],
|
||||
_info: &[u8],
|
||||
length: usize,
|
||||
) -> Result<Zeroizing<Vec<u8>>, CryptoError> {
|
||||
Ok(Zeroizing::new(vec![0u8; length]))
|
||||
}
|
||||
}
|
||||
|
||||
impl MacProvider for StubProvider {
|
||||
fn compute_mac(
|
||||
&self,
|
||||
_a: MacAlgorithm,
|
||||
_k: &[u8],
|
||||
_data: &[u8],
|
||||
) -> Result<Vec<u8>, CryptoError> {
|
||||
Ok(vec![0u8; 32])
|
||||
}
|
||||
fn verify_mac(
|
||||
&self,
|
||||
_a: MacAlgorithm,
|
||||
_k: &[u8],
|
||||
_data: &[u8],
|
||||
_mac: &[u8],
|
||||
) -> Result<bool, CryptoError> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl HashProvider for StubProvider {
|
||||
fn hash(&self, _a: HashAlgorithm, data: &[u8]) -> Result<Vec<u8>, 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;
|
||||
|
|
|
|||
|
|
@ -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<Vec<u8>, CryptoError> {
|
||||
Ok(pt.to_vec())
|
||||
}
|
||||
fn decrypt_aead(
|
||||
&self,
|
||||
_a: AeadAlgorithm,
|
||||
_k: &[u8],
|
||||
_n: &[u8],
|
||||
ct: &[u8],
|
||||
_aad: &[u8],
|
||||
) -> Result<Vec<u8>, CryptoError> {
|
||||
Ok(ct.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl KdfProvider for StubProvider {
|
||||
fn derive_key(
|
||||
&self,
|
||||
_a: KdfAlgorithm,
|
||||
_ikm: &[u8],
|
||||
_salt: &[u8],
|
||||
_info: &[u8],
|
||||
length: usize,
|
||||
) -> Result<Zeroizing<Vec<u8>>, CryptoError> {
|
||||
Ok(Zeroizing::new(vec![0u8; length]))
|
||||
}
|
||||
}
|
||||
|
||||
impl MacProvider for StubProvider {
|
||||
fn compute_mac(
|
||||
&self,
|
||||
_a: MacAlgorithm,
|
||||
_k: &[u8],
|
||||
_data: &[u8],
|
||||
) -> Result<Vec<u8>, CryptoError> {
|
||||
Ok(vec![0u8; 32])
|
||||
}
|
||||
fn verify_mac(
|
||||
&self,
|
||||
_a: MacAlgorithm,
|
||||
_k: &[u8],
|
||||
_data: &[u8],
|
||||
_mac: &[u8],
|
||||
) -> Result<bool, CryptoError> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
impl HashProvider for StubProvider {
|
||||
fn hash(&self, _a: HashAlgorithm, data: &[u8]) -> Result<Vec<u8>, 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);
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub fn compute_mac(algo: MacAlgorithm, key: &[u8], data: &[u8]) -> Result<Vec<u8
|
|||
MacAlgorithm::HmacSha384 => 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;
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
Loading…
Reference in New Issue