1use super::{EncryptionScheme, Kdf, Parameters, Pbkdf2Params, Pbkdf2Prf, ScryptParams};
4use crate::{Error, Result};
5use cbc::cipher::{
6 block_padding::Pkcs7, BlockCipher, BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit,
7};
8use pbkdf2::{
9 hmac::digest::{
10 block_buffer::Eager,
11 core_api::{BlockSizeUser, BufferKindUser, CoreProxy, FixedOutputCore, UpdateCore},
12 generic_array::typenum::{IsLess, Le, NonZero, U256},
13 HashMarker,
14 },
15 pbkdf2_hmac,
16};
17use scrypt::scrypt;
18
19const MAX_KEY_LEN: usize = 32;
21
22fn cbc_encrypt<'a, C: BlockEncryptMut + BlockCipher + KeyInit>(
23 es: EncryptionScheme<'_>,
24 key: EncryptionKey,
25 iv: &[u8],
26 buffer: &'a mut [u8],
27 pos: usize,
28) -> Result<&'a [u8]> {
29 cbc::Encryptor::<C>::new_from_slices(key.as_slice(), iv)
30 .map_err(|_| es.to_alg_params_invalid())?
31 .encrypt_padded_mut::<Pkcs7>(buffer, pos)
32 .map_err(|_| Error::EncryptFailed)
33}
34
35fn cbc_decrypt<'a, C: BlockDecryptMut + BlockCipher + KeyInit>(
36 es: EncryptionScheme<'_>,
37 key: EncryptionKey,
38 iv: &[u8],
39 buffer: &'a mut [u8],
40) -> Result<&'a [u8]> {
41 cbc::Decryptor::<C>::new_from_slices(key.as_slice(), iv)
42 .map_err(|_| es.to_alg_params_invalid())?
43 .decrypt_padded_mut::<Pkcs7>(buffer)
44 .map_err(|_| Error::EncryptFailed)
45}
46
47pub fn encrypt_in_place<'b>(
48 params: &Parameters<'_>,
49 password: impl AsRef<[u8]>,
50 buf: &'b mut [u8],
51 pos: usize,
52) -> Result<&'b [u8]> {
53 let es = params.encryption;
54 let key_size = es.key_size();
55 if key_size > MAX_KEY_LEN {
56 return Err(es.to_alg_params_invalid());
57 }
58 let key = EncryptionKey::derive_from_password(password.as_ref(), ¶ms.kdf, key_size)?;
59
60 match es {
61 EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::<aes::Aes128Enc>(es, key, iv, buf, pos),
62 EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::<aes::Aes192Enc>(es, key, iv, buf, pos),
63 EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::<aes::Aes256Enc>(es, key, iv, buf, pos),
64 #[cfg(feature = "3des")]
65 EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::<des::TdesEde3>(es, key, iv, buf, pos),
66 #[cfg(feature = "des-insecure")]
67 EncryptionScheme::DesCbc { .. } => Err(Error::UnsupportedAlgorithm {
68 oid: super::DES_CBC_OID,
69 }),
70 }
71}
72
73pub fn decrypt_in_place<'a>(
75 params: &Parameters<'_>,
76 password: impl AsRef<[u8]>,
77 buf: &'a mut [u8],
78) -> Result<&'a [u8]> {
79 let es = params.encryption;
80 let key = EncryptionKey::derive_from_password(password.as_ref(), ¶ms.kdf, es.key_size())?;
81
82 match es {
83 EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::<aes::Aes128Dec>(es, key, iv, buf),
84 EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::<aes::Aes192Dec>(es, key, iv, buf),
85 EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::<aes::Aes256Dec>(es, key, iv, buf),
86 #[cfg(feature = "3des")]
87 EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::<des::TdesEde3>(es, key, iv, buf),
88 #[cfg(feature = "des-insecure")]
89 EncryptionScheme::DesCbc { iv } => cbc_decrypt::<des::Des>(es, key, iv, buf),
90 }
91}
92
93struct EncryptionKey {
96 buffer: [u8; MAX_KEY_LEN],
97 length: usize,
98}
99
100impl EncryptionKey {
101 pub fn derive_from_password(password: &[u8], kdf: &Kdf<'_>, key_size: usize) -> Result<Self> {
103 if let Some(len) = kdf.key_length() {
105 if key_size != len.into() {
106 return Err(kdf.to_alg_params_invalid());
107 }
108 }
109
110 match kdf {
111 Kdf::Pbkdf2(pbkdf2_params) => {
112 let key = match pbkdf2_params.prf {
113 #[cfg(feature = "sha1-insecure")]
114 Pbkdf2Prf::HmacWithSha1 => EncryptionKey::derive_with_pbkdf2::<sha1::Sha1>(
115 password,
116 pbkdf2_params,
117 key_size,
118 ),
119 #[cfg(not(feature = "sha1-insecure"))]
120 Pbkdf2Prf::HmacWithSha1 => {
121 return Err(Error::UnsupportedAlgorithm {
122 oid: super::HMAC_WITH_SHA1_OID,
123 })
124 }
125 Pbkdf2Prf::HmacWithSha224 => EncryptionKey::derive_with_pbkdf2::<sha2::Sha224>(
126 password,
127 pbkdf2_params,
128 key_size,
129 ),
130 Pbkdf2Prf::HmacWithSha256 => EncryptionKey::derive_with_pbkdf2::<sha2::Sha256>(
131 password,
132 pbkdf2_params,
133 key_size,
134 ),
135 Pbkdf2Prf::HmacWithSha384 => EncryptionKey::derive_with_pbkdf2::<sha2::Sha384>(
136 password,
137 pbkdf2_params,
138 key_size,
139 ),
140 Pbkdf2Prf::HmacWithSha512 => EncryptionKey::derive_with_pbkdf2::<sha2::Sha512>(
141 password,
142 pbkdf2_params,
143 key_size,
144 ),
145 };
146
147 Ok(key)
148 }
149 Kdf::Scrypt(scrypt_params) => {
150 EncryptionKey::derive_with_scrypt(password, scrypt_params, key_size)
151 }
152 }
153 }
154
155 fn derive_with_pbkdf2<D>(password: &[u8], params: &Pbkdf2Params<'_>, length: usize) -> Self
157 where
158 D: CoreProxy,
159 D::Core: Sync
160 + HashMarker
161 + UpdateCore
162 + FixedOutputCore
163 + BufferKindUser<BufferKind = Eager>
164 + Default
165 + Clone,
166 <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
167 Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
168 {
169 let mut buffer = [0u8; MAX_KEY_LEN];
170
171 pbkdf2_hmac::<D>(
172 password,
173 params.salt,
174 params.iteration_count,
175 &mut buffer[..length],
176 );
177
178 Self { buffer, length }
179 }
180
181 fn derive_with_scrypt(
183 password: &[u8],
184 params: &ScryptParams<'_>,
185 length: usize,
186 ) -> Result<Self> {
187 let mut buffer = [0u8; MAX_KEY_LEN];
188 scrypt(
189 password,
190 params.salt,
191 ¶ms.try_into()?,
192 &mut buffer[..length],
193 )
194 .map_err(|_| Error::AlgorithmParametersInvalid {
195 oid: super::SCRYPT_OID,
196 })?;
197
198 Ok(Self { buffer, length })
199 }
200
201 fn as_slice(&self) -> &[u8] {
203 &self.buffer[..self.length]
204 }
205}