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