1use aes::{Aes128, Aes192, Aes256};
2use blowfish::Blowfish;
3use camellia::{Camellia128, Camellia192, Camellia256};
4use cast5::Cast5;
5use cfb_mode::{
6 cipher::{AsyncStreamCipher, KeyIvInit},
7 BufDecryptor, BufEncryptor, Decryptor, Encryptor,
8};
9use cipher::{BlockCipher, BlockDecrypt, BlockEncryptMut};
10use des::TdesEde3;
11use idea::Idea;
12use log::debug;
13use num_enum::{FromPrimitive, IntoPrimitive};
14use rand::{CryptoRng, Rng};
15use twofish::Twofish;
16use zeroize::Zeroizing;
17
18use crate::{
19 composed::RawSessionKey,
20 errors::{bail, ensure, unimplemented_err, Error, Result},
21};
22
23mod decryptor;
24mod encryptor;
25
26pub use self::{decryptor::StreamDecryptor, encryptor::StreamEncryptor};
27
28fn decrypt<MODE>(key: &[u8], iv: &[u8], prefix: &mut [u8], data: &mut [u8]) -> Result<()>
29where
30 MODE: BlockDecrypt + BlockEncryptMut + BlockCipher,
31 BufDecryptor<MODE>: KeyIvInit,
32{
33 let mut mode = BufDecryptor::<MODE>::new_from_slices(key, iv)?;
34
35 mode.decrypt(prefix);
42
43 mode.decrypt(data);
44 Ok(())
45}
46
47fn decrypt_resync<MODE>(key: &[u8], iv: &[u8], prefix: &mut [u8], data: &mut [u8]) -> Result<()>
49where
50 MODE: BlockDecrypt + BlockEncryptMut + BlockCipher,
51 BufDecryptor<MODE>: KeyIvInit,
52{
53 let mut mode = BufDecryptor::<MODE>::new_from_slices(key, iv)?;
54
55 let encrypted_prefix = prefix[2..].to_vec();
62 mode.decrypt(prefix);
63 mode = BufDecryptor::<MODE>::new_from_slices(key, &encrypted_prefix)?;
64
65 mode.decrypt(data);
66 Ok(())
67}
68
69fn encrypt<MODE>(key: &[u8], iv: &[u8], prefix: &mut [u8], data: &mut [u8]) -> Result<()>
70where
71 MODE: BlockDecrypt + BlockEncryptMut + BlockCipher,
72 BufEncryptor<MODE>: KeyIvInit,
73{
74 let mut mode = BufEncryptor::<MODE>::new_from_slices(key, iv)?;
75 mode.encrypt(prefix);
76
77 mode.encrypt(data);
78
79 Ok(())
80}
81
82fn encrypt_resync<MODE>(key: &[u8], iv: &[u8], prefix: &mut [u8], data: &mut [u8]) -> Result<()>
86where
87 MODE: BlockDecrypt + BlockEncryptMut + BlockCipher,
88 BufEncryptor<MODE>: KeyIvInit,
89{
90 let mut mode = BufEncryptor::<MODE>::new_from_slices(key, iv)?;
91 mode.encrypt(prefix);
92
93 mode = BufEncryptor::<MODE>::new_from_slices(key, &prefix[2..])?;
95 mode.encrypt(data);
96
97 Ok(())
98}
99
100#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
103#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
104#[repr(u8)]
105#[non_exhaustive]
106pub enum SymmetricKeyAlgorithm {
107 #[cfg_attr(test, proptest(skip))]
109 Plaintext = 0,
110 IDEA = 1,
112 TripleDES = 2,
114 CAST5 = 3,
116 Blowfish = 4,
118 AES128 = 7,
121 AES192 = 8,
123 AES256 = 9,
125 Twofish = 10,
127 Camellia128 = 11,
129 Camellia192 = 12,
131 Camellia256 = 13,
133 Private10 = 110,
134
135 #[num_enum(catch_all)]
136 Other(#[cfg_attr(test, proptest(strategy = "111u8.."))] u8),
137}
138
139impl Default for SymmetricKeyAlgorithm {
140 fn default() -> Self {
141 Self::AES128
142 }
143}
144
145impl zeroize::DefaultIsZeroes for SymmetricKeyAlgorithm {}
146
147impl SymmetricKeyAlgorithm {
148 pub fn block_size(self) -> usize {
151 match self {
152 SymmetricKeyAlgorithm::Plaintext => 0,
153 SymmetricKeyAlgorithm::IDEA => 8,
154 SymmetricKeyAlgorithm::TripleDES => 8,
155 SymmetricKeyAlgorithm::CAST5 => 8,
156 SymmetricKeyAlgorithm::Blowfish => 8,
157 SymmetricKeyAlgorithm::AES128 => 16,
158 SymmetricKeyAlgorithm::AES192 => 16,
159 SymmetricKeyAlgorithm::AES256 => 16,
160 SymmetricKeyAlgorithm::Twofish => 16,
161 SymmetricKeyAlgorithm::Camellia128 => 16,
162 SymmetricKeyAlgorithm::Camellia192 => 16,
163 SymmetricKeyAlgorithm::Camellia256 => 16,
164 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => 0,
165 }
166 }
167
168 #[cfg(test)]
169 pub(crate) fn cfb_prefix_size(&self) -> usize {
170 self.block_size() + 2
171 }
172
173 pub const fn key_size(self) -> usize {
176 match self {
177 SymmetricKeyAlgorithm::Plaintext => 0,
178 SymmetricKeyAlgorithm::IDEA => 16,
179 SymmetricKeyAlgorithm::TripleDES => 24,
180 SymmetricKeyAlgorithm::CAST5 => 16,
181 SymmetricKeyAlgorithm::Blowfish => 16, SymmetricKeyAlgorithm::AES128 => 16,
184 SymmetricKeyAlgorithm::AES192 => 24,
185 SymmetricKeyAlgorithm::AES256 => 32,
186 SymmetricKeyAlgorithm::Twofish => 32,
187 SymmetricKeyAlgorithm::Camellia128 => 16,
188 SymmetricKeyAlgorithm::Camellia192 => 24,
189 SymmetricKeyAlgorithm::Camellia256 => 32,
190
191 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => 0,
192 }
193 }
194
195 pub fn decrypt(self, key: &[u8], prefix: &mut [u8], ciphertext: &mut [u8]) -> Result<()> {
199 debug!("unprotected decrypt");
200 let iv_vec = vec![0u8; self.block_size()];
201 self.decrypt_with_iv_resync(key, &iv_vec, prefix, ciphertext)?;
202 Ok(())
203 }
204
205 pub fn decrypt_protected(
211 self,
212 key: &[u8],
213 prefix: &mut [u8],
214 ciphertext: &mut Vec<u8>,
215 ) -> Result<()> {
216 debug!("protected decrypt");
217
218 let iv_vec = vec![0u8; self.block_size()];
219 self.decrypt_with_iv(key, &iv_vec, prefix, ciphertext)?;
220
221 const MDC_LEN: usize = 22;
223 let mdc = ciphertext.split_off(ciphertext.len() - MDC_LEN);
224
225 let sha1 = calculate_sha1_unchecked([prefix, &ciphertext[..], &mdc[0..2]]);
227 if mdc[0] != 0xD3 || mdc[1] != 0x14 || mdc[2..] != sha1[..]
230 {
231 return Err(Error::MdcError);
232 }
233
234 Ok(())
235 }
236
237 pub fn decrypt_with_iv(
251 self,
252 key: &[u8],
253 iv_vec: &[u8],
254 encrypted_prefix: &mut [u8],
255 encrypted_data: &mut [u8],
256 ) -> Result<()> {
257 let bs = self.block_size();
258 let ciphertext_len = encrypted_prefix.len() + encrypted_data.len();
259 ensure!(bs + 2 < ciphertext_len, "invalid ciphertext");
260
261 match self {
262 SymmetricKeyAlgorithm::Plaintext => {
263 bail!("'Plaintext' is not a legal cipher for encrypted data")
264 }
265 SymmetricKeyAlgorithm::IDEA => {
266 decrypt::<Idea>(key, iv_vec, encrypted_prefix, encrypted_data)?;
267 }
268 SymmetricKeyAlgorithm::TripleDES => {
269 decrypt::<TdesEde3>(key, iv_vec, encrypted_prefix, encrypted_data)?;
270 }
271 SymmetricKeyAlgorithm::CAST5 => {
272 decrypt::<Cast5>(key, iv_vec, encrypted_prefix, encrypted_data)?;
273 }
274 SymmetricKeyAlgorithm::Blowfish => {
275 decrypt::<Blowfish>(key, iv_vec, encrypted_prefix, encrypted_data)?;
276 }
277 SymmetricKeyAlgorithm::AES128 => {
278 decrypt::<Aes128>(key, iv_vec, encrypted_prefix, encrypted_data)?;
279 }
280 SymmetricKeyAlgorithm::AES192 => {
281 decrypt::<Aes192>(key, iv_vec, encrypted_prefix, encrypted_data)?;
282 }
283 SymmetricKeyAlgorithm::AES256 => {
284 decrypt::<Aes256>(key, iv_vec, encrypted_prefix, encrypted_data)?;
285 }
286 SymmetricKeyAlgorithm::Twofish => {
287 decrypt::<Twofish>(key, iv_vec, encrypted_prefix, encrypted_data)?;
288 }
289 SymmetricKeyAlgorithm::Camellia128 => {
290 decrypt::<Camellia128>(key, iv_vec, encrypted_prefix, encrypted_data)?;
291 }
292 SymmetricKeyAlgorithm::Camellia192 => {
293 decrypt::<Camellia192>(key, iv_vec, encrypted_prefix, encrypted_data)?;
294 }
295 SymmetricKeyAlgorithm::Camellia256 => {
296 decrypt::<Camellia256>(key, iv_vec, encrypted_prefix, encrypted_data)?
297 }
298 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
299 unimplemented_err!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
300 }
301 }
302
303 Ok(())
304 }
305
306 pub fn decrypt_with_iv_resync(
308 self,
309 key: &[u8],
310 iv_vec: &[u8],
311 encrypted_prefix: &mut [u8],
312 encrypted_data: &mut [u8],
313 ) -> Result<()> {
314 let bs = self.block_size();
315 let ciphertext_len = encrypted_prefix.len() + encrypted_data.len();
316 ensure!(bs + 2 < ciphertext_len, "invalid ciphertext");
317
318 match self {
319 SymmetricKeyAlgorithm::Plaintext => {
320 bail!("'Plaintext' is not a legal cipher for encrypted data")
321 }
322 SymmetricKeyAlgorithm::IDEA => {
323 decrypt_resync::<Idea>(key, iv_vec, encrypted_prefix, encrypted_data)?;
324 }
325 SymmetricKeyAlgorithm::TripleDES => {
326 decrypt_resync::<TdesEde3>(key, iv_vec, encrypted_prefix, encrypted_data)?;
327 }
328 SymmetricKeyAlgorithm::CAST5 => {
329 decrypt_resync::<Cast5>(key, iv_vec, encrypted_prefix, encrypted_data)?;
330 }
331 SymmetricKeyAlgorithm::Blowfish => {
332 decrypt_resync::<Blowfish>(key, iv_vec, encrypted_prefix, encrypted_data)?;
333 }
334 SymmetricKeyAlgorithm::AES128 => {
335 decrypt_resync::<Aes128>(key, iv_vec, encrypted_prefix, encrypted_data)?;
336 }
337 SymmetricKeyAlgorithm::AES192 => {
338 decrypt_resync::<Aes192>(key, iv_vec, encrypted_prefix, encrypted_data)?;
339 }
340 SymmetricKeyAlgorithm::AES256 => {
341 decrypt_resync::<Aes256>(key, iv_vec, encrypted_prefix, encrypted_data)?;
342 }
343 SymmetricKeyAlgorithm::Twofish => {
344 decrypt_resync::<Twofish>(key, iv_vec, encrypted_prefix, encrypted_data)?;
345 }
346 SymmetricKeyAlgorithm::Camellia128 => {
347 decrypt_resync::<Camellia128>(key, iv_vec, encrypted_prefix, encrypted_data)?;
348 }
349 SymmetricKeyAlgorithm::Camellia192 => {
350 decrypt_resync::<Camellia192>(key, iv_vec, encrypted_prefix, encrypted_data)?;
351 }
352 SymmetricKeyAlgorithm::Camellia256 => {
353 decrypt_resync::<Camellia256>(key, iv_vec, encrypted_prefix, encrypted_data)?
354 }
355 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
356 unimplemented_err!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
357 }
358 }
359
360 Ok(())
361 }
362
363 pub fn decrypt_with_iv_regular(
366 self,
367 key: &[u8],
368 iv_vec: &[u8],
369 ciphertext: &mut [u8],
370 ) -> Result<()> {
371 match self {
372 SymmetricKeyAlgorithm::Plaintext => {
373 bail!("'Plaintext' is not a legal cipher for encrypted data")
374 }
375 SymmetricKeyAlgorithm::IDEA => {
376 Decryptor::<Idea>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
377 }
378 SymmetricKeyAlgorithm::TripleDES => {
379 Decryptor::<TdesEde3>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
380 }
381 SymmetricKeyAlgorithm::CAST5 => {
382 Decryptor::<Cast5>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
383 }
384 SymmetricKeyAlgorithm::Blowfish => {
385 Decryptor::<Blowfish>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
386 }
387 SymmetricKeyAlgorithm::AES128 => {
388 Decryptor::<Aes128>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
389 }
390 SymmetricKeyAlgorithm::AES192 => {
391 Decryptor::<Aes192>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
392 }
393 SymmetricKeyAlgorithm::AES256 => {
394 Decryptor::<Aes256>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
395 }
396 SymmetricKeyAlgorithm::Twofish => {
397 Decryptor::<Twofish>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
398 }
399 SymmetricKeyAlgorithm::Camellia128 => {
400 Decryptor::<Camellia128>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
401 }
402 SymmetricKeyAlgorithm::Camellia192 => {
403 Decryptor::<Camellia192>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
404 }
405 SymmetricKeyAlgorithm::Camellia256 => {
406 Decryptor::<Camellia256>::new_from_slices(key, iv_vec)?.decrypt(ciphertext);
407 }
408 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
409 unimplemented_err!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
410 }
411 }
412
413 Ok(())
414 }
415
416 pub fn encrypt<R: CryptoRng + Rng>(
419 self,
420 mut rng: R,
421 key: &[u8],
422 plaintext: &[u8],
423 ) -> Result<Vec<u8>> {
424 debug!("encrypt unprotected");
425
426 let iv_vec = vec![0u8; self.block_size()];
427
428 let bs = self.block_size();
429
430 let prefix_len = bs + 2;
431 let plaintext_len = plaintext.len();
432
433 let mut ciphertext = vec![0u8; prefix_len + plaintext_len];
434 rng.fill_bytes(&mut ciphertext[..bs]);
436
437 ciphertext[bs] = ciphertext[bs - 2];
439 ciphertext[bs + 1] = ciphertext[bs - 1];
440
441 ciphertext[prefix_len..].copy_from_slice(plaintext);
443
444 self.encrypt_with_iv_resync(key, &iv_vec, &mut ciphertext)?;
445
446 Ok(ciphertext)
447 }
448
449 pub fn encrypt_protected<R: CryptoRng + Rng>(
450 self,
451 mut rng: R,
452 key: &[u8],
453 plaintext: &[u8],
454 ) -> Result<Vec<u8>> {
455 use sha1::{Digest, Sha1};
457
458 debug!("protected encrypt");
459
460 let mdc_len = 22;
462
463 let bs = self.block_size();
464
465 let prefix_len = bs + 2;
466 let plaintext_len = plaintext.len();
467
468 let mut ciphertext = vec![0u8; prefix_len + plaintext_len + mdc_len];
469
470 rng.fill_bytes(&mut ciphertext[..bs]);
472
473 ciphertext[bs] = ciphertext[bs - 2];
475 ciphertext[bs + 1] = ciphertext[bs - 1];
476
477 ciphertext[prefix_len..(prefix_len + plaintext_len)].copy_from_slice(plaintext);
479 ciphertext[prefix_len + plaintext_len] = 0xD3;
481 ciphertext[prefix_len + plaintext_len + 1] = 0x14;
482 let checksum = &Sha1::digest(&ciphertext[..(prefix_len + plaintext_len + 2)])[..20];
484 ciphertext[(prefix_len + plaintext_len + 2)..].copy_from_slice(checksum);
485
486 let iv_vec = vec![0u8; self.block_size()];
488
489 self.encrypt_with_iv(key, &iv_vec, &mut ciphertext)?;
490
491 Ok(ciphertext)
492 }
493
494 pub fn encrypted_protected_len(&self, plaintext_len: usize) -> usize {
495 self.encrypted_protected_overhead() + plaintext_len
496 }
497
498 pub fn encrypted_protected_overhead(&self) -> usize {
499 self.block_size() +
503 2 +
505 22
507 }
508
509 pub fn stream_encryptor<R, I>(
510 self,
511 rng: R,
512 key: &[u8],
513 plaintext: I,
514 ) -> Result<StreamEncryptor<I>>
515 where
516 R: Rng + CryptoRng,
517 I: std::io::Read,
518 {
519 StreamEncryptor::new(rng, self, key, plaintext)
520 }
521
522 pub fn stream_decryptor_protected<R>(
524 self,
525 key: &[u8],
526 ciphertext: R,
527 ) -> Result<StreamDecryptor<R>>
528 where
529 R: std::io::BufRead,
530 {
531 StreamDecryptor::new(self, true, key, ciphertext)
532 }
533
534 pub fn stream_decryptor_unprotected<R>(
536 self,
537 key: &[u8],
538 ciphertext: R,
539 ) -> Result<StreamDecryptor<R>>
540 where
541 R: std::io::BufRead,
542 {
543 StreamDecryptor::new(self, false, key, ciphertext)
544 }
545
546 pub fn encrypt_with_iv(self, key: &[u8], iv_vec: &[u8], ciphertext: &mut [u8]) -> Result<()> {
553 let bs = self.block_size();
554
555 let (prefix, data) = ciphertext.split_at_mut(bs + 2);
556
557 {
558 match self {
559 SymmetricKeyAlgorithm::Plaintext => {
560 bail!("'Plaintext' is not a legal cipher for encrypted data")
561 }
562 SymmetricKeyAlgorithm::IDEA => {
563 encrypt::<Idea>(key, iv_vec, prefix, data)?;
564 }
565 SymmetricKeyAlgorithm::TripleDES => {
566 encrypt::<TdesEde3>(key, iv_vec, prefix, data)?;
567 }
568 SymmetricKeyAlgorithm::CAST5 => {
569 encrypt::<Cast5>(key, iv_vec, prefix, data)?;
570 }
571 SymmetricKeyAlgorithm::Blowfish => {
572 encrypt::<Blowfish>(key, iv_vec, prefix, data)?;
573 }
574 SymmetricKeyAlgorithm::AES128 => {
575 encrypt::<Aes128>(key, iv_vec, prefix, data)?;
576 }
577 SymmetricKeyAlgorithm::AES192 => {
578 encrypt::<Aes192>(key, iv_vec, prefix, data)?;
579 }
580 SymmetricKeyAlgorithm::AES256 => encrypt::<Aes256>(key, iv_vec, prefix, data)?,
581 SymmetricKeyAlgorithm::Twofish => {
582 encrypt::<Twofish>(key, iv_vec, prefix, data)?;
583 }
584 SymmetricKeyAlgorithm::Camellia128 => {
585 encrypt::<Camellia128>(key, iv_vec, prefix, data)?;
586 }
587 SymmetricKeyAlgorithm::Camellia192 => {
588 encrypt::<Camellia192>(key, iv_vec, prefix, data)?;
589 }
590 SymmetricKeyAlgorithm::Camellia256 => {
591 encrypt::<Camellia256>(key, iv_vec, prefix, data)?;
592 }
593 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
594 bail!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
595 }
596 }
597 }
598
599 Ok(())
600 }
601
602 pub fn encrypt_with_iv_resync(
604 self,
605 key: &[u8],
606 iv_vec: &[u8],
607 ciphertext: &mut [u8],
608 ) -> Result<()> {
609 let bs = self.block_size();
610
611 let (prefix, data) = ciphertext.split_at_mut(bs + 2);
612
613 {
614 match self {
615 SymmetricKeyAlgorithm::Plaintext => {
616 bail!("'Plaintext' is not a legal cipher for encrypted data")
617 }
618 SymmetricKeyAlgorithm::IDEA => {
619 encrypt_resync::<Idea>(key, iv_vec, prefix, data)?;
620 }
621 SymmetricKeyAlgorithm::TripleDES => {
622 encrypt_resync::<TdesEde3>(key, iv_vec, prefix, data)?;
623 }
624 SymmetricKeyAlgorithm::CAST5 => {
625 encrypt_resync::<Cast5>(key, iv_vec, prefix, data)?;
626 }
627 SymmetricKeyAlgorithm::Blowfish => {
628 encrypt_resync::<Blowfish>(key, iv_vec, prefix, data)?;
629 }
630 SymmetricKeyAlgorithm::AES128 => {
631 encrypt_resync::<Aes128>(key, iv_vec, prefix, data)?;
632 }
633 SymmetricKeyAlgorithm::AES192 => {
634 encrypt_resync::<Aes192>(key, iv_vec, prefix, data)?;
635 }
636 SymmetricKeyAlgorithm::AES256 => {
637 encrypt_resync::<Aes256>(key, iv_vec, prefix, data)?
638 }
639 SymmetricKeyAlgorithm::Twofish => {
640 encrypt_resync::<Twofish>(key, iv_vec, prefix, data)?;
641 }
642 SymmetricKeyAlgorithm::Camellia128 => {
643 encrypt_resync::<Camellia128>(key, iv_vec, prefix, data)?;
644 }
645 SymmetricKeyAlgorithm::Camellia192 => {
646 encrypt_resync::<Camellia192>(key, iv_vec, prefix, data)?;
647 }
648 SymmetricKeyAlgorithm::Camellia256 => {
649 encrypt_resync::<Camellia256>(key, iv_vec, prefix, data)?;
650 }
651 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
652 bail!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
653 }
654 }
655 }
656
657 Ok(())
658 }
659
660 pub fn encrypt_with_iv_regular(
662 self,
663 key: &[u8],
664 iv_vec: &[u8],
665 plaintext: &mut [u8],
666 ) -> Result<()> {
667 match self {
668 SymmetricKeyAlgorithm::Plaintext => {
669 bail!("'Plaintext' is not a legal cipher for encrypted data")
670 }
671 SymmetricKeyAlgorithm::IDEA => {
672 Encryptor::<Idea>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
673 }
674 SymmetricKeyAlgorithm::TripleDES => {
675 Encryptor::<TdesEde3>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
676 }
677 SymmetricKeyAlgorithm::CAST5 => {
678 Encryptor::<Cast5>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
679 }
680 SymmetricKeyAlgorithm::Blowfish => {
681 Encryptor::<Blowfish>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
682 }
683 SymmetricKeyAlgorithm::AES128 => {
684 Encryptor::<Aes128>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
685 }
686 SymmetricKeyAlgorithm::AES192 => {
687 Encryptor::<Aes192>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
688 }
689 SymmetricKeyAlgorithm::AES256 => {
690 Encryptor::<Aes256>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
691 }
692 SymmetricKeyAlgorithm::Twofish => {
693 Encryptor::<Twofish>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
694 }
695 SymmetricKeyAlgorithm::Camellia128 => {
696 Encryptor::<Camellia128>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
697 }
698 SymmetricKeyAlgorithm::Camellia192 => {
699 Encryptor::<Camellia192>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
700 }
701 SymmetricKeyAlgorithm::Camellia256 => {
702 Encryptor::<Camellia256>::new_from_slices(key, iv_vec)?.encrypt(plaintext);
703 }
704 SymmetricKeyAlgorithm::Private10 | SymmetricKeyAlgorithm::Other(_) => {
705 unimplemented_err!("SymmetricKeyAlgorithm {} is unsupported", u8::from(self))
706 }
707 }
708 Ok(())
709 }
710
711 pub fn new_session_key<R: Rng + CryptoRng>(self, mut rng: R) -> RawSessionKey {
713 let mut session_key = Zeroizing::new(vec![0u8; self.key_size()]);
714 rng.fill_bytes(&mut session_key);
715 session_key.into()
716 }
717}
718
719#[inline]
720fn calculate_sha1_unchecked<I, T>(data: I) -> [u8; 20]
721where
722 T: AsRef<[u8]>,
723 I: IntoIterator<Item = T>,
724{
725 use sha1::{Digest, Sha1};
726
727 let mut digest = Sha1::new();
728 for chunk in data {
729 digest.update(chunk.as_ref());
730 }
731 digest.finalize().into()
732}
733
734#[cfg(test)]
735mod tests {
736 use std::{io::Read, time::Instant};
737
738 use log::info;
739 use rand::{Rng, SeedableRng};
740 use rand_chacha::ChaCha8Rng;
741
742 use super::*;
743
744 macro_rules! roundtrip_unprotected {
745 ($name:ident, $alg:path) => {
746 #[test]
747 fn $name() {
748 pretty_env_logger::try_init().ok();
749
750 let mut data_rng = ChaCha8Rng::seed_from_u64(0);
751
752 const MAX_SIZE: usize = 2048;
753
754 for i in 1..MAX_SIZE {
756 info!("Size {}", i);
757 let mut data = vec![0u8; i];
758 data_rng.fill(&mut data[..]);
759 let mut key = vec![0u8; $alg.key_size()];
760 data_rng.fill(&mut key[..]);
761
762 info!("unprotected encrypt");
763 let mut rng = ChaCha8Rng::seed_from_u64(8);
764 let ciphertext = $alg.encrypt(&mut rng, &key, &data).unwrap();
765 assert_ne!(data, ciphertext);
766
767 {
768 info!("unprotected decrypt");
769 let mut ciphertext = ciphertext.clone();
770 let mut plaintext = ciphertext.split_off($alg.cfb_prefix_size());
771 let mut prefix = ciphertext;
772 $alg.decrypt(&key, &mut prefix, &mut plaintext).unwrap();
773 assert_eq!(
774 hex::encode(&data),
775 hex::encode(&plaintext),
776 "unprotected decrypt"
777 );
778 }
779
780 {
781 info!("unprotected decrypt streaming");
782 dbg!(ciphertext.len(), $alg.cfb_prefix_size());
783 let mut input = std::io::Cursor::new(&ciphertext);
784 let mut decryptor =
785 $alg.stream_decryptor_unprotected(&key, &mut input).unwrap();
786 let mut plaintext = Vec::new();
787 decryptor.read_to_end(&mut plaintext).unwrap();
788 assert_eq!(
789 hex::encode(&data),
790 hex::encode(&plaintext),
791 "stream decrypt failed"
792 );
793 }
794 }
795 }
796 };
797 }
798
799 macro_rules! roundtrip_protected {
800 ($name:ident, $alg:path) => {
801 #[test]
802 fn $name() {
803 pretty_env_logger::try_init().ok();
804
805 let mut data_rng = ChaCha8Rng::seed_from_u64(0);
806
807 const MAX_SIZE: usize = 2048;
808
809 for i in 1..MAX_SIZE {
811 info!("Size {}", i);
812 let mut data = vec![0u8; i];
813 data_rng.fill(&mut data[..]);
814 let mut key = vec![0u8; $alg.key_size()];
815 data_rng.fill(&mut key[..]);
816
817 info!("encrypt");
818 let mut rng = ChaCha8Rng::seed_from_u64(8);
819 let ciphertext = $alg.encrypt_protected(&mut rng, &key, &data).unwrap();
820 assert_ne!(data, ciphertext, "failed to encrypt");
821
822 {
823 info!("encrypt streaming");
824 let mut input = std::io::Cursor::new(&data);
825 let len = $alg.encrypted_protected_len(data.len());
826 assert_eq!(len, ciphertext.len(), "failed to encrypt");
827 let mut output = Vec::new();
828 let mut rng = ChaCha8Rng::seed_from_u64(8);
829 let mut encryptor =
830 $alg.stream_encryptor(&mut rng, &key, &mut input).unwrap();
831 encryptor.read_to_end(&mut output).unwrap();
832
833 assert_eq!(output.len(), len, "output length mismatch");
834 assert_eq!(ciphertext, output, "output mismatch");
835 }
836
837 {
838 info!("decrypt");
839 let mut ciphertext = ciphertext.clone();
840 let mut plaintext = ciphertext.split_off($alg.cfb_prefix_size());
841 let mut prefix = ciphertext;
842 $alg.decrypt_protected(&key, &mut prefix, &mut plaintext)
843 .unwrap();
844 assert_eq!(data, plaintext, "decrypt failed");
845 }
846 {
847 info!("decrypt streaming");
848 dbg!(ciphertext.len(), $alg.cfb_prefix_size());
849 let mut input = std::io::Cursor::new(&ciphertext);
850 let mut decryptor =
851 $alg.stream_decryptor_protected(&key, &mut input).unwrap();
852 let mut plaintext = Vec::new();
853 decryptor.read_to_end(&mut plaintext).unwrap();
854 assert_eq!(
855 hex::encode(&data),
856 hex::encode(&plaintext),
857 "stream decrypt failed"
858 );
859 }
860 }
861 }
862 };
863 }
864
865 roundtrip_protected!(roundtrip_protected_aes128, SymmetricKeyAlgorithm::AES128);
866 roundtrip_protected!(roundtrip_protected_aes192, SymmetricKeyAlgorithm::AES192);
867 roundtrip_protected!(roundtrip_protected_aes256, SymmetricKeyAlgorithm::AES256);
868 roundtrip_protected!(
869 roundtrip_protected_tripledes,
870 SymmetricKeyAlgorithm::TripleDES
871 );
872 roundtrip_protected!(
873 roundtrip_protected_blowfish,
874 SymmetricKeyAlgorithm::Blowfish
875 );
876 roundtrip_protected!(roundtrip_protected_twofish, SymmetricKeyAlgorithm::Twofish);
877 roundtrip_protected!(roundtrip_protected_cast5, SymmetricKeyAlgorithm::CAST5);
878 roundtrip_protected!(roundtrip_protected_idea, SymmetricKeyAlgorithm::IDEA);
879 roundtrip_protected!(
880 roundtrip_protected_camellia128,
881 SymmetricKeyAlgorithm::Camellia128
882 );
883 roundtrip_protected!(
884 roundtrip_protected_camellia192,
885 SymmetricKeyAlgorithm::Camellia192
886 );
887 roundtrip_protected!(
888 roundtrip_protected_camellia256,
889 SymmetricKeyAlgorithm::Camellia256
890 );
891
892 roundtrip_unprotected!(roundtrip_unprotected_aes128, SymmetricKeyAlgorithm::AES128);
893 roundtrip_unprotected!(roundtrip_unprotected_aes192, SymmetricKeyAlgorithm::AES192);
894 roundtrip_unprotected!(roundtrip_unprotected_aes256, SymmetricKeyAlgorithm::AES256);
895 roundtrip_unprotected!(
896 roundtrip_unprotected_tripledes,
897 SymmetricKeyAlgorithm::TripleDES
898 );
899 roundtrip_unprotected!(
900 roundtrip_unprotected_blowfish,
901 SymmetricKeyAlgorithm::Blowfish
902 );
903 roundtrip_unprotected!(
904 roundtrip_unprotected_twofish,
905 SymmetricKeyAlgorithm::Twofish
906 );
907 roundtrip_unprotected!(roundtrip_unprotected_cast5, SymmetricKeyAlgorithm::CAST5);
908 roundtrip_unprotected!(roundtrip_unprotected_idea, SymmetricKeyAlgorithm::IDEA);
909 roundtrip_unprotected!(
910 roundtrip_unprotected_camellia128,
911 SymmetricKeyAlgorithm::Camellia128
912 );
913 roundtrip_unprotected!(
914 roundtrip_unprotected_camellia192,
915 SymmetricKeyAlgorithm::Camellia192
916 );
917 roundtrip_unprotected!(
918 roundtrip_unprotected_camellia256,
919 SymmetricKeyAlgorithm::Camellia256
920 );
921
922 #[test]
923 pub fn decrypt_without_enough_ciphertext() {
924 let key: [u8; 0] = [];
925 let mut prefix: [u8; 0] = [];
926 let mut cipher_text: [u8; 0] = [];
927 assert!(SymmetricKeyAlgorithm::AES128
928 .decrypt(&key, &mut prefix, &mut cipher_text)
929 .is_err());
930 }
931
932 use rand::RngCore;
933
934 #[ignore]
935 #[test]
936 fn bench_aes_256_protected() {
937 const SIZE: usize = 1024 * 1024 * 64;
938 let mut rng = ChaCha8Rng::seed_from_u64(0);
939 let mut data = vec![0u8; SIZE];
940 rng.fill_bytes(&mut data);
941
942 let mut key = vec![0u8; SymmetricKeyAlgorithm::AES256.key_size()];
943 rng.fill_bytes(&mut key);
944
945 let now = Instant::now();
946 let mut encryptor = SymmetricKeyAlgorithm::AES256
947 .stream_encryptor(&mut rng, &key, &data[..])
948 .unwrap();
949
950 let mut output = Vec::with_capacity(SIZE);
951 encryptor.read_to_end(&mut output).unwrap();
952
953 let elapsed = now.elapsed();
954 let elapsed_milli = elapsed.as_millis();
955 let mb_per_s = ((SIZE as f64) / 1000f64 / 1000f64 / elapsed_milli as f64) * 1000f64;
956 println!("Encryption: {elapsed_milli} ms, MByte/s: {mb_per_s:.2?}");
957
958 let now = Instant::now();
959
960 let mut decryptor = SymmetricKeyAlgorithm::AES256
961 .stream_decryptor_protected(&key, &output[..])
962 .unwrap();
963 let mut res = Vec::with_capacity(SIZE);
964 decryptor.read_to_end(&mut res).unwrap();
965 let elapsed = now.elapsed();
966
967 assert_eq!(res, data);
968
969 let elapsed_milli = elapsed.as_millis();
970 let mb_per_s = (SIZE as f64 / 1000f64 / 1000f64 / elapsed_milli as f64) * 1000f64;
971 println!("Decryption: {elapsed_milli} ms, MByte/s: {mb_per_s:.2?}");
972 }
973
974 #[ignore]
975 #[test]
976 fn bench_aes_256_unprotected() {
977 const SIZE: usize = 1024 * 1024 * 256;
978 let mut rng = ChaCha8Rng::seed_from_u64(0);
979 let mut data = vec![0u8; SIZE];
980 rng.fill_bytes(&mut data);
981
982 let mut key = vec![0u8; SymmetricKeyAlgorithm::AES256.key_size()];
983 rng.fill_bytes(&mut key);
984
985 let now = Instant::now();
986 let output = SymmetricKeyAlgorithm::AES256
987 .encrypt(&mut rng, &key, &data[..])
988 .unwrap();
989
990 let elapsed = now.elapsed();
991 let elapsed_milli = elapsed.as_millis();
992 let mb_per_s = ((SIZE as f64) / 1000f64 / 1000f64 / elapsed_milli as f64) * 1000f64;
993 println!("Encryption: {elapsed_milli} ms, MByte/s: {mb_per_s:.2?}");
994
995 let now = Instant::now();
996
997 let mut decryptor = SymmetricKeyAlgorithm::AES256
998 .stream_decryptor_unprotected(&key, &output[..])
999 .unwrap();
1000 let mut res = Vec::with_capacity(SIZE);
1001 decryptor.read_to_end(&mut res).unwrap();
1002 let elapsed = now.elapsed();
1003
1004 assert_eq!(res, data);
1005
1006 let elapsed_milli = elapsed.as_millis();
1007 let mb_per_s = (SIZE as f64 / 1000f64 / 1000f64 / elapsed_milli as f64) * 1000f64;
1008 println!("Decryption: {elapsed_milli} ms, MByte/s: {mb_per_s:.2?}");
1009 }
1010}