lib_q_core/contexts/
aead.rs1#[cfg(feature = "alloc")]
7use alloc::{
8 boxed::Box,
9 string::String,
10 vec::Vec,
11};
12
13use super::BaseContext;
14use crate::api::{
15 AeadOperations,
16 Algorithm,
17 AlgorithmCategory,
18 CryptoProvider,
19 HashOperations,
20 KemOperations,
21 SignatureOperations,
22};
23use crate::error::Result;
24use crate::traits::{
25 AeadKey,
26 Nonce,
27};
28
29#[cfg(feature = "alloc")]
31pub struct AeadOperationsBridge {
32 aead: Box<dyn AeadOperations + Send + Sync>,
33}
34
35#[cfg(feature = "alloc")]
36impl CryptoProvider for AeadOperationsBridge {
37 fn kem(&self) -> Option<&dyn KemOperations> {
38 None
39 }
40
41 fn signature(&self) -> Option<&dyn SignatureOperations> {
42 None
43 }
44
45 fn hash(&self) -> Option<&dyn HashOperations> {
46 None
47 }
48
49 fn aead(&self) -> Option<&dyn AeadOperations> {
50 Some(self.aead.as_ref())
51 }
52}
53
54#[cfg(feature = "alloc")]
56pub struct AeadContext {
57 inner: BaseContext<Self>,
58}
59
60#[cfg(feature = "alloc")]
61impl AeadContext {
62 pub fn new() -> Self {
68 Self {
69 inner: BaseContext::new(),
70 }
71 }
72
73 pub fn with_provider(provider: Box<dyn CryptoProvider>) -> Self {
75 Self {
76 inner: BaseContext::with_provider(provider),
77 }
78 }
79
80 pub fn with_aead_operations(aead: Box<dyn AeadOperations + Send + Sync>) -> Self {
85 Self {
86 inner: BaseContext::with_provider(Box::new(AeadOperationsBridge { aead })),
87 }
88 }
89
90 #[cfg(feature = "alloc")]
92 pub fn with_default_provider() -> Self {
93 Self {
94 inner: match crate::providers::LibQCryptoProvider::new() {
95 Ok(provider) => BaseContext::with_provider(Box::new(provider)),
96 Err(_) => BaseContext::new(),
97 },
98 }
99 }
100
101 pub fn set_provider(&mut self, provider: Box<dyn CryptoProvider>) {
103 self.inner.set_provider(provider);
104 }
105
106 pub fn provider(&self) -> Option<&dyn CryptoProvider> {
108 self.inner.provider()
109 }
110
111 pub fn encrypt(
113 &mut self,
114 algorithm: Algorithm,
115 key: &AeadKey,
116 nonce: &Nonce,
117 plaintext: &[u8],
118 associated_data: Option<&[u8]>,
119 ) -> Result<Vec<u8>> {
120 self.inner.ensure_initialized()?;
121
122 if algorithm.category() != AlgorithmCategory::Aead {
124 return Err(crate::error::Error::InvalidAlgorithm {
125 algorithm: "Algorithm is not an AEAD algorithm",
126 });
127 }
128
129 match self.inner.provider().and_then(|p| p.aead()) {
131 Some(aead_ops) => aead_ops.encrypt(algorithm, key, nonce, plaintext, associated_data),
132 None => Err(crate::error::Error::ProviderNotConfigured {
133 operation: String::from("AEAD"),
134 }),
135 }
136 }
137
138 pub fn decrypt(
144 &self,
145 algorithm: Algorithm,
146 key: &AeadKey,
147 nonce: &Nonce,
148 ciphertext: &[u8],
149 associated_data: Option<&[u8]>,
150 ) -> Result<Vec<u8>> {
151 if !self.inner.is_initialized() {
152 return Err(crate::error::Error::InvalidState {
153 operation: String::from("decrypt"),
154 reason: String::from("Context not initialized"),
155 });
156 }
157
158 if algorithm.category() != AlgorithmCategory::Aead {
160 return Err(crate::error::Error::InvalidAlgorithm {
161 algorithm: "Algorithm is not an AEAD algorithm",
162 });
163 }
164
165 match self.inner.provider().and_then(|p| p.aead()) {
167 Some(aead_ops) => aead_ops.decrypt(algorithm, key, nonce, ciphertext, associated_data),
168 None => Err(crate::error::Error::ProviderNotConfigured {
169 operation: String::from("AEAD"),
170 }),
171 }
172 }
173
174 pub fn is_initialized(&self) -> bool {
176 self.inner.is_initialized()
177 }
178}
179
180#[cfg(feature = "alloc")]
181impl Default for AeadContext {
182 fn default() -> Self {
183 Self::new()
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::api::{
191 AeadOperations,
192 CryptoProvider,
193 HashOperations,
194 KemOperations,
195 SignatureOperations,
196 };
197
198 struct MockAeadProvider;
200
201 impl CryptoProvider for MockAeadProvider {
202 fn kem(&self) -> Option<&dyn KemOperations> {
203 None
204 }
205 fn signature(&self) -> Option<&dyn SignatureOperations> {
206 None
207 }
208 fn hash(&self) -> Option<&dyn HashOperations> {
209 None
210 }
211 fn aead(&self) -> Option<&dyn AeadOperations> {
212 Some(self)
213 }
214 }
215
216 impl AeadOperations for MockAeadProvider {
217 fn encrypt(
218 &self,
219 _algorithm: Algorithm,
220 _key: &AeadKey,
221 _nonce: &Nonce,
222 _plaintext: &[u8],
223 _associated_data: Option<&[u8]>,
224 ) -> Result<Vec<u8>> {
225 Err(crate::error::Error::NotImplemented {
226 feature: "Mock AEAD operations not implemented".to_string(),
227 })
228 }
229
230 fn decrypt(
231 &self,
232 _algorithm: Algorithm,
233 _key: &AeadKey,
234 _nonce: &Nonce,
235 _ciphertext: &[u8],
236 _associated_data: Option<&[u8]>,
237 ) -> Result<Vec<u8>> {
238 Err(crate::error::Error::NotImplemented {
239 feature: "Mock AEAD operations not implemented".to_string(),
240 })
241 }
242 }
243
244 #[test]
245 fn test_aead_context_with_aead_operations_bridge() {
246 let context = AeadContext::with_aead_operations(Box::new(MockAeadProvider));
247 assert!(!context.is_initialized());
248 assert!(context.provider().is_some());
249 assert!(context.provider().unwrap().aead().is_some());
250 }
251
252 #[test]
253 fn test_aead_context_creation() {
254 let context = AeadContext::new();
255 assert!(!context.is_initialized());
256 assert!(context.provider().is_none());
257 }
258
259 #[test]
260 fn test_aead_context_with_provider() {
261 let provider = Box::new(MockAeadProvider);
262 let context = AeadContext::with_provider(provider);
263 assert!(!context.is_initialized());
264 assert!(context.provider().is_some());
265 }
266
267 #[test]
268 fn test_aead_context_provider_management() {
269 let mut context = AeadContext::new();
270 assert!(context.provider().is_none());
271
272 let provider = Box::new(MockAeadProvider);
273 context.set_provider(provider);
274 assert!(context.provider().is_some());
275 }
276
277 #[test]
278 fn test_aead_context_initialization() {
279 let mut context = AeadContext::new();
280 assert!(!context.is_initialized());
281
282 let key = AeadKey::new(vec![0u8; 32]);
283 let nonce = Nonce::new(vec![0u8; 16]);
284
285 let result = context.encrypt(Algorithm::Saturnin, &key, &nonce, b"test data", None);
287 assert!(result.is_err()); assert!(context.is_initialized());
289 }
290
291 #[test]
292 fn test_aead_context_algorithm_validation() {
293 let mut context = AeadContext::new();
294 let key = AeadKey::new(vec![0u8; 32]);
295 let nonce = Nonce::new(vec![0u8; 16]);
296
297 let result = context.encrypt(Algorithm::MlKem512, &key, &nonce, b"test data", None);
299 assert!(result.is_err());
300 if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
301 } else {
303 panic!("Expected InvalidAlgorithm error");
304 }
305 }
306}