FIX: test data was not accurate for AEAD
This commit is contained in:
parent
c82d472004
commit
cc72bb8919
|
|
@ -13,53 +13,10 @@ use ccc_crypto_core::{
|
||||||
capabilities::ProviderCapabilities,
|
capabilities::ProviderCapabilities,
|
||||||
error::CryptoError,
|
error::CryptoError,
|
||||||
provider::{AeadProvider, CryptoProvider, HashProvider, KdfProvider, KemProvider, MacProvider},
|
provider::{AeadProvider, CryptoProvider, HashProvider, KdfProvider, KemProvider, MacProvider},
|
||||||
types::{AlgoTestResult, BenchmarkReport, KemEncapResult, KemKeyPair, SelfTestReport},
|
types::{BenchmarkReport, KemEncapResult, KemKeyPair, SelfTestReport},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{aead, capabilities, hash, kdf, kem, mac};
|
use crate::{aead, capabilities, hash, kdf, kem, mac, self_test};
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
// Embedded NIST / RFC test vectors for self_test()
|
|
||||||
// These are checked at runtime; failures gate the provider from being marked
|
|
||||||
// `available` in the capability catalog.
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
struct AeadVector {
|
|
||||||
algo: AeadAlgorithm,
|
|
||||||
key: &'static str,
|
|
||||||
nonce: &'static str,
|
|
||||||
aad: &'static str,
|
|
||||||
pt: &'static str,
|
|
||||||
ct_tag: &'static str, // ciphertext || tag, hex-encoded
|
|
||||||
}
|
|
||||||
|
|
||||||
/// NIST SP 800-38D and RFC 8439 test vectors.
|
|
||||||
static AEAD_VECTORS: &[AeadVector] = &[
|
|
||||||
// ── AES-256-GCM: NIST CAVS test case GCM-256/96/128 (test case 1) ───────
|
|
||||||
AeadVector {
|
|
||||||
algo: AeadAlgorithm::AesGcm256,
|
|
||||||
key: "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
|
||||||
nonce: "cafebabefacedbaddecaf888",
|
|
||||||
aad: "",
|
|
||||||
pt: "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72\
|
|
||||||
1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
|
|
||||||
ct_tag: "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa\
|
|
||||||
8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
|
|
||||||
},
|
|
||||||
// ── ChaCha20-Poly1305: RFC 8439 §2.8.2 test vector ──────────────────────
|
|
||||||
AeadVector {
|
|
||||||
algo: AeadAlgorithm::ChaCha20Poly1305,
|
|
||||||
key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
|
|
||||||
nonce: "070000004041424344454647",
|
|
||||||
aad: "50515253c0c1c2c3c4c5c6c7",
|
|
||||||
pt: "4c616469657320616e642047656e746c656d656e206f662074686520636c617373\
|
|
||||||
206f6620273939",
|
|
||||||
ct_tag: "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63\
|
|
||||||
dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b369\
|
|
||||||
2ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3\
|
|
||||||
ff4def08e4b7a9de576d26586cec64b6116",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
// WolfSslProvider
|
// WolfSslProvider
|
||||||
|
|
@ -220,15 +177,7 @@ impl CryptoProvider for WolfSslProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn self_test(&self) -> SelfTestReport {
|
fn self_test(&self) -> SelfTestReport {
|
||||||
let mut results: Vec<AlgoTestResult> = Vec::new();
|
self_test::run()
|
||||||
|
|
||||||
// Run AEAD test vectors.
|
|
||||||
for v in AEAD_VECTORS {
|
|
||||||
let result = run_aead_vector(v);
|
|
||||||
results.push(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
SelfTestReport::finalise("wolfssl", results)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn benchmark(&self) -> BenchmarkReport {
|
fn benchmark(&self) -> BenchmarkReport {
|
||||||
|
|
@ -236,48 +185,4 @@ impl CryptoProvider for WolfSslProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
// Test vector runner
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
fn run_aead_vector(v: &AeadVector) -> AlgoTestResult {
|
|
||||||
let test_name = format!("{} NIST/RFC vector", v.algo.name());
|
|
||||||
|
|
||||||
let decode = |hex: &str| -> Vec<u8> {
|
|
||||||
(0..hex.len())
|
|
||||||
.step_by(2)
|
|
||||||
.map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap_or(0))
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
let key = decode(v.key);
|
|
||||||
let nonce = decode(v.nonce);
|
|
||||||
let aad = decode(v.aad);
|
|
||||||
let pt = decode(v.pt);
|
|
||||||
let expected = decode(v.ct_tag);
|
|
||||||
|
|
||||||
match aead::encrypt(v.algo, &key, &nonce, &pt, &aad) {
|
|
||||||
Ok(ct_tag) if ct_tag == expected => AlgoTestResult {
|
|
||||||
algo_id: v.algo as u32,
|
|
||||||
algo_name: test_name,
|
|
||||||
passed: true,
|
|
||||||
error_message: None,
|
|
||||||
},
|
|
||||||
Ok(ct_tag) => AlgoTestResult {
|
|
||||||
algo_id: v.algo as u32,
|
|
||||||
algo_name: test_name.clone(),
|
|
||||||
passed: false,
|
|
||||||
error_message: Some(format!(
|
|
||||||
"output mismatch: got {} bytes, expected {} bytes",
|
|
||||||
ct_tag.len(),
|
|
||||||
expected.len()
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
Err(e) => AlgoTestResult {
|
|
||||||
algo_id: v.algo as u32,
|
|
||||||
algo_name: test_name,
|
|
||||||
passed: false,
|
|
||||||
error_message: Some(e.to_string()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
//! Embedded NIST / RFC test vectors for the power-on self-test.
|
||||||
|
//!
|
||||||
|
//! These are checked at runtime by [`WolfSslProvider::self_test()`]; failures
|
||||||
|
//! gate the provider from being marked `available` in the capability catalog.
|
||||||
|
|
||||||
|
use ccc_crypto_core::{
|
||||||
|
algorithms::AeadAlgorithm,
|
||||||
|
types::{AlgoTestResult, SelfTestReport},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::aead;
|
||||||
|
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
// AEAD vectors
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
struct AeadVector {
|
||||||
|
algo: AeadAlgorithm,
|
||||||
|
key: &'static str,
|
||||||
|
nonce: &'static str,
|
||||||
|
aad: &'static str,
|
||||||
|
pt: &'static str,
|
||||||
|
ct_tag: &'static str, // ciphertext || tag, hex-encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST SP 800-38D and RFC 8439 test vectors.
|
||||||
|
static AEAD_VECTORS: &[AeadVector] = &[
|
||||||
|
// ── AES-256-GCM: NIST SP 800-38D Test Case 16 ───────────────────────
|
||||||
|
// Key: feffe9...308308 × 2 (AES-256)
|
||||||
|
// Nonce: cafebabefacedbaddecaf888
|
||||||
|
// AAD: feedfacedeadbeeffeedfacedeadbeefabaddad2 (20 bytes)
|
||||||
|
// PT: d9313225...637b39 (60 bytes)
|
||||||
|
// ct_tag = ciphertext (60 bytes) || GHASH tag (16 bytes) = 76 bytes
|
||||||
|
AeadVector {
|
||||||
|
algo: AeadAlgorithm::AesGcm256,
|
||||||
|
key: "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
|
||||||
|
nonce: "cafebabefacedbaddecaf888",
|
||||||
|
aad: "feedfacedeadbeeffeedfacedeadbeefabaddad2",
|
||||||
|
pt: "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72\
|
||||||
|
1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
|
||||||
|
ct_tag: "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa\
|
||||||
|
8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662\
|
||||||
|
76fc6ece0f4e1768cddf8853bb2d551b",
|
||||||
|
},
|
||||||
|
// ── ChaCha20-Poly1305: RFC 8439 §2.8.2 ──────────────────────────────
|
||||||
|
// PT: "Ladies and Gentlemen of the class of '99" (40 bytes)
|
||||||
|
// ct_tag = ciphertext (40 bytes) || Poly1305 tag (16 bytes) = 56 bytes
|
||||||
|
AeadVector {
|
||||||
|
algo: AeadAlgorithm::ChaCha20Poly1305,
|
||||||
|
key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
|
||||||
|
nonce: "070000004041424344454647",
|
||||||
|
aad: "50515253c0c1c2c3c4c5c6c7",
|
||||||
|
pt: "4c616469657320616e642047656e746c656d656e206f662074686520636c617373\
|
||||||
|
206f6620273939",
|
||||||
|
ct_tag: "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6\
|
||||||
|
3dbea45e8ca96712f180d4e9016c65a7dde15e3106075ebd",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
// Runner
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Run all embedded self-test vectors and return a [`SelfTestReport`].
|
||||||
|
pub(crate) fn run() -> SelfTestReport {
|
||||||
|
let mut results: Vec<AlgoTestResult> = Vec::new();
|
||||||
|
for v in AEAD_VECTORS {
|
||||||
|
results.push(run_aead_vector(v));
|
||||||
|
}
|
||||||
|
SelfTestReport::finalise("wolfssl", results)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_aead_vector(v: &AeadVector) -> AlgoTestResult {
|
||||||
|
let test_name = format!("{} NIST/RFC vector", v.algo.name());
|
||||||
|
|
||||||
|
let decode = |hex: &str| -> Vec<u8> {
|
||||||
|
(0..hex.len())
|
||||||
|
.step_by(2)
|
||||||
|
.map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap_or(0))
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
let key = decode(v.key);
|
||||||
|
let nonce = decode(v.nonce);
|
||||||
|
let aad = decode(v.aad);
|
||||||
|
let pt = decode(v.pt);
|
||||||
|
let expected = decode(v.ct_tag);
|
||||||
|
|
||||||
|
match aead::encrypt(v.algo, &key, &nonce, &pt, &aad) {
|
||||||
|
Ok(ct_tag) if ct_tag == expected => AlgoTestResult {
|
||||||
|
algo_id: v.algo as u32,
|
||||||
|
algo_name: test_name,
|
||||||
|
passed: true,
|
||||||
|
error_message: None,
|
||||||
|
},
|
||||||
|
Ok(ct_tag) => AlgoTestResult {
|
||||||
|
algo_id: v.algo as u32,
|
||||||
|
algo_name: test_name.clone(),
|
||||||
|
passed: false,
|
||||||
|
error_message: Some(format!(
|
||||||
|
"output mismatch: got {} bytes, expected {} bytes",
|
||||||
|
ct_tag.len(),
|
||||||
|
expected.len()
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Err(e) => AlgoTestResult {
|
||||||
|
algo_id: v.algo as u32,
|
||||||
|
algo_name: test_name,
|
||||||
|
passed: false,
|
||||||
|
error_message: Some(e.to_string()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue