1#[cfg(feature = "alloc")]
4use alloc::boxed::Box;
5use alloc::vec::Vec;
6
7use lib_q_core::{
8 Aead,
9 AeadDecryptSemantic,
10 AeadKey,
11 Algorithm,
12 DecryptSemanticOutcome,
13 Nonce,
14 Result,
15};
16
17use crate::metadata::{
18 AeadMetadata,
19 AeadWithMetadata,
20};
21
22pub struct TweakAead {
24 metadata: &'static AeadMetadata,
25 inner: lib_q_tweak_aead::TweakAead,
26}
27
28impl TweakAead {
29 pub fn new() -> Self {
30 Self {
31 metadata: crate::metadata::get_metadata(Algorithm::TweakAead)
32 .expect("TweakAead metadata"),
33 inner: lib_q_tweak_aead::TweakAead::new(),
34 }
35 }
36}
37
38impl Aead for TweakAead {
39 fn encrypt(
40 &self,
41 key: &AeadKey,
42 nonce: &Nonce,
43 plaintext: &[u8],
44 associated_data: Option<&[u8]>,
45 ) -> Result<Vec<u8>> {
46 self.validate_key(key)?;
47 self.validate_nonce(nonce)?;
48 crate::security::validation::validate_plaintext(plaintext)?;
49 let ad = associated_data.unwrap_or(&[]);
50 crate::security::validation::validate_associated_data(ad)?;
51 self.inner.encrypt(key, nonce, plaintext, Some(ad))
52 }
53
54 fn decrypt(
55 &self,
56 key: &AeadKey,
57 nonce: &Nonce,
58 ciphertext: &[u8],
59 associated_data: Option<&[u8]>,
60 ) -> Result<Vec<u8>> {
61 self.validate_key(key)?;
62 self.validate_nonce(nonce)?;
63 self.validate_ciphertext_size(ciphertext.len())?;
64 crate::security::validation::validate_ciphertext(ciphertext)?;
65 let ad = associated_data.unwrap_or(&[]);
66 crate::security::validation::validate_associated_data(ad)?;
67 self.inner.decrypt(key, nonce, ciphertext, Some(ad))
68 }
69}
70
71impl AeadDecryptSemantic for TweakAead {
72 fn decrypt_semantic(
73 &self,
74 key: &AeadKey,
75 nonce: &Nonce,
76 ciphertext: &[u8],
77 associated_data: Option<&[u8]>,
78 ) -> Result<DecryptSemanticOutcome> {
79 self.validate_key(key)?;
80 self.validate_nonce(nonce)?;
81 self.validate_ciphertext_size(ciphertext.len())?;
82 crate::security::validation::validate_ciphertext(ciphertext)?;
83 let ad = associated_data.unwrap_or(&[]);
84 crate::security::validation::validate_associated_data(ad)?;
85 self.inner
86 .decrypt_semantic(key, nonce, ciphertext, Some(ad))
87 }
88}
89
90impl AeadWithMetadata for TweakAead {
91 fn metadata(&self) -> &'static AeadMetadata {
92 self.metadata
93 }
94}
95
96impl Default for TweakAead {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102impl crate::plugin::AeadPlugin for TweakAead {
103 fn algorithm(&self) -> Algorithm {
104 Algorithm::TweakAead
105 }
106
107 fn create(&self) -> Result<Box<dyn AeadWithMetadata>> {
108 Ok(Box::new(Self::new()))
109 }
110
111 fn metadata(&self) -> &'static AeadMetadata {
112 crate::metadata::get_metadata(Algorithm::TweakAead).expect("TweakAead metadata")
113 }
114
115 fn name(&self) -> &'static str {
116 "Tweak-AEAD"
117 }
118
119 fn version(&self) -> &'static str {
120 "1.0.0"
121 }
122
123 fn description(&self) -> &'static str {
124 "Parallel tweakable-block CTR AEAD over Keccak-f[1600]"
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn metadata_matches() {
134 let a = TweakAead::new();
135 assert_eq!(a.algorithm(), Algorithm::TweakAead);
136 assert_eq!(a.key_size(), 32);
137 assert_eq!(a.nonce_size(), 16);
138 assert_eq!(a.tag_size(), 32);
139 }
140}