1extern crate thiserror;
43extern crate zeroize;
44
45#[allow(non_snake_case)]
46mod ctaes_ffi;
47mod error;
48mod padding;
49
50use ctaes_ffi::{
51 AES128_CBC_ctx, AES128_CBC_decrypt, AES128_CBC_encrypt, AES128_CBC_init, AES128_ctx,
52 AES128_decrypt, AES128_encrypt, AES128_init, AES192_CBC_ctx, AES192_CBC_decrypt,
53 AES192_CBC_encrypt, AES192_CBC_init, AES192_ctx, AES192_decrypt, AES192_encrypt, AES192_init,
54 AES256_CBC_ctx, AES256_CBC_decrypt, AES256_CBC_encrypt, AES256_CBC_init, AES256_ctx,
55 AES256_decrypt, AES256_encrypt, AES256_init, FfiAesCbcCipher, FfiAesCipher,
56};
57pub use error::Error;
58pub use padding::{Padding, Pkcs7, ZeroPadding};
59
60pub const AES128_KEY_LENGTH: usize = 16;
61pub const AES192_KEY_LENGTH: usize = 24;
62pub const AES256_KEY_LENGTH: usize = 32;
63pub const AES_BLOCK_SIZE: usize = 16;
64
65pub trait AesBlockCipher: FfiAesCipher {
67 fn encrypt(&self, plaintext: &[u8], ciphertext: &mut [u8]) -> Result<(), Error> {
69 if plaintext.len() % AES_BLOCK_SIZE != 0 {
70 return Err(Error::NonBlockSizeAlignedBuffer);
71 }
72 if plaintext.len() > ciphertext.len() {
73 return Err(Error::InsufficientBufferSize);
74 }
75
76 let num_blocks = plaintext.len() / AES_BLOCK_SIZE;
77 self.ffi_encrypt(num_blocks, ciphertext, plaintext);
78
79 Ok(())
80 }
81
82 fn decrypt(&self, ciphertext: &[u8], plaintext: &mut [u8]) -> Result<(), Error> {
84 if ciphertext.len() % AES_BLOCK_SIZE != 0 {
85 return Err(Error::NonBlockSizeAlignedBuffer);
86 }
87 if plaintext.len() < ciphertext.len() {
88 return Err(Error::InsufficientBufferSize);
89 }
90
91 let num_blocks = ciphertext.len() / AES_BLOCK_SIZE;
92 self.ffi_decrypt(num_blocks, plaintext, ciphertext);
93
94 Ok(())
95 }
96}
97
98#[derive(Default)]
100pub struct Aes128 {
101 context: AES128_ctx,
102}
103
104impl FfiAesCipher for Aes128 {
105 fn ffi_init(&mut self, key: &[u8]) {
106 unsafe {
107 AES128_init(&mut self.context, key.as_ptr());
108 }
109 }
110
111 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
112 unsafe {
113 AES128_decrypt(&self.context, num_blocks, plaintext.as_mut_ptr(), ciphertext.as_ptr());
114 }
115 }
116
117 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
118 unsafe {
119 AES128_encrypt(&self.context, num_blocks, ciphertext.as_mut_ptr(), plaintext.as_ptr());
120 }
121 }
122}
123
124impl Aes128 {
125 pub fn new(key: &[u8]) -> Result<Self, Error> {
126 if key.len() != AES128_KEY_LENGTH {
127 return Err(Error::KeyIncorrectLength(AES128_KEY_LENGTH));
128 }
129
130 let context = AES128_ctx::default();
131 let mut cipher = Aes128 { context };
132 cipher.ffi_init(key);
133
134 Ok(cipher)
135 }
136}
137
138impl AesBlockCipher for Aes128 {}
139
140#[derive(Default)]
142pub struct Aes192 {
143 context: AES192_ctx,
144}
145
146impl FfiAesCipher for Aes192 {
147 fn ffi_init(&mut self, key: &[u8]) {
148 unsafe {
149 AES192_init(&mut self.context, key.as_ptr());
150 }
151 }
152
153 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
154 unsafe {
155 AES192_decrypt(&self.context, num_blocks, plaintext.as_mut_ptr(), ciphertext.as_ptr());
156 }
157 }
158
159 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
160 unsafe {
161 AES192_encrypt(&self.context, num_blocks, ciphertext.as_mut_ptr(), plaintext.as_ptr());
162 }
163 }
164}
165
166impl Aes192 {
167 pub fn new(key: &[u8]) -> Result<Self, Error> {
168 if key.len() != AES192_KEY_LENGTH {
169 return Err(Error::KeyIncorrectLength(AES192_KEY_LENGTH));
170 }
171
172 let context = AES192_ctx::default();
173 let mut cipher = Aes192 { context };
174 cipher.ffi_init(key);
175
176 Ok(cipher)
177 }
178}
179
180impl AesBlockCipher for Aes192 {}
181
182#[derive(Default)]
184pub struct Aes256 {
185 context: AES256_ctx,
186}
187
188impl FfiAesCipher for Aes256 {
189 fn ffi_init(&mut self, key: &[u8]) {
190 unsafe {
191 AES256_init(&mut self.context, key.as_ptr());
192 }
193 }
194
195 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
196 unsafe {
197 AES256_decrypt(&self.context, num_blocks, plaintext.as_mut_ptr(), ciphertext.as_ptr());
198 }
199 }
200
201 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
202 unsafe {
203 AES256_encrypt(&self.context, num_blocks, ciphertext.as_mut_ptr(), plaintext.as_ptr());
204 }
205 }
206}
207
208impl Aes256 {
209 pub fn new(key: &[u8]) -> Result<Self, Error> {
210 if key.len() != AES256_KEY_LENGTH {
211 return Err(Error::KeyIncorrectLength(AES256_KEY_LENGTH));
212 }
213
214 let context = AES256_ctx::default();
215 let mut cipher = Aes256 { context };
216 cipher.ffi_init(key);
217
218 Ok(cipher)
219 }
220}
221
222impl AesBlockCipher for Aes256 {}
223
224pub trait AesCbcBlockCipher: FfiAesCbcCipher {
226 fn encrypt(&self, plaintext: &[u8], ciphertext: &mut [u8]) -> Result<(), Error> {
227 if plaintext.len() % AES_BLOCK_SIZE != 0 {
228 return Err(Error::NonBlockSizeAlignedBuffer);
229 }
230 if plaintext.len() > ciphertext.len() {
231 return Err(Error::InsufficientBufferSize);
232 }
233
234 let num_blocks = plaintext.len() / AES_BLOCK_SIZE;
235 self.ffi_encrypt(num_blocks, ciphertext, plaintext);
236
237 Ok(())
238 }
239
240 fn decrypt(&self, ciphertext: &[u8], plaintext: &mut [u8]) -> Result<(), Error> {
241 if ciphertext.len() % AES_BLOCK_SIZE != 0 {
242 return Err(Error::NonBlockSizeAlignedBuffer);
243 }
244 if plaintext.len() < ciphertext.len() {
245 return Err(Error::InsufficientBufferSize);
246 }
247
248 let num_blocks = ciphertext.len() / AES_BLOCK_SIZE;
249 self.ffi_decrypt(num_blocks, plaintext, ciphertext);
250
251 Ok(())
252 }
253}
254
255pub struct Aes128Cbc<'a> {
257 key: &'a [u8],
258 iv: &'a [u8],
259}
260
261impl<'a> Aes128Cbc<'a> {
262 pub fn new(key: &'a [u8], iv: &'a [u8]) -> Result<Self, Error> {
263 if key.len() != AES128_KEY_LENGTH {
264 return Err(Error::KeyIncorrectLength(AES128_KEY_LENGTH));
265 }
266 if iv.len() != AES_BLOCK_SIZE {
267 return Err(Error::IvIncorrectLength);
268 }
269
270 Ok(Self { key, iv })
271 }
272}
273
274impl FfiAesCbcCipher for Aes128Cbc<'_> {
275 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
276 let mut context = AES128_CBC_ctx::default();
277 unsafe {
278 AES128_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
279 AES128_CBC_decrypt(
280 &mut context,
281 num_blocks,
282 plaintext.as_mut_ptr(),
283 ciphertext.as_ptr(),
284 );
285 }
286 }
287
288 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
289 let mut context = AES128_CBC_ctx::default();
290 unsafe {
291 AES128_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
292 AES128_CBC_encrypt(
293 &mut context,
294 num_blocks,
295 ciphertext.as_mut_ptr(),
296 plaintext.as_ptr(),
297 );
298 }
299 }
300}
301
302impl AesCbcBlockCipher for Aes128Cbc<'_> {}
303
304pub struct Aes192Cbc<'a> {
306 key: &'a [u8],
307 iv: &'a [u8],
308}
309
310impl<'a> Aes192Cbc<'a> {
311 pub fn new(key: &'a [u8], iv: &'a [u8]) -> Result<Self, Error> {
312 if key.len() != AES192_KEY_LENGTH {
313 return Err(Error::KeyIncorrectLength(AES192_KEY_LENGTH));
314 }
315 if iv.len() != AES_BLOCK_SIZE {
316 return Err(Error::IvIncorrectLength);
317 }
318
319 Ok(Self { key, iv })
320 }
321}
322
323impl FfiAesCbcCipher for Aes192Cbc<'_> {
324 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
325 let mut context = AES192_CBC_ctx::default();
326 unsafe {
327 AES192_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
328 AES192_CBC_decrypt(
329 &mut context,
330 num_blocks,
331 plaintext.as_mut_ptr(),
332 ciphertext.as_ptr(),
333 );
334 }
335 }
336
337 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
338 let mut context = AES192_CBC_ctx::default();
339 unsafe {
340 AES192_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
341 AES192_CBC_encrypt(
342 &mut context,
343 num_blocks,
344 ciphertext.as_mut_ptr(),
345 plaintext.as_ptr(),
346 );
347 }
348 }
349}
350
351impl AesCbcBlockCipher for Aes192Cbc<'_> {}
352
353pub struct Aes256Cbc<'a> {
355 key: &'a [u8],
356 iv: &'a [u8],
357}
358
359impl<'a> Aes256Cbc<'a> {
360 pub fn new(key: &'a [u8], iv: &'a [u8]) -> Result<Self, Error> {
361 if key.len() != AES256_KEY_LENGTH {
362 return Err(Error::KeyIncorrectLength(AES256_KEY_LENGTH));
363 }
364 if iv.len() != AES_BLOCK_SIZE {
365 return Err(Error::IvIncorrectLength);
366 }
367
368 Ok(Self { key, iv })
369 }
370}
371
372impl FfiAesCbcCipher for Aes256Cbc<'_> {
373 fn ffi_decrypt(&self, num_blocks: usize, plaintext: &mut [u8], ciphertext: &[u8]) {
374 let mut context = AES256_CBC_ctx::default();
375 unsafe {
376 AES256_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
377 AES256_CBC_decrypt(
378 &mut context,
379 num_blocks,
380 plaintext.as_mut_ptr(),
381 ciphertext.as_ptr(),
382 );
383 }
384 }
385
386 fn ffi_encrypt(&self, num_blocks: usize, ciphertext: &mut [u8], plaintext: &[u8]) {
387 let mut context = AES256_CBC_ctx::default();
388 unsafe {
389 AES256_CBC_init(&mut context, self.key.as_ptr(), self.iv.as_ptr());
390 AES256_CBC_encrypt(
391 &mut context,
392 num_blocks,
393 ciphertext.as_mut_ptr(),
394 plaintext.as_ptr(),
395 );
396 }
397 }
398}
399
400impl AesCbcBlockCipher for Aes256Cbc<'_> {}
401
402#[cfg(test)]
403mod test {
404 use crate::AES128_KEY_LENGTH;
405 use crate::AES192_KEY_LENGTH;
406 use crate::AES256_KEY_LENGTH;
407 use crate::{
408 Aes128, Aes128Cbc, Aes192, Aes192Cbc, Aes256, Aes256Cbc, AesBlockCipher, AesCbcBlockCipher,
409 Error,
410 };
411
412 #[test]
413 fn test_buffer_validation() {
414 assert!(matches!(
415 Aes128::new([0u8; 17].as_slice()),
416 Err(Error::KeyIncorrectLength(AES128_KEY_LENGTH))
417 ));
418 assert!(matches!(
419 Aes192::new([0u8; 25].as_slice()),
420 Err(Error::KeyIncorrectLength(AES192_KEY_LENGTH))
421 ));
422 assert!(matches!(
423 Aes256::new([0u8; 33].as_slice()),
424 Err(Error::KeyIncorrectLength(AES256_KEY_LENGTH))
425 ));
426 assert!(matches!(
427 Aes128Cbc::new([0u8; 17].as_slice(), [0u8; 16].as_slice()),
428 Err(Error::KeyIncorrectLength(AES128_KEY_LENGTH))
429 ));
430 assert!(matches!(
431 Aes128Cbc::new([0u8; 16].as_slice(), [0u8; 17].as_slice()),
432 Err(Error::IvIncorrectLength)
433 ));
434 assert!(matches!(
435 Aes192Cbc::new([0u8; 25].as_slice(), [0u8; 16].as_slice()),
436 Err(Error::KeyIncorrectLength(AES192_KEY_LENGTH))
437 ));
438 assert!(matches!(
439 Aes192Cbc::new([0u8; 24].as_slice(), [0u8; 17].as_slice()),
440 Err(Error::IvIncorrectLength)
441 ));
442 assert!(matches!(
443 Aes256Cbc::new([0u8; 33].as_slice(), [0u8; 16].as_slice()),
444 Err(Error::KeyIncorrectLength(AES256_KEY_LENGTH))
445 ));
446 assert!(matches!(
447 Aes256Cbc::new([0u8; 32].as_slice(), [0u8; 17].as_slice()),
448 Err(Error::IvIncorrectLength)
449 ));
450
451 let cipher = Aes128::new([0u8; 16].as_slice()).unwrap();
452 assert!(matches!(
453 cipher.encrypt([0u8; 33].as_slice(), [0u8; 33].as_mut_slice()),
454 Err(Error::NonBlockSizeAlignedBuffer)
455 ));
456 assert!(matches!(
457 cipher.encrypt([0u8; 64].as_slice(), [0u8; 32].as_mut_slice()),
458 Err(Error::InsufficientBufferSize)
459 ));
460 assert!(matches!(
461 cipher.decrypt([0u8; 64].as_slice(), [0u8; 32].as_mut_slice()),
462 Err(Error::InsufficientBufferSize)
463 ));
464 assert!(matches!(cipher.decrypt([0u8; 0].as_slice(), [0u8; 32768].as_mut_slice()), Ok(())));
465 assert!(matches!(
466 cipher.decrypt([0u8; crate::AES_BLOCK_SIZE].as_slice(), [0u8; 32768].as_mut_slice()),
467 Ok(())
468 ));
469
470 let cipher = Aes128Cbc::new([0u8; 16].as_slice(), [0u8; 16].as_slice()).unwrap();
471 assert!(matches!(
472 cipher.encrypt([0u8; 33].as_slice(), [0u8; 33].as_mut_slice()),
473 Err(Error::NonBlockSizeAlignedBuffer)
474 ));
475 assert!(matches!(
476 cipher.encrypt([0u8; 64].as_slice(), [0u8; 32].as_mut_slice()),
477 Err(Error::InsufficientBufferSize)
478 ));
479 assert!(matches!(
480 cipher.decrypt([0u8; 64].as_slice(), [0u8; 32].as_mut_slice()),
481 Err(Error::InsufficientBufferSize)
482 ));
483 assert!(matches!(cipher.decrypt([0u8; 0].as_slice(), [0u8; 32768].as_mut_slice()), Ok(())));
484 assert!(matches!(
485 cipher.decrypt([0u8; crate::AES_BLOCK_SIZE].as_slice(), [0u8; 32768].as_mut_slice()),
486 Ok(())
487 ));
488 }
489}