dcrypt_algorithms/aead/
mod.rs1#[cfg(feature = "alloc")]
36extern crate alloc;
37
38#[cfg(feature = "alloc")]
40pub mod gcm;
41
42#[cfg(feature = "alloc")]
43pub mod chacha20poly1305;
44
45#[cfg(feature = "alloc")]
46pub mod xchacha20poly1305;
47
48#[cfg(feature = "alloc")]
50pub use self::gcm::Gcm;
51
52#[cfg(feature = "alloc")]
53pub use self::chacha20poly1305::ChaCha20Poly1305;
54
55#[cfg(feature = "alloc")]
56pub use self::xchacha20poly1305::XChaCha20Poly1305;
57
58use crate::error::{Error, Result};
59use crate::types::{Nonce, SecretBytes};
60#[cfg(feature = "alloc")]
61use alloc::vec::Vec;
62use dcrypt_internal::random::{try_fill_bytes_zeroing_on_error, CryptoRng, RngCore};
63use dcrypt_internal::zeroing::{Zeroize, Zeroizing};
64
65pub trait AeadAlgorithm {
67 const KEY_SIZE: usize;
69
70 const TAG_SIZE: usize;
72
73 fn name() -> &'static str;
75}
76
77pub enum ChaCha20Poly1305Algorithm {}
79
80impl AeadAlgorithm for ChaCha20Poly1305Algorithm {
81 const KEY_SIZE: usize = 32;
82 const TAG_SIZE: usize = 16;
83
84 fn name() -> &'static str {
85 "ChaCha20-Poly1305"
86 }
87}
88
89pub trait Operation<T> {
91 fn execute(self) -> Result<T>;
93
94 fn reset(&mut self);
96}
97
98pub trait AeadEncryptOperation<'a, A: AeadAlgorithm>: Operation<Vec<u8>> {
100 fn with_nonce(self, nonce: &'a Nonce<12>) -> Self;
102
103 fn with_aad(self, aad: &'a [u8]) -> Self;
105
106 fn encrypt(self, plaintext: &'a [u8]) -> Result<Vec<u8>>;
108}
109
110pub trait AeadDecryptOperation<'a, A: AeadAlgorithm>: Operation<Vec<u8>> {
112 fn with_nonce(self, nonce: &'a Nonce<12>) -> Self;
114
115 fn with_aad(self, aad: &'a [u8]) -> Self;
117
118 fn decrypt(self, ciphertext: &'a [u8]) -> Result<Vec<u8>>;
120}
121
122pub trait AeadCipher {
124 type Algorithm: AeadAlgorithm;
126
127 type Key: AsRef<[u8]> + AsMut<[u8]> + Clone + Zeroize;
129
130 fn new(key: &Self::Key) -> Result<Self>
132 where
133 Self: Sized;
134
135 fn encrypt(&self) -> impl AeadEncryptOperation<'_, Self::Algorithm>;
137
138 fn decrypt(&self) -> impl AeadDecryptOperation<'_, Self::Algorithm>;
140
141 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self::Key>;
143
144 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Nonce<12>>;
146
147 fn name() -> &'static str {
149 Self::Algorithm::name()
150 }
151
152 fn key_size() -> usize {
154 Self::Algorithm::KEY_SIZE
155 }
156
157 fn tag_size() -> usize {
159 Self::Algorithm::TAG_SIZE
160 }
161}
162
163#[cfg(feature = "alloc")]
165pub struct ChaCha20Poly1305Cipher {
166 inner: chacha20poly1305::ChaCha20Poly1305,
167}
168
169#[cfg(feature = "alloc")]
170impl AeadCipher for ChaCha20Poly1305Cipher {
171 type Algorithm = ChaCha20Poly1305Algorithm;
172 type Key = SecretBytes<32>;
173
174 fn new(key: &Self::Key) -> Result<Self> {
175 let mut key_array = Zeroizing::new([0u8; 32]);
176 key_array.copy_from_slice(key.as_ref());
177
178 let inner = chacha20poly1305::ChaCha20Poly1305::new(&*key_array);
179
180 Ok(Self { inner })
181 }
182
183 fn encrypt(&self) -> impl AeadEncryptOperation<'_, Self::Algorithm> {
184 ChaCha20Poly1305EncryptOperation {
185 cipher: self,
186 nonce: None,
187 aad: None,
188 }
189 }
190
191 fn decrypt(&self) -> impl AeadDecryptOperation<'_, Self::Algorithm> {
192 ChaCha20Poly1305DecryptOperation {
193 cipher: self,
194 nonce: None,
195 aad: None,
196 }
197 }
198
199 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self::Key> {
200 let mut key = Zeroizing::new([0u8; 32]);
201 try_fill_bytes_zeroing_on_error(rng, &mut key[..])?;
202 Ok(SecretBytes::new(*key))
203 }
204
205 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Nonce<12>> {
206 let mut nonce = [0u8; 12];
207 try_fill_bytes_zeroing_on_error(rng, &mut nonce)?;
208 Ok(Nonce::<12>::new(nonce))
209 }
210}
211
212#[cfg(feature = "alloc")]
214pub struct ChaCha20Poly1305EncryptOperation<'a> {
215 cipher: &'a ChaCha20Poly1305Cipher,
216 nonce: Option<&'a Nonce<12>>,
217 aad: Option<&'a [u8]>,
218}
219
220#[cfg(feature = "alloc")]
221impl Operation<Vec<u8>> for ChaCha20Poly1305EncryptOperation<'_> {
222 fn execute(self) -> Result<Vec<u8>> {
223 Err(Error::param("operation", "use encrypt method instead"))
224 }
225
226 fn reset(&mut self) {
227 self.nonce = None;
228 self.aad = None;
229 }
230}
231
232#[cfg(feature = "alloc")]
233impl<'a> AeadEncryptOperation<'a, ChaCha20Poly1305Algorithm>
234 for ChaCha20Poly1305EncryptOperation<'a>
235{
236 fn with_nonce(mut self, nonce: &'a Nonce<12>) -> Self {
237 self.nonce = Some(nonce);
238 self
239 }
240
241 fn with_aad(mut self, aad: &'a [u8]) -> Self {
242 self.aad = Some(aad);
243 self
244 }
245
246 fn encrypt(self, plaintext: &'a [u8]) -> Result<Vec<u8>> {
247 let nonce = self.nonce.ok_or_else(|| {
248 Error::param("nonce", "nonce is required for ChaCha20Poly1305 encryption")
249 })?;
250
251 self.cipher.inner.encrypt(nonce, plaintext, self.aad)
252 }
253}
254
255#[cfg(feature = "alloc")]
257pub struct ChaCha20Poly1305DecryptOperation<'a> {
258 cipher: &'a ChaCha20Poly1305Cipher,
259 nonce: Option<&'a Nonce<12>>,
260 aad: Option<&'a [u8]>,
261}
262
263#[cfg(feature = "alloc")]
264impl Operation<Vec<u8>> for ChaCha20Poly1305DecryptOperation<'_> {
265 fn execute(self) -> Result<Vec<u8>> {
266 Err(Error::param("operation", "use decrypt method instead"))
267 }
268
269 fn reset(&mut self) {
270 self.nonce = None;
271 self.aad = None;
272 }
273}
274
275#[cfg(feature = "alloc")]
276impl<'a> AeadDecryptOperation<'a, ChaCha20Poly1305Algorithm>
277 for ChaCha20Poly1305DecryptOperation<'a>
278{
279 fn with_nonce(mut self, nonce: &'a Nonce<12>) -> Self {
280 self.nonce = Some(nonce);
281 self
282 }
283
284 fn with_aad(mut self, aad: &'a [u8]) -> Self {
285 self.aad = Some(aad);
286 self
287 }
288
289 fn decrypt(self, ciphertext: &'a [u8]) -> Result<Vec<u8>> {
290 let nonce = self.nonce.ok_or_else(|| {
291 Error::param("nonce", "nonce is required for ChaCha20Poly1305 decryption")
292 })?;
293
294 self.cipher.inner.decrypt(nonce, ciphertext, self.aad)
295 }
296}