script/dom/webcrypto/subtlecrypto/
aes_cbc_operation.rs1use aes::{Aes128, Aes192, Aes256};
6use cbc::cipher::block_padding::Pkcs7;
7use cbc::cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit};
8use cbc::{Decryptor, Encryptor};
9use js::context::JSContext;
10
11use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::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 ExportedKey, SubtleAesCbcParams, SubtleAesDerivedKeyParams, SubtleAesKeyGenParams, aes_common,
20};
21
22pub(crate) fn encrypt(
24 normalized_algorithm: &SubtleAesCbcParams,
25 key: &CryptoKey,
26 plaintext: &[u8],
27) -> Result<Vec<u8>, Error> {
28 if normalized_algorithm.iv.len() != 16 {
31 return Err(Error::Operation(Some(
32 "The initialization vector length is not 16 bytes".into(),
33 )));
34 }
35
36 let iv = normalized_algorithm
42 .iv
43 .as_slice()
44 .try_into()
45 .map_err(|_| Error::Operation(Some("Invalid AES-CBC IV".into())))?;
46 let ciphertext = match key.handle() {
47 Handle::Aes128Key(key) => {
48 let encryptor = Encryptor::<Aes128>::new(key, &iv);
49 encryptor.encrypt_padded_vec::<Pkcs7>(plaintext)
50 },
51 Handle::Aes192Key(key) => {
52 let encryptor = Encryptor::<Aes192>::new(key, &iv);
53 encryptor.encrypt_padded_vec::<Pkcs7>(plaintext)
54 },
55 Handle::Aes256Key(key) => {
56 let encryptor = Encryptor::<Aes256>::new(key, &iv);
57 encryptor.encrypt_padded_vec::<Pkcs7>(plaintext)
58 },
59 _ => {
60 return Err(Error::Operation(Some(
61 "The key handle is not representing an AES key".to_string(),
62 )));
63 },
64 };
65
66 Ok(ciphertext)
68}
69
70pub(crate) fn decrypt(
72 normalized_algorithm: &SubtleAesCbcParams,
73 key: &CryptoKey,
74 ciphertext: &[u8],
75) -> Result<Vec<u8>, Error> {
76 if normalized_algorithm.iv.len() != 16 {
79 return Err(Error::Operation(Some(
80 "The initialization vector length is not 16 bytes".into(),
81 )));
82 }
83
84 if ciphertext.is_empty() {
87 return Err(Error::Operation(Some("The ciphertext is empty".into())));
88 }
89 if !ciphertext.len().is_multiple_of(16) {
90 return Err(Error::Operation(Some(
91 "The ciphertext length is not a multiple of 16 bytes".into(),
92 )));
93 }
94
95 let iv = normalized_algorithm
103 .iv
104 .as_slice()
105 .try_into()
106 .map_err(|_| Error::Operation(Some("Invalid AES-CBC IV".into())))?;
107 let plaintext = match key.handle() {
108 Handle::Aes128Key(key) => {
109 let decryptor = Decryptor::<Aes128>::new(key, &iv);
110 decryptor.decrypt_padded_vec::<Pkcs7>(ciphertext)
111 },
112 Handle::Aes192Key(key) => {
113 let decryptor = Decryptor::<Aes192>::new(key, &iv);
114 decryptor.decrypt_padded_vec::<Pkcs7>(ciphertext)
115 },
116 Handle::Aes256Key(key) => {
117 let decryptor = Decryptor::<Aes256>::new(key, &iv);
118 decryptor.decrypt_padded_vec::<Pkcs7>(ciphertext)
119 },
120 _ => {
121 return Err(Error::Operation(Some(
122 "The key handle is not representing an AES key".to_string(),
123 )));
124 },
125 }
126 .map_err(|_| Error::Operation(Some("Failed to perform AES-CBC decryption".into())))?;
127
128 Ok(plaintext)
130}
131
132pub(crate) fn generate_key(
134 cx: &mut JSContext,
135 global: &GlobalScope,
136 normalized_algorithm: &SubtleAesKeyGenParams,
137 extractable: bool,
138 usages: Vec<KeyUsage>,
139) -> Result<DomRoot<CryptoKey>, Error> {
140 aes_common::generate_key(
141 AesAlgorithm::AesCbc,
142 cx,
143 global,
144 normalized_algorithm,
145 extractable,
146 usages,
147 )
148}
149
150pub(crate) fn import_key(
152 cx: &mut JSContext,
153 global: &GlobalScope,
154 format: KeyFormat,
155 key_data: &[u8],
156 extractable: bool,
157 usages: Vec<KeyUsage>,
158) -> Result<DomRoot<CryptoKey>, Error> {
159 aes_common::import_key(
160 AesAlgorithm::AesCbc,
161 cx,
162 global,
163 format,
164 key_data,
165 extractable,
166 usages,
167 )
168}
169
170pub(crate) fn export_key(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
172 aes_common::export_key(AesAlgorithm::AesCbc, format, key)
173}
174
175pub(crate) fn get_key_length(
177 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
178) -> Result<Option<u32>, Error> {
179 aes_common::get_key_length(normalized_derived_key_algorithm)
180}