1use aes::cipher::crypto_common::Key;
6use aes::{Aes128, Aes192, Aes256};
7use cbc::{Decryptor, Encryptor};
8use cipher::block_padding::Pkcs7;
9use cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
10
11use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{KeyType, KeyUsage};
12use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
13use crate::dom::bindings::error::Error;
14use crate::dom::bindings::root::DomRoot;
15use crate::dom::cryptokey::{CryptoKey, Handle};
16use crate::dom::globalscope::GlobalScope;
17use crate::dom::subtlecrypto::aes_common::AesAlgorithm;
18use crate::dom::subtlecrypto::{
19 ALG_AES_CBC, ExportedKey, KeyAlgorithmAndDerivatives, SubtleAesCbcParams,
20 SubtleAesDerivedKeyParams, SubtleAesKeyAlgorithm, SubtleAesKeyGenParams, aes_common,
21};
22use crate::script_runtime::CanGc;
23
24pub(crate) fn encrypt(
26 normalized_algorithm: &SubtleAesCbcParams,
27 key: &CryptoKey,
28 plaintext: &[u8],
29) -> Result<Vec<u8>, Error> {
30 if normalized_algorithm.iv.len() != 16 {
33 return Err(Error::Operation(Some(
34 "The initialization vector length is not 16 bytes".into(),
35 )));
36 }
37
38 let iv = normalized_algorithm.iv.as_slice();
44 let ciphertext = match key.handle() {
45 Handle::Aes128Key(key) => {
46 let encryptor = Encryptor::<Aes128>::new(key, iv.into());
47 encryptor.encrypt_padded_vec_mut::<Pkcs7>(plaintext)
48 },
49 Handle::Aes192Key(key) => {
50 let encryptor = Encryptor::<Aes192>::new(key, iv.into());
51 encryptor.encrypt_padded_vec_mut::<Pkcs7>(plaintext)
52 },
53 Handle::Aes256Key(key) => {
54 let encryptor = Encryptor::<Aes256>::new(key, iv.into());
55 encryptor.encrypt_padded_vec_mut::<Pkcs7>(plaintext)
56 },
57 _ => {
58 return Err(Error::Operation(Some(
59 "The key handle is not representing an AES key".to_string(),
60 )));
61 },
62 };
63
64 Ok(ciphertext)
66}
67
68pub(crate) fn decrypt(
70 normalized_algorithm: &SubtleAesCbcParams,
71 key: &CryptoKey,
72 ciphertext: &[u8],
73) -> Result<Vec<u8>, Error> {
74 if normalized_algorithm.iv.len() != 16 {
77 return Err(Error::Operation(Some(
78 "The initialization vector length is not 16 bytes".into(),
79 )));
80 }
81
82 if ciphertext.is_empty() {
85 return Err(Error::Operation(Some("The ciphertext is empty".into())));
86 }
87 if ciphertext.len() % 16 != 0 {
88 return Err(Error::Operation(Some(
89 "The ciphertext length is not a multiple of 16 bytes".into(),
90 )));
91 }
92
93 let iv = normalized_algorithm.iv.as_slice();
101 let plaintext = match key.handle() {
102 Handle::Aes128Key(key) => {
103 let decryptor = Decryptor::<Aes128>::new(key, iv.into());
104 decryptor
105 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
106 .map_err(|_| {
107 Error::Operation(Some("Failed to perform AES-CBC decryption".to_string()))
108 })?
109 },
110 Handle::Aes192Key(key) => {
111 let decryptor = Decryptor::<Aes192>::new(key, iv.into());
112 decryptor
113 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
114 .map_err(|_| {
115 Error::Operation(Some("Failed to perform AES-CBC decryption".to_string()))
116 })?
117 },
118 Handle::Aes256Key(key) => {
119 let decryptor = Decryptor::<Aes256>::new(key, iv.into());
120 decryptor
121 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
122 .map_err(|_| {
123 Error::Operation(Some("Failed to perform AES-CBC decryption".to_string()))
124 })?
125 },
126 _ => {
127 return Err(Error::Operation(Some(
128 "The key handle is not representing an AES key".to_string(),
129 )));
130 },
131 };
132 Ok(plaintext)
134}
135
136pub(crate) fn generate_key(
138 global: &GlobalScope,
139 normalized_algorithm: &SubtleAesKeyGenParams,
140 extractable: bool,
141 usages: Vec<KeyUsage>,
142 can_gc: CanGc,
143) -> Result<DomRoot<CryptoKey>, Error> {
144 aes_common::generate_key(
145 AesAlgorithm::AesCbc,
146 global,
147 normalized_algorithm,
148 extractable,
149 usages,
150 can_gc,
151 )
152}
153
154pub(crate) fn import_key(
156 global: &GlobalScope,
157 format: KeyFormat,
158 key_data: &[u8],
159 extractable: bool,
160 usages: Vec<KeyUsage>,
161 can_gc: CanGc,
162) -> Result<DomRoot<CryptoKey>, Error> {
163 if usages.iter().any(|usage| {
168 !matches!(
169 usage,
170 KeyUsage::Encrypt | KeyUsage::Decrypt | KeyUsage::WrapKey | KeyUsage::UnwrapKey
171 )
172 }) {
173 return Err(Error::Syntax(Some(
174 "Usages contains an entry which is not one of \"encrypt\", \"decrypt\", \"wrapKey\" \
175 or \"unwrapKey\""
176 .to_string(),
177 )));
178 }
179
180 let data = aes_common::import_key_from_key_data(
182 AesAlgorithm::AesCbc,
183 format,
184 key_data,
185 extractable,
186 &usages,
187 )?;
188
189 let handle = match data.len() {
195 16 => Handle::Aes128Key(Key::<Aes128>::clone_from_slice(&data)),
196 24 => Handle::Aes192Key(Key::<Aes192>::clone_from_slice(&data)),
197 32 => Handle::Aes256Key(Key::<Aes256>::clone_from_slice(&data)),
198 _ => {
199 return Err(Error::Data(Some(
200 "The length in bits of data is not 128, 192 or 256".to_string(),
201 )));
202 },
203 };
204 let algorithm = SubtleAesKeyAlgorithm {
205 name: ALG_AES_CBC.to_string(),
206 length: data.len() as u16 * 8,
207 };
208 let key = CryptoKey::new(
209 global,
210 KeyType::Secret,
211 extractable,
212 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm),
213 usages,
214 handle,
215 can_gc,
216 );
217
218 Ok(key)
220}
221
222pub(crate) fn export_key(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
224 aes_common::export_key(AesAlgorithm::AesCbc, format, key)
225}
226
227pub(crate) fn get_key_length(
229 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
230) -> Result<Option<u32>, Error> {
231 aes_common::get_key_length(normalized_derived_key_algorithm)
232}