1mod kdf;
6
7#[cfg(feature = "pbes2")]
8mod encryption;
9
10pub use self::kdf::{
11 Kdf, Pbkdf2Params, Pbkdf2Prf, ScryptParams, HMAC_WITH_SHA1_OID, HMAC_WITH_SHA256_OID,
12 PBKDF2_OID, SCRYPT_OID,
13};
14
15use crate::{AlgorithmIdentifierRef, Error, Result};
16use der::{
17 asn1::{AnyRef, ObjectIdentifier, OctetStringRef},
18 Decode, DecodeValue, Encode, EncodeValue, ErrorKind, Length, Reader, Sequence, Tag, Writer,
19};
20
21#[cfg(all(feature = "alloc", feature = "pbes2"))]
22use alloc::vec::Vec;
23
24pub const AES_128_CBC_OID: ObjectIdentifier =
27 ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.2");
28
29pub const AES_192_CBC_OID: ObjectIdentifier =
32 ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.22");
33
34pub const AES_256_CBC_OID: ObjectIdentifier =
37 ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.1.42");
38
39#[cfg(feature = "des-insecure")]
41pub const DES_CBC_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.7");
42
43#[cfg(feature = "3des")]
45pub const DES_EDE3_CBC_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.3.7");
46
47pub const PBES2_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.5.13");
51
52const AES_BLOCK_SIZE: usize = 16;
54
55#[cfg(any(feature = "3des", feature = "des-insecure"))]
57const DES_BLOCK_SIZE: usize = 8;
58
59#[derive(Clone, Debug, Eq, PartialEq)]
69pub struct Parameters<'a> {
70 pub kdf: Kdf<'a>,
72
73 pub encryption: EncryptionScheme<'a>,
75}
76
77impl<'a> Parameters<'a> {
78 pub fn pbkdf2_sha256_aes128cbc(
81 pbkdf2_iterations: u32,
82 pbkdf2_salt: &'a [u8],
83 aes_iv: &'a [u8; AES_BLOCK_SIZE],
84 ) -> Result<Self> {
85 let kdf = Pbkdf2Params::hmac_with_sha256(pbkdf2_iterations, pbkdf2_salt)?.into();
86 let encryption = EncryptionScheme::Aes128Cbc { iv: aes_iv };
87 Ok(Self { kdf, encryption })
88 }
89
90 pub fn pbkdf2_sha256_aes256cbc(
93 pbkdf2_iterations: u32,
94 pbkdf2_salt: &'a [u8],
95 aes_iv: &'a [u8; AES_BLOCK_SIZE],
96 ) -> Result<Self> {
97 let kdf = Pbkdf2Params::hmac_with_sha256(pbkdf2_iterations, pbkdf2_salt)?.into();
98 let encryption = EncryptionScheme::Aes256Cbc { iv: aes_iv };
99 Ok(Self { kdf, encryption })
100 }
101
102 #[cfg(feature = "pbes2")]
109 pub fn scrypt_aes128cbc(
110 params: scrypt::Params,
111 salt: &'a [u8],
112 aes_iv: &'a [u8; AES_BLOCK_SIZE],
113 ) -> Result<Self> {
114 let kdf = ScryptParams::from_params_and_salt(params, salt)?.into();
115 let encryption = EncryptionScheme::Aes128Cbc { iv: aes_iv };
116 Ok(Self { kdf, encryption })
117 }
118
119 #[cfg(feature = "pbes2")]
129 pub fn scrypt_aes256cbc(
130 params: scrypt::Params,
131 salt: &'a [u8],
132 aes_iv: &'a [u8; AES_BLOCK_SIZE],
133 ) -> Result<Self> {
134 let kdf = ScryptParams::from_params_and_salt(params, salt)?.into();
135 let encryption = EncryptionScheme::Aes256Cbc { iv: aes_iv };
136 Ok(Self { kdf, encryption })
137 }
138
139 #[cfg(all(feature = "alloc", feature = "pbes2"))]
142 pub fn decrypt(&self, password: impl AsRef<[u8]>, ciphertext: &[u8]) -> Result<Vec<u8>> {
143 let mut buffer = ciphertext.to_vec();
144 let pt_len = self.decrypt_in_place(password, &mut buffer)?.len();
145 buffer.truncate(pt_len);
146 Ok(buffer)
147 }
148
149 #[cfg(feature = "pbes2")]
156 pub fn decrypt_in_place<'b>(
157 &self,
158 password: impl AsRef<[u8]>,
159 buffer: &'b mut [u8],
160 ) -> Result<&'b [u8]> {
161 encryption::decrypt_in_place(self, password, buffer)
162 }
163
164 #[cfg(all(feature = "alloc", feature = "pbes2"))]
167 pub fn encrypt(&self, password: impl AsRef<[u8]>, plaintext: &[u8]) -> Result<Vec<u8>> {
168 let mut buffer = Vec::with_capacity(plaintext.len() + AES_BLOCK_SIZE);
170 buffer.extend_from_slice(plaintext);
171 buffer.extend_from_slice(&[0u8; AES_BLOCK_SIZE]);
172
173 let ct_len = self
174 .encrypt_in_place(password, &mut buffer, plaintext.len())?
175 .len();
176
177 buffer.truncate(ct_len);
178 Ok(buffer)
179 }
180
181 #[cfg(feature = "pbes2")]
185 pub fn encrypt_in_place<'b>(
186 &self,
187 password: impl AsRef<[u8]>,
188 buffer: &'b mut [u8],
189 pos: usize,
190 ) -> Result<&'b [u8]> {
191 encryption::encrypt_in_place(self, password, buffer, pos)
192 }
193}
194
195impl<'a> DecodeValue<'a> for Parameters<'a> {
196 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
197 AnyRef::decode_value(reader, header)?.try_into()
198 }
199}
200
201impl EncodeValue for Parameters<'_> {
202 fn value_len(&self) -> der::Result<Length> {
203 self.kdf.encoded_len()? + self.encryption.encoded_len()?
204 }
205
206 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
207 self.kdf.encode(writer)?;
208 self.encryption.encode(writer)?;
209 Ok(())
210 }
211}
212
213impl<'a> Sequence<'a> for Parameters<'a> {}
214
215impl<'a> TryFrom<AnyRef<'a>> for Parameters<'a> {
216 type Error = der::Error;
217
218 fn try_from(any: AnyRef<'a>) -> der::Result<Self> {
219 any.sequence(|params| {
220 let kdf = AlgorithmIdentifierRef::decode(params)?;
221 let encryption = AlgorithmIdentifierRef::decode(params)?;
222
223 Ok(Self {
224 kdf: kdf.try_into()?,
225 encryption: encryption.try_into()?,
226 })
227 })
228 }
229}
230
231#[derive(Copy, Clone, Debug, Eq, PartialEq)]
233#[non_exhaustive]
234pub enum EncryptionScheme<'a> {
235 Aes128Cbc {
237 iv: &'a [u8; AES_BLOCK_SIZE],
239 },
240
241 Aes192Cbc {
243 iv: &'a [u8; AES_BLOCK_SIZE],
245 },
246
247 Aes256Cbc {
249 iv: &'a [u8; AES_BLOCK_SIZE],
251 },
252
253 #[cfg(feature = "3des")]
255 DesEde3Cbc {
256 iv: &'a [u8; DES_BLOCK_SIZE],
258 },
259
260 #[cfg(feature = "des-insecure")]
262 DesCbc {
263 iv: &'a [u8; DES_BLOCK_SIZE],
265 },
266}
267
268impl<'a> EncryptionScheme<'a> {
269 pub fn key_size(&self) -> usize {
271 match self {
272 Self::Aes128Cbc { .. } => 16,
273 Self::Aes192Cbc { .. } => 24,
274 Self::Aes256Cbc { .. } => 32,
275 #[cfg(feature = "des-insecure")]
276 Self::DesCbc { .. } => 8,
277 #[cfg(feature = "3des")]
278 Self::DesEde3Cbc { .. } => 24,
279 }
280 }
281
282 pub fn oid(&self) -> ObjectIdentifier {
284 match self {
285 Self::Aes128Cbc { .. } => AES_128_CBC_OID,
286 Self::Aes192Cbc { .. } => AES_192_CBC_OID,
287 Self::Aes256Cbc { .. } => AES_256_CBC_OID,
288 #[cfg(feature = "des-insecure")]
289 Self::DesCbc { .. } => DES_CBC_OID,
290 #[cfg(feature = "3des")]
291 Self::DesEde3Cbc { .. } => DES_EDE3_CBC_OID,
292 }
293 }
294
295 pub fn to_alg_params_invalid(&self) -> Error {
299 Error::AlgorithmParametersInvalid { oid: self.oid() }
300 }
301}
302
303impl<'a> Decode<'a> for EncryptionScheme<'a> {
304 fn decode<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
305 AlgorithmIdentifierRef::decode(reader).and_then(TryInto::try_into)
306 }
307}
308
309impl<'a> TryFrom<AlgorithmIdentifierRef<'a>> for EncryptionScheme<'a> {
310 type Error = der::Error;
311
312 fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result<Self> {
313 let iv = match alg.parameters {
315 Some(params) => params.decode_as::<OctetStringRef<'a>>()?.as_bytes(),
316 None => return Err(Tag::OctetString.value_error()),
317 };
318
319 match alg.oid {
320 AES_128_CBC_OID => Ok(Self::Aes128Cbc {
321 iv: iv
322 .try_into()
323 .map_err(|_| der::Tag::OctetString.value_error())?,
324 }),
325 AES_192_CBC_OID => Ok(Self::Aes192Cbc {
326 iv: iv
327 .try_into()
328 .map_err(|_| der::Tag::OctetString.value_error())?,
329 }),
330 AES_256_CBC_OID => Ok(Self::Aes256Cbc {
331 iv: iv
332 .try_into()
333 .map_err(|_| der::Tag::OctetString.value_error())?,
334 }),
335 #[cfg(feature = "des-insecure")]
336 DES_CBC_OID => Ok(Self::DesCbc {
337 iv: iv[0..DES_BLOCK_SIZE]
338 .try_into()
339 .map_err(|_| der::Tag::OctetString.value_error())?,
340 }),
341 #[cfg(feature = "3des")]
342 DES_EDE3_CBC_OID => Ok(Self::DesEde3Cbc {
343 iv: iv[0..DES_BLOCK_SIZE]
344 .try_into()
345 .map_err(|_| der::Tag::OctetString.value_error())?,
346 }),
347 oid => Err(ErrorKind::OidUnknown { oid }.into()),
348 }
349 }
350}
351
352impl<'a> TryFrom<EncryptionScheme<'a>> for AlgorithmIdentifierRef<'a> {
353 type Error = der::Error;
354
355 fn try_from(scheme: EncryptionScheme<'a>) -> der::Result<Self> {
356 let parameters = OctetStringRef::new(match scheme {
357 EncryptionScheme::Aes128Cbc { iv } => iv,
358 EncryptionScheme::Aes192Cbc { iv } => iv,
359 EncryptionScheme::Aes256Cbc { iv } => iv,
360 #[cfg(feature = "des-insecure")]
361 EncryptionScheme::DesCbc { iv } => iv,
362 #[cfg(feature = "3des")]
363 EncryptionScheme::DesEde3Cbc { iv } => iv,
364 })?;
365
366 Ok(AlgorithmIdentifierRef {
367 oid: scheme.oid(),
368 parameters: Some(parameters.into()),
369 })
370 }
371}
372
373impl<'a> Encode for EncryptionScheme<'a> {
374 fn encoded_len(&self) -> der::Result<Length> {
375 AlgorithmIdentifierRef::try_from(*self)?.encoded_len()
376 }
377
378 fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
379 AlgorithmIdentifierRef::try_from(*self)?.encode(writer)
380 }
381}