1use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit, block_padding::Pkcs7};
9use generic_array::GenericArray;
10use hmac::Mac;
11use subtle::ConstantTimeEq;
12use typenum::U32;
13
14use crate::{
15 error::Result,
16 util::{PBKDF_SHA256_HMAC_OUT_SIZE, PbkdfSha256Hmac},
17};
18
19#[derive(Debug)]
21pub(crate) struct DecryptError {}
22
23pub(crate) fn decrypt_aes256(
27 iv: &[u8; 16],
28 data: Vec<u8>,
29 key: &GenericArray<u8, U32>,
30) -> Result<Vec<u8>, DecryptError> {
31 let iv = GenericArray::from_slice(iv);
33 let mut data = data;
34 let decrypted_key_slice = cbc::Decryptor::<aes::Aes256>::new(key, iv)
35 .decrypt_padded_mut::<Pkcs7>(&mut data)
36 .map_err(|_| DecryptError {})?;
37
38 let decrypted_len = decrypted_key_slice.len();
41 data.truncate(decrypted_len);
42
43 Ok(data)
44}
45
46pub(crate) fn decrypt_aes256_hmac(
50 iv: &[u8; 16],
51 mac: &[u8; 32],
52 data: Vec<u8>,
53 mac_key: &GenericArray<u8, U32>,
54 key: &GenericArray<u8, U32>,
55) -> Result<Vec<u8>, DecryptError> {
56 let res = generate_mac(mac_key, iv, &data);
57 if res.ct_ne(mac).into() {
58 return Err(DecryptError {});
59 }
60 decrypt_aes256(iv, data, key)
61}
62
63pub(crate) fn encrypt_aes256_hmac(
69 data_dec: &[u8],
70 mac_key: &GenericArray<u8, U32>,
71 key: &GenericArray<u8, U32>,
72) -> Result<([u8; 16], [u8; 32], Vec<u8>)> {
73 let rng = rand::thread_rng();
74 let (iv, data) = encrypt_aes256_internal(rng, data_dec, key);
75 let mac = generate_mac(mac_key, &iv, &data);
76
77 Ok((iv, mac, data))
78}
79
80fn encrypt_aes256_internal(
85 mut rng: impl rand::RngCore,
86 data_dec: &[u8],
87 key: &GenericArray<u8, U32>,
88) -> ([u8; 16], Vec<u8>) {
89 let mut iv = [0u8; 16];
90 rng.fill_bytes(&mut iv);
91 let data = cbc::Encryptor::<aes::Aes256>::new(key, &iv.into())
92 .encrypt_padded_vec_mut::<Pkcs7>(data_dec);
93
94 (iv, data)
95}
96
97fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> [u8; 32] {
99 let mut hmac =
100 PbkdfSha256Hmac::new_from_slice(mac_key).expect("hmac new_from_slice should not fail");
101 hmac.update(iv);
102 hmac.update(data);
103 let mac: [u8; PBKDF_SHA256_HMAC_OUT_SIZE] = (*hmac.finalize().into_bytes())
104 .try_into()
105 .expect("HMAC output size to be correct");
107 mac
108}
109
110#[cfg(test)]
111mod tests {
112 use bitwarden_encoding::B64;
113 use generic_array::{ArrayLength, sequence::GenericSequence};
114 use rand::SeedableRng;
115
116 use super::*;
117
118 fn generate_generic_array<N: ArrayLength<u8>>(
121 offset: u8,
122 increment: u8,
123 ) -> GenericArray<u8, N> {
124 GenericArray::generate(|i| offset + i as u8 * increment)
125 }
126
127 fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec<u8> {
130 (0..length).map(|i| offset + i as u8 * increment).collect()
131 }
132
133 #[test]
134 fn test_encrypt_aes256_internal() {
135 let key = generate_generic_array(0, 1);
136
137 let rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]);
138 let result = encrypt_aes256_internal(rng, "EncryptMe!".as_bytes(), &key);
139 assert_eq!(
140 result,
141 (
142 [
143 62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161
144 ],
145 vec![
146 214, 76, 187, 97, 58, 146, 212, 140, 95, 164, 177, 204, 179, 133, 172, 148
147 ]
148 )
149 );
150 }
151
152 #[test]
153 fn test_generate_mac() {
154 let mac_key = generate_vec(16, 0, 16);
155
156 let iv = generate_vec(16, 0, 16);
157 let data = generate_vec(16, 0, 16);
158
159 let mac = generate_mac(&mac_key, &iv, &data);
160 assert!(mac.iter().any(|&b| b != 0));
161 }
162
163 #[test]
164 fn test_decrypt_aes256() {
165 let iv = generate_vec(16, 0, 1);
166 let iv: &[u8; 16] = iv.as_slice().try_into().unwrap();
167 let key = generate_generic_array(0, 1);
168 let data: B64 = ("ByUF8vhyX4ddU9gcooznwA==").parse().unwrap();
169
170 let decrypted = decrypt_aes256(iv, data.into(), &key).unwrap();
171
172 assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!");
173 }
174}