dcrypt_algorithms/block/
mod.rs1#![cfg_attr(not(feature = "std"), no_std)]
29
30#[cfg(feature = "alloc")]
31extern crate alloc;
32
33#[cfg(not(feature = "std"))]
34use alloc::vec::Vec;
35use zeroize::{Zeroize, ZeroizeOnDrop};
36
37use crate::error::{validate, Error, Result};
38use crate::types::{Nonce, SecretBytes};
39use rand::{CryptoRng, RngCore};
40
41pub mod aes;
42pub mod modes;
43
44pub use aes::{Aes128, Aes192, Aes256};
46pub use modes::{cbc::Cbc, ctr::Ctr};
47
48pub trait CipherAlgorithm {
50 const KEY_SIZE: usize;
52
53 const BLOCK_SIZE: usize;
55
56 fn name() -> &'static str;
58}
59
60pub trait AesVariant: CipherAlgorithm {
62 const ROUNDS: usize;
64}
65
66pub trait CipherMode {
68 fn name() -> &'static str;
70
71 const REQUIRES_IV: bool;
73
74 const IS_AUTHENTICATED: bool;
76
77 const IV_SIZE: usize;
79
80 const TAG_SIZE: Option<usize>;
82}
83
84pub trait BlockCipher {
86 type Algorithm: CipherAlgorithm;
88
89 type Key: AsRef<[u8]> + AsMut<[u8]> + Clone + Zeroize;
91
92 fn new(key: &Self::Key) -> Self;
94
95 fn encrypt_block(&self, block: &mut [u8]) -> Result<()>;
97
98 fn decrypt_block(&self, block: &mut [u8]) -> Result<()>;
100
101 fn key_size() -> usize {
103 Self::Algorithm::KEY_SIZE
104 }
105
106 fn block_size() -> usize {
108 Self::Algorithm::BLOCK_SIZE
109 }
110
111 fn name() -> &'static str {
113 Self::Algorithm::name()
114 }
115
116 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Key;
118}
119
120pub trait BlockCipherMode<C: BlockCipher> {
122 type Mode: CipherMode;
124
125 type Nonce: AsRef<[u8]> + AsMut<[u8]> + Clone;
127
128 fn new(cipher: C, nonce: &Self::Nonce) -> Result<Self>
130 where
131 Self: Sized;
132
133 fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>>;
135
136 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>>;
138
139 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Nonce;
141
142 fn mode_name() -> &'static str {
144 Self::Mode::name()
145 }
146}
147
148pub trait AuthenticatedCipherMode<C: BlockCipher>: BlockCipherMode<C> {
150 type Tag: AsRef<[u8]> + AsMut<[u8]> + Clone;
152
153 fn encrypt_with_aad(&self, plaintext: &[u8], aad: &[u8]) -> Result<Vec<u8>>;
155
156 fn decrypt_with_aad(&self, ciphertext: &[u8], aad: &[u8]) -> Result<Vec<u8>>;
158
159 fn tag_size() -> usize {
161 Self::Mode::TAG_SIZE.unwrap_or(0)
162 }
163}
164
165pub enum Aes128Algorithm {}
167
168impl CipherAlgorithm for Aes128Algorithm {
169 const KEY_SIZE: usize = 16;
170 const BLOCK_SIZE: usize = 16;
171
172 fn name() -> &'static str {
173 "AES-128"
174 }
175}
176
177impl AesVariant for Aes128Algorithm {
178 const ROUNDS: usize = 10;
179}
180
181#[derive(Clone, Zeroize, ZeroizeOnDrop)]
183pub struct TypedAes128 {
184 inner: aes::Aes128,
185}
186
187impl CipherAlgorithm for TypedAes128 {
189 const KEY_SIZE: usize = 16;
190 const BLOCK_SIZE: usize = 16;
191
192 fn name() -> &'static str {
193 "AES-128"
194 }
195}
196
197impl BlockCipher for TypedAes128 {
198 type Algorithm = Aes128Algorithm;
199 type Key = SecretBytes<16>;
200
201 fn new(key: &Self::Key) -> Self {
202 Self {
203 inner: aes::Aes128::new(key),
204 }
205 }
206
207 fn encrypt_block(&self, block: &mut [u8]) -> Result<()> {
208 validate::length("AES-128 block", block.len(), Self::Algorithm::BLOCK_SIZE)?;
209 self.inner.encrypt_block(block)
210 }
211
212 fn decrypt_block(&self, block: &mut [u8]) -> Result<()> {
213 validate::length("AES-128 block", block.len(), Self::Algorithm::BLOCK_SIZE)?;
214 self.inner.decrypt_block(block)
215 }
216
217 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Key {
218 let mut key = [0u8; 16];
219 rng.fill_bytes(&mut key);
220 SecretBytes::new(key)
221 }
222}
223
224pub enum CbcMode {}
226
227impl CipherMode for CbcMode {
228 const REQUIRES_IV: bool = true;
229 const IS_AUTHENTICATED: bool = false;
230 const IV_SIZE: usize = 16; const TAG_SIZE: Option<usize> = None;
232
233 fn name() -> &'static str {
234 "CBC"
235 }
236}
237
238pub struct TypedCbc<C: BlockCipher + CipherAlgorithm + Zeroize + ZeroizeOnDrop> {
240 inner: modes::cbc::Cbc<C>,
241 _phantom: core::marker::PhantomData<C>,
242}
243
244impl<C: BlockCipher + CipherAlgorithm + Zeroize + ZeroizeOnDrop> BlockCipherMode<C>
245 for TypedCbc<C>
246{
247 type Mode = CbcMode;
248 type Nonce = Nonce<16>;
249
250 fn new(cipher: C, nonce: &Self::Nonce) -> Result<Self> {
251 validate::length(
253 "CBC initialization vector",
254 nonce.as_ref().len(),
255 C::BLOCK_SIZE,
256 )?;
257
258 let inner = modes::cbc::Cbc::new(cipher, nonce)?;
259 Ok(Self {
260 inner,
261 _phantom: core::marker::PhantomData,
262 })
263 }
264
265 fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
266 if plaintext.len() % C::BLOCK_SIZE != 0 {
268 return Err(Error::Length {
269 context: "CBC plaintext",
270 expected: ((plaintext.len() / C::BLOCK_SIZE) + 1) * C::BLOCK_SIZE,
271 actual: plaintext.len(),
272 });
273 }
274
275 self.inner.encrypt(plaintext)
276 }
277
278 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
279 if ciphertext.len() % C::BLOCK_SIZE != 0 {
281 return Err(Error::Length {
282 context: "CBC ciphertext",
283 expected: ((ciphertext.len() / C::BLOCK_SIZE) + 1) * C::BLOCK_SIZE,
284 actual: ciphertext.len(),
285 });
286 }
287
288 self.inner.decrypt(ciphertext)
289 }
290
291 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Nonce {
292 let mut nonce = [0u8; 16];
293 rng.fill_bytes(&mut nonce);
294 Nonce::new(nonce)
295 }
296}