1#[cfg(feature = "alloc")]
7use alloc::{
8 string::ToString,
9 vec::Vec,
10};
11
12use crate::api::{
13 AeadOperations,
14 Algorithm,
15};
16use crate::error::Result;
17use crate::security::SecurityValidator;
18use crate::traits::{
19 AeadKey,
20 Nonce,
21};
22
23#[cfg(feature = "alloc")]
27#[derive(Clone)]
28pub struct LibQAeadStubProvider {
29 security_validator: SecurityValidator,
30}
31
32#[cfg(feature = "alloc")]
33impl LibQAeadStubProvider {
34 pub fn new() -> Result<Self> {
36 Ok(Self {
37 security_validator: SecurityValidator::new()?,
38 })
39 }
40}
41
42#[cfg(feature = "alloc")]
43impl AeadOperations for LibQAeadStubProvider {
44 fn encrypt(
45 &self,
46 algorithm: Algorithm,
47 key: &AeadKey,
48 nonce: &Nonce,
49 plaintext: &[u8],
50 associated_data: Option<&[u8]>,
51 ) -> Result<Vec<u8>> {
52 self.security_validator
54 .validate_algorithm_category(algorithm, crate::api::AlgorithmCategory::Aead)?;
55
56 self.security_validator
58 .validate_key_material(key.as_bytes())?;
59
60 self.security_validator.validate_nonce(nonce.as_bytes())?;
62
63 self.security_validator.validate_aead_message(plaintext)?;
65
66 if let Some(ad) = associated_data {
68 self.security_validator.validate_aead_message(ad)?;
69 }
70
71 Err(crate::error::Error::NotImplemented {
72 feature: "AEAD — use `lib_q_aead::LibQAeadProvider`, `libq::aead::context()`, or `AeadContext::with_aead_operations`"
73 .to_string(),
74 })
75 }
76
77 fn decrypt(
78 &self,
79 algorithm: Algorithm,
80 key: &AeadKey,
81 nonce: &Nonce,
82 ciphertext: &[u8],
83 associated_data: Option<&[u8]>,
84 ) -> Result<Vec<u8>> {
85 self.security_validator
87 .validate_algorithm_category(algorithm, crate::api::AlgorithmCategory::Aead)?;
88
89 self.security_validator
91 .validate_key_material(key.as_bytes())?;
92
93 self.security_validator.validate_nonce(nonce.as_bytes())?;
95
96 self.security_validator
98 .validate_ciphertext(algorithm, ciphertext)?;
99
100 if let Some(ad) = associated_data {
102 self.security_validator.validate_aead_message(ad)?;
103 }
104
105 Err(crate::error::Error::NotImplemented {
106 feature: "AEAD — use `lib_q_aead::LibQAeadProvider`, `libq::aead::context()`, or `AeadContext::with_aead_operations`"
107 .to_string(),
108 })
109 }
110}
111
112#[cfg(test)]
113#[cfg(feature = "alloc")]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_aead_stub_provider_creation() {
119 let provider = LibQAeadStubProvider::new();
120 assert!(
121 provider.is_ok(),
122 "LibQAeadStubProvider should be created successfully"
123 );
124 }
125
126 #[test]
127 fn test_aead_stub_unsupported_algorithm() {
128 let provider = LibQAeadStubProvider::new().unwrap();
129 let key = AeadKey::new(vec![0u8; 32]);
130 let nonce = Nonce::new(vec![0u8; 16]);
131 let result = provider.encrypt(Algorithm::MlKem512, &key, &nonce, b"test", None);
132 assert!(
133 result.is_err(),
134 "Should return error for unsupported algorithm"
135 );
136
137 if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
138 } else {
140 panic!("Expected InvalidAlgorithm error");
141 }
142 }
143
144 #[test]
145 fn test_aead_stub_unregistered_aead_algorithm() {
146 let provider = LibQAeadStubProvider::new().unwrap();
147 let key = AeadKey::new(vec![
149 0xA3, 0x17, 0x5B, 0xE2, 0x94, 0x0D, 0x68, 0xF1, 0x3C, 0x86, 0xD5, 0x4A, 0x72, 0xBE,
150 0x09, 0xC7, 0x58, 0xE4, 0x1F, 0x8B, 0xA0, 0x63, 0xD9, 0x2E, 0x7D, 0x45, 0xFB, 0x16,
151 0xCA, 0x30, 0x9E, 0x54,
152 ]);
153 let nonce = Nonce::new(vec![
154 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x70, 0x81, 0x92, 0xA3, 0xB4, 0xC5, 0xD6, 0xE7,
155 0xF8, 0x09,
156 ]);
157
158 let result = provider.encrypt(Algorithm::Saturnin, &key, &nonce, b"test", None);
160 assert!(
161 result.is_err(),
162 "Should return error when feature flag is not enabled"
163 );
164
165 if let Err(crate::error::Error::NotImplemented { feature }) = result {
166 assert!(
167 feature.contains("LibQAeadProvider") || feature.contains("libq::aead::context"),
168 "Error should direct callers to lib-q-aead / libq::aead::context(): {feature}"
169 );
170 } else {
171 panic!("Expected NotImplemented error, got: {:?}", result);
172 }
173 }
174}