1use crate::{Cipher, Error, Result};
4use cipher::{Block, BlockCipherEncrypt, KeyIvInit};
5
6#[cfg(feature = "aes-ctr")]
7use {
8 crate::Ctr128BE,
9 cipher::{BlockSizeUser, StreamCipherCore, array::sizes::U16},
10};
11
12#[cfg(feature = "tdes")]
13use des::TdesEde3;
14
15#[cfg(any(feature = "aes-cbc", feature = "aes-ctr"))]
16use aes::{Aes128, Aes192, Aes256};
17
18#[cfg(any(feature = "aes-cbc", feature = "tdes"))]
19use cipher::block::BlockModeEncrypt;
20
21pub struct Encryptor {
26 inner: Inner,
28}
29
30enum Inner {
32 #[cfg(feature = "aes-cbc")]
33 Aes128Cbc(cbc::Encryptor<Aes128>),
34 #[cfg(feature = "aes-cbc")]
35 Aes192Cbc(cbc::Encryptor<Aes192>),
36 #[cfg(feature = "aes-cbc")]
37 Aes256Cbc(cbc::Encryptor<Aes256>),
38 #[cfg(feature = "aes-ctr")]
39 Aes128Ctr(Ctr128BE<Aes128>),
40 #[cfg(feature = "aes-ctr")]
41 Aes192Ctr(Ctr128BE<Aes192>),
42 #[cfg(feature = "aes-ctr")]
43 Aes256Ctr(Ctr128BE<Aes256>),
44 #[cfg(feature = "tdes")]
45 TDesCbc(cbc::Encryptor<TdesEde3>),
46}
47
48impl Encryptor {
49 pub fn new(cipher: Cipher, key: &[u8], iv: &[u8]) -> Result<Self> {
51 cipher.check_key_and_iv(key, iv)?;
52
53 let inner = match cipher {
54 #[cfg(feature = "aes-cbc")]
55 Cipher::Aes128Cbc => cbc::Encryptor::new_from_slices(key, iv).map(Inner::Aes128Cbc),
56 #[cfg(feature = "aes-cbc")]
57 Cipher::Aes192Cbc => cbc::Encryptor::new_from_slices(key, iv).map(Inner::Aes192Cbc),
58 #[cfg(feature = "aes-cbc")]
59 Cipher::Aes256Cbc => cbc::Encryptor::new_from_slices(key, iv).map(Inner::Aes256Cbc),
60 #[cfg(feature = "aes-ctr")]
61 Cipher::Aes128Ctr => Ctr128BE::new_from_slices(key, iv).map(Inner::Aes128Ctr),
62 #[cfg(feature = "aes-ctr")]
63 Cipher::Aes192Ctr => Ctr128BE::new_from_slices(key, iv).map(Inner::Aes192Ctr),
64 #[cfg(feature = "aes-ctr")]
65 Cipher::Aes256Ctr => Ctr128BE::new_from_slices(key, iv).map(Inner::Aes256Ctr),
66 #[cfg(feature = "tdes")]
67 Cipher::TDesCbc => cbc::Encryptor::new_from_slices(key, iv).map(Inner::TDesCbc),
68 _ => return Err(cipher.unsupported()),
69 }
70 .map_err(|_| Error::Length)?;
71
72 Ok(Self { inner })
73 }
74
75 pub fn cipher(&self) -> Cipher {
77 match &self.inner {
78 #[cfg(feature = "aes-cbc")]
79 Inner::Aes128Cbc(_) => Cipher::Aes128Cbc,
80 #[cfg(feature = "aes-cbc")]
81 Inner::Aes192Cbc(_) => Cipher::Aes192Cbc,
82 #[cfg(feature = "aes-cbc")]
83 Inner::Aes256Cbc(_) => Cipher::Aes256Cbc,
84 #[cfg(feature = "aes-ctr")]
85 Inner::Aes128Ctr(_) => Cipher::Aes128Ctr,
86 #[cfg(feature = "aes-ctr")]
87 Inner::Aes192Ctr(_) => Cipher::Aes192Ctr,
88 #[cfg(feature = "aes-ctr")]
89 Inner::Aes256Ctr(_) => Cipher::Aes256Ctr,
90 #[cfg(feature = "tdes")]
91 Inner::TDesCbc(_) => Cipher::TDesCbc,
92 }
93 }
94
95 pub fn encrypt(&mut self, buffer: &mut [u8]) -> Result<()> {
100 match &mut self.inner {
101 #[cfg(feature = "aes-cbc")]
102 Inner::Aes128Cbc(cipher) => cbc_encrypt(cipher, buffer)?,
103 #[cfg(feature = "aes-cbc")]
104 Inner::Aes192Cbc(cipher) => cbc_encrypt(cipher, buffer)?,
105 #[cfg(feature = "aes-cbc")]
106 Inner::Aes256Cbc(cipher) => cbc_encrypt(cipher, buffer)?,
107 #[cfg(feature = "aes-ctr")]
108 Inner::Aes128Ctr(cipher) => ctr_encrypt(cipher, buffer)?,
109 #[cfg(feature = "aes-ctr")]
110 Inner::Aes192Ctr(cipher) => ctr_encrypt(cipher, buffer)?,
111 #[cfg(feature = "aes-ctr")]
112 Inner::Aes256Ctr(cipher) => ctr_encrypt(cipher, buffer)?,
113 #[cfg(feature = "tdes")]
114 Inner::TDesCbc(cipher) => cbc_encrypt(cipher, buffer)?,
115 }
116
117 Ok(())
118 }
119}
120
121#[cfg(any(feature = "aes-cbc", feature = "tdes"))]
123fn cbc_encrypt<C>(encryptor: &mut cbc::Encryptor<C>, buffer: &mut [u8]) -> Result<()>
124where
125 C: BlockCipherEncrypt,
126{
127 let (blocks, remaining) = Block::<C>::slice_as_chunks_mut(buffer);
128
129 if !remaining.is_empty() {
131 return Err(Error::Length);
132 }
133
134 encryptor.encrypt_blocks(blocks);
135 Ok(())
136}
137
138#[cfg(feature = "aes-ctr")]
140pub(crate) fn ctr_encrypt<C>(encryptor: &mut Ctr128BE<C>, buffer: &mut [u8]) -> Result<()>
141where
142 C: BlockCipherEncrypt + BlockSizeUser<BlockSize = U16>,
143{
144 let (blocks, remaining) = Block::<C>::slice_as_chunks_mut(buffer);
145
146 if !remaining.is_empty() {
148 return Err(Error::Length);
149 }
150
151 encryptor.apply_keystream_blocks(blocks);
152 Ok(())
153}