#[cfg(feature = "alloc")]
use alloc::{
string::ToString,
vec::Vec,
};
use crate::api::{
AeadOperations,
Algorithm,
};
use crate::error::Result;
use crate::security::SecurityValidator;
use crate::traits::{
AeadKey,
Nonce,
};
#[cfg(feature = "alloc")]
#[derive(Clone)]
pub struct LibQAeadStubProvider {
security_validator: SecurityValidator,
}
#[cfg(feature = "alloc")]
impl LibQAeadStubProvider {
pub fn new() -> Result<Self> {
Ok(Self {
security_validator: SecurityValidator::new()?,
})
}
}
#[cfg(feature = "alloc")]
impl AeadOperations for LibQAeadStubProvider {
fn encrypt(
&self,
algorithm: Algorithm,
key: &AeadKey,
nonce: &Nonce,
plaintext: &[u8],
associated_data: Option<&[u8]>,
) -> Result<Vec<u8>> {
self.security_validator
.validate_algorithm_category(algorithm, crate::api::AlgorithmCategory::Aead)?;
self.security_validator
.validate_key_material(key.as_bytes())?;
self.security_validator.validate_nonce(nonce.as_bytes())?;
self.security_validator.validate_aead_message(plaintext)?;
if let Some(ad) = associated_data {
self.security_validator.validate_aead_message(ad)?;
}
Err(crate::error::Error::NotImplemented {
feature: "AEAD — use `lib_q_aead::LibQAeadProvider`, `libq::aead::context()`, or `AeadContext::with_aead_operations`"
.to_string(),
})
}
fn decrypt(
&self,
algorithm: Algorithm,
key: &AeadKey,
nonce: &Nonce,
ciphertext: &[u8],
associated_data: Option<&[u8]>,
) -> Result<Vec<u8>> {
self.security_validator
.validate_algorithm_category(algorithm, crate::api::AlgorithmCategory::Aead)?;
self.security_validator
.validate_key_material(key.as_bytes())?;
self.security_validator.validate_nonce(nonce.as_bytes())?;
self.security_validator
.validate_ciphertext(algorithm, ciphertext)?;
if let Some(ad) = associated_data {
self.security_validator.validate_aead_message(ad)?;
}
Err(crate::error::Error::NotImplemented {
feature: "AEAD — use `lib_q_aead::LibQAeadProvider`, `libq::aead::context()`, or `AeadContext::with_aead_operations`"
.to_string(),
})
}
}
#[cfg(test)]
#[cfg(feature = "alloc")]
mod tests {
use super::*;
#[test]
fn test_aead_stub_provider_creation() {
let provider = LibQAeadStubProvider::new();
assert!(
provider.is_ok(),
"LibQAeadStubProvider should be created successfully"
);
}
#[test]
fn test_aead_stub_unsupported_algorithm() {
let provider = LibQAeadStubProvider::new().unwrap();
let key = AeadKey::new(vec![0u8; 32]);
let nonce = Nonce::new(vec![0u8; 16]);
let result = provider.encrypt(Algorithm::MlKem512, &key, &nonce, b"test", None);
assert!(
result.is_err(),
"Should return error for unsupported algorithm"
);
if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
} else {
panic!("Expected InvalidAlgorithm error");
}
}
#[test]
fn test_aead_stub_unregistered_aead_algorithm() {
let provider = LibQAeadStubProvider::new().unwrap();
let key = AeadKey::new(vec![
0xA3, 0x17, 0x5B, 0xE2, 0x94, 0x0D, 0x68, 0xF1, 0x3C, 0x86, 0xD5, 0x4A, 0x72, 0xBE,
0x09, 0xC7, 0x58, 0xE4, 0x1F, 0x8B, 0xA0, 0x63, 0xD9, 0x2E, 0x7D, 0x45, 0xFB, 0x16,
0xCA, 0x30, 0x9E, 0x54,
]);
let nonce = Nonce::new(vec![
0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x70, 0x81, 0x92, 0xA3, 0xB4, 0xC5, 0xD6, 0xE7,
0xF8, 0x09,
]);
let result = provider.encrypt(Algorithm::Saturnin, &key, &nonce, b"test", None);
assert!(
result.is_err(),
"Should return error when feature flag is not enabled"
);
if let Err(crate::error::Error::NotImplemented { feature }) = result {
assert!(
feature.contains("LibQAeadProvider") || feature.contains("libq::aead::context"),
"Error should direct callers to lib-q-aead / libq::aead::context(): {feature}"
);
} else {
panic!("Expected NotImplemented error, got: {:?}", result);
}
}
}