1use aes::cipher::block_padding::Pkcs7;
6use aes::cipher::generic_array::GenericArray;
7use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit, StreamCipher};
8use aes::{Aes128, Aes192, Aes256};
9use aes_gcm::{AeadInPlace, AesGcm, KeyInit};
10use aes_kw::{KekAes128, KekAes192, KekAes256};
11use base64ct::{Base64UrlUnpadded, Encoding};
12use cipher::consts::{U12, U16, U32};
13use rand::TryRngCore;
14use rand::rngs::OsRng;
15
16use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
17 CryptoKeyMethods, KeyType, KeyUsage,
18};
19use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{JsonWebKey, KeyFormat};
20use crate::dom::bindings::error::Error;
21use crate::dom::bindings::root::DomRoot;
22use crate::dom::bindings::str::DOMString;
23use crate::dom::cryptokey::{CryptoKey, Handle};
24use crate::dom::globalscope::GlobalScope;
25use crate::dom::subtlecrypto::{
26 ALG_AES_CBC, ALG_AES_CTR, ALG_AES_GCM, ALG_AES_KW, ExportedKey, JsonWebKeyExt,
27 KeyAlgorithmAndDerivatives, SubtleAesCbcParams, SubtleAesCtrParams, SubtleAesDerivedKeyParams,
28 SubtleAesGcmParams, SubtleAesKeyAlgorithm, SubtleAesKeyGenParams,
29};
30use crate::script_runtime::CanGc;
31
32type Aes128CbcEnc = cbc::Encryptor<Aes128>;
33type Aes128CbcDec = cbc::Decryptor<Aes128>;
34type Aes192CbcEnc = cbc::Encryptor<Aes192>;
35type Aes192CbcDec = cbc::Decryptor<Aes192>;
36type Aes256CbcEnc = cbc::Encryptor<Aes256>;
37type Aes256CbcDec = cbc::Decryptor<Aes256>;
38type Aes128Ctr = ctr::Ctr64BE<Aes128>;
39type Aes192Ctr = ctr::Ctr64BE<Aes192>;
40type Aes256Ctr = ctr::Ctr64BE<Aes256>;
41
42type Aes128Gcm96Iv = AesGcm<Aes128, U12>;
43type Aes128Gcm128Iv = AesGcm<Aes128, U16>;
44type Aes192Gcm96Iv = AesGcm<Aes192, U12>;
45type Aes256Gcm96Iv = AesGcm<Aes256, U12>;
46type Aes128Gcm256Iv = AesGcm<Aes128, U32>;
47type Aes192Gcm256Iv = AesGcm<Aes192, U32>;
48type Aes256Gcm256Iv = AesGcm<Aes256, U32>;
49
50pub(crate) fn encrypt_aes_ctr(
52 normalized_algorithm: &SubtleAesCtrParams,
53 key: &CryptoKey,
54 plaintext: &[u8],
55) -> Result<Vec<u8>, Error> {
56 if normalized_algorithm.counter.len() != 16 ||
61 normalized_algorithm.length == 0 ||
62 normalized_algorithm.length > 128
63 {
64 return Err(Error::Operation);
65 }
66
67 let mut ciphertext = Vec::from(plaintext);
73 let counter = GenericArray::from_slice(&normalized_algorithm.counter);
74
75 match key.handle() {
76 Handle::Aes128(data) => {
77 let key_data = GenericArray::from_slice(data);
78 Aes128Ctr::new(key_data, counter).apply_keystream(&mut ciphertext)
79 },
80 Handle::Aes192(data) => {
81 let key_data = GenericArray::from_slice(data);
82 Aes192Ctr::new(key_data, counter).apply_keystream(&mut ciphertext)
83 },
84 Handle::Aes256(data) => {
85 let key_data = GenericArray::from_slice(data);
86 Aes256Ctr::new(key_data, counter).apply_keystream(&mut ciphertext)
87 },
88 _ => return Err(Error::Data),
89 };
90
91 Ok(ciphertext)
93}
94
95pub(crate) fn decrypt_aes_ctr(
97 normalized_algorithm: &SubtleAesCtrParams,
98 key: &CryptoKey,
99 ciphertext: &[u8],
100) -> Result<Vec<u8>, Error> {
101 encrypt_aes_ctr(normalized_algorithm, key, ciphertext)
103}
104
105pub(crate) fn generate_key_aes_ctr(
107 global: &GlobalScope,
108 normalized_algorithm: &SubtleAesKeyGenParams,
109 extractable: bool,
110 usages: Vec<KeyUsage>,
111 can_gc: CanGc,
112) -> Result<DomRoot<CryptoKey>, Error> {
113 generate_key_aes(
114 global,
115 normalized_algorithm,
116 extractable,
117 usages,
118 ALG_AES_CTR,
119 &[
120 KeyUsage::Encrypt,
121 KeyUsage::Decrypt,
122 KeyUsage::WrapKey,
123 KeyUsage::UnwrapKey,
124 ],
125 can_gc,
126 )
127}
128
129pub(crate) fn import_key_aes_ctr(
131 global: &GlobalScope,
132 format: KeyFormat,
133 key_data: &[u8],
134 extractable: bool,
135 usages: Vec<KeyUsage>,
136 can_gc: CanGc,
137) -> Result<DomRoot<CryptoKey>, Error> {
138 import_key_aes(
139 global,
140 format,
141 key_data,
142 extractable,
143 usages,
144 ALG_AES_CTR,
145 can_gc,
146 )
147}
148
149pub(crate) fn export_key_aes_ctr(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
151 export_key_aes(format, key)
152}
153
154pub(crate) fn get_key_length_aes_ctr(
156 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
157) -> Result<Option<u32>, Error> {
158 get_key_length_aes(normalized_derived_key_algorithm)
159}
160
161pub(crate) fn encrypt_aes_cbc(
163 normalized_algorithm: &SubtleAesCbcParams,
164 key: &CryptoKey,
165 plaintext: &[u8],
166) -> Result<Vec<u8>, Error> {
167 if normalized_algorithm.iv.len() != 16 {
170 return Err(Error::Operation);
171 }
172
173 let plaintext = Vec::from(plaintext);
179 let iv = GenericArray::from_slice(&normalized_algorithm.iv);
180 let ciphertext = match key.handle() {
181 Handle::Aes128(data) => {
182 let key_data = GenericArray::from_slice(data);
183 Aes128CbcEnc::new(key_data, iv).encrypt_padded_vec_mut::<Pkcs7>(&plaintext)
184 },
185 Handle::Aes192(data) => {
186 let key_data = GenericArray::from_slice(data);
187 Aes192CbcEnc::new(key_data, iv).encrypt_padded_vec_mut::<Pkcs7>(&plaintext)
188 },
189 Handle::Aes256(data) => {
190 let key_data = GenericArray::from_slice(data);
191 Aes256CbcEnc::new(key_data, iv).encrypt_padded_vec_mut::<Pkcs7>(&plaintext)
192 },
193 _ => return Err(Error::Data),
194 };
195
196 Ok(ciphertext)
198}
199
200pub(crate) fn decrypt_aes_cbc(
202 normalized_algorithm: &SubtleAesCbcParams,
203 key: &CryptoKey,
204 ciphertext: &[u8],
205) -> Result<Vec<u8>, Error> {
206 if normalized_algorithm.iv.len() != 16 {
209 return Err(Error::Operation);
210 }
211
212 if ciphertext.is_empty() || ciphertext.len() % 16 != 0 {
215 return Err(Error::Operation);
216 }
217
218 let mut ciphertext = Vec::from(ciphertext);
226 let iv = GenericArray::from_slice(&normalized_algorithm.iv);
227 let plaintext = match key.handle() {
228 Handle::Aes128(data) => {
229 let key_data = GenericArray::from_slice(data);
230 Aes128CbcDec::new(key_data, iv)
231 .decrypt_padded_mut::<Pkcs7>(ciphertext.as_mut_slice())
232 .map_err(|_| Error::Operation)?
233 },
234 Handle::Aes192(data) => {
235 let key_data = GenericArray::from_slice(data);
236 Aes192CbcDec::new(key_data, iv)
237 .decrypt_padded_mut::<Pkcs7>(ciphertext.as_mut_slice())
238 .map_err(|_| Error::Operation)?
239 },
240 Handle::Aes256(data) => {
241 let key_data = GenericArray::from_slice(data);
242 Aes256CbcDec::new(key_data, iv)
243 .decrypt_padded_mut::<Pkcs7>(ciphertext.as_mut_slice())
244 .map_err(|_| Error::Operation)?
245 },
246 _ => return Err(Error::Data),
247 };
248
249 Ok(plaintext.to_vec())
251}
252
253pub(crate) fn generate_key_aes_cbc(
255 global: &GlobalScope,
256 normalized_algorithm: &SubtleAesKeyGenParams,
257 extractable: bool,
258 usages: Vec<KeyUsage>,
259 can_gc: CanGc,
260) -> Result<DomRoot<CryptoKey>, Error> {
261 generate_key_aes(
262 global,
263 normalized_algorithm,
264 extractable,
265 usages,
266 ALG_AES_CBC,
267 &[
268 KeyUsage::Encrypt,
269 KeyUsage::Decrypt,
270 KeyUsage::WrapKey,
271 KeyUsage::UnwrapKey,
272 ],
273 can_gc,
274 )
275}
276
277pub(crate) fn import_key_aes_cbc(
279 global: &GlobalScope,
280 format: KeyFormat,
281 key_data: &[u8],
282 extractable: bool,
283 usages: Vec<KeyUsage>,
284 can_gc: CanGc,
285) -> Result<DomRoot<CryptoKey>, Error> {
286 import_key_aes(
287 global,
288 format,
289 key_data,
290 extractable,
291 usages,
292 ALG_AES_CBC,
293 can_gc,
294 )
295}
296
297pub(crate) fn export_key_aes_cbc(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
299 export_key_aes(format, key)
300}
301
302pub(crate) fn get_key_length_aes_cbc(
304 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
305) -> Result<Option<u32>, Error> {
306 get_key_length_aes(normalized_derived_key_algorithm)
307}
308
309pub(crate) fn encrypt_aes_gcm(
311 normalized_algorithm: &SubtleAesGcmParams,
312 key: &CryptoKey,
313 plaintext: &[u8],
314) -> Result<Vec<u8>, Error> {
315 if plaintext.len() as u64 > (2 << 39) - 256 {
317 return Err(Error::Operation);
318 }
319
320 if normalized_algorithm
327 .additional_data
328 .as_ref()
329 .is_some_and(|data| data.len() > u64::MAX as usize)
330 {
331 return Err(Error::Operation);
332 }
333
334 let tag_length = match normalized_algorithm.tag_length {
342 None => 128,
343 Some(length) if matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128) => length,
344 _ => {
345 return Err(Error::Operation);
346 },
347 };
348
349 let additional_data = normalized_algorithm
352 .additional_data
353 .as_deref()
354 .unwrap_or_default();
355
356 let key_length = key.handle().as_bytes().len();
362 let iv_length = normalized_algorithm.iv.len();
363 let mut ciphertext = plaintext.to_vec();
364 let key_bytes = key.handle().as_bytes();
365 let tag = match (key_length, iv_length) {
366 (16, 12) => {
367 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
368 <Aes128Gcm96Iv>::new_from_slice(key_bytes)
369 .expect("key length did not match")
370 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
371 },
372 (16, 16) => {
373 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
374 <Aes128Gcm128Iv>::new_from_slice(key_bytes)
375 .expect("key length did not match")
376 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
377 },
378 (24, 12) => {
379 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
380 <Aes192Gcm96Iv>::new_from_slice(key_bytes)
381 .expect("key length did not match")
382 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
383 },
384 (32, 12) => {
385 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
386 <Aes256Gcm96Iv>::new_from_slice(key_bytes)
387 .expect("key length did not match")
388 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
389 },
390 (16, 32) => {
391 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
392 <Aes128Gcm256Iv>::new_from_slice(key_bytes)
393 .expect("key length did not match")
394 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
395 },
396 (24, 32) => {
397 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
398 <Aes192Gcm256Iv>::new_from_slice(key_bytes)
399 .expect("key length did not match")
400 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
401 },
402 (32, 32) => {
403 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
404 <Aes256Gcm256Iv>::new_from_slice(key_bytes)
405 .expect("key length did not match")
406 .encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
407 },
408 _ => {
409 log::warn!(
410 "Missing AES-GCM encryption implementation with {key_length}-byte key and {iv_length}-byte IV"
411 );
412 return Err(Error::NotSupported);
413 },
414 };
415
416 ciphertext.extend_from_slice(&tag.unwrap()[..tag_length as usize / 8]);
418
419 Ok(ciphertext)
421}
422
423pub(crate) fn decrypt_aes_gcm(
425 normalized_algorithm: &SubtleAesGcmParams,
426 key: &CryptoKey,
427 ciphertext: &[u8],
428) -> Result<Vec<u8>, Error> {
429 let tag_length = match normalized_algorithm.tag_length {
437 None => 128,
438 Some(length) if matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128) => length as usize,
439 _ => {
440 return Err(Error::Operation);
441 },
442 };
443
444 if ciphertext.len() * 8 < tag_length {
447 return Err(Error::Operation);
448 }
449
450 let additional_data = normalized_algorithm
466 .additional_data
467 .as_deref()
468 .unwrap_or_default();
469
470 let mut plaintext = ciphertext.to_vec();
480 let key_length = key.handle().as_bytes().len();
481 let iv_length = normalized_algorithm.iv.len();
482 let key_bytes = key.handle().as_bytes();
483 let result = match (key_length, iv_length) {
484 (16, 12) => {
485 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
486 <Aes128Gcm96Iv>::new_from_slice(key_bytes)
487 .expect("key length did not match")
488 .decrypt_in_place(nonce, additional_data, &mut plaintext)
489 },
490 (16, 16) => {
491 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
492 <Aes128Gcm128Iv>::new_from_slice(key_bytes)
493 .expect("key length did not match")
494 .decrypt_in_place(nonce, additional_data, &mut plaintext)
495 },
496 (24, 12) => {
497 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
498 <Aes192Gcm96Iv>::new_from_slice(key_bytes)
499 .expect("key length did not match")
500 .decrypt_in_place(nonce, additional_data, &mut plaintext)
501 },
502 (32, 12) => {
503 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
504 <Aes256Gcm96Iv>::new_from_slice(key_bytes)
505 .expect("key length did not match")
506 .decrypt_in_place(nonce, additional_data, &mut plaintext)
507 },
508 (16, 32) => {
509 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
510 <Aes128Gcm256Iv>::new_from_slice(key_bytes)
511 .expect("key length did not match")
512 .decrypt_in_place(nonce, additional_data, &mut plaintext)
513 },
514 (24, 32) => {
515 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
516 <Aes192Gcm256Iv>::new_from_slice(key_bytes)
517 .expect("key length did not match")
518 .decrypt_in_place(nonce, additional_data, &mut plaintext)
519 },
520 (32, 32) => {
521 let nonce = GenericArray::from_slice(&normalized_algorithm.iv);
522 <Aes256Gcm256Iv>::new_from_slice(key_bytes)
523 .expect("key length did not match")
524 .decrypt_in_place(nonce, additional_data, &mut plaintext)
525 },
526 _ => {
527 log::warn!(
528 "Missing AES-GCM decryption implementation with {key_length}-byte key and {iv_length}-byte IV"
529 );
530 return Err(Error::NotSupported);
531 },
532 };
533 if result.is_err() {
534 return Err(Error::Operation);
535 }
536
537 Ok(plaintext)
538}
539
540pub(crate) fn generate_key_aes_gcm(
542 global: &GlobalScope,
543 normalized_algorithm: &SubtleAesKeyGenParams,
544 extractable: bool,
545 usages: Vec<KeyUsage>,
546 can_gc: CanGc,
547) -> Result<DomRoot<CryptoKey>, Error> {
548 generate_key_aes(
549 global,
550 normalized_algorithm,
551 extractable,
552 usages,
553 ALG_AES_GCM,
554 &[
555 KeyUsage::Encrypt,
556 KeyUsage::Decrypt,
557 KeyUsage::WrapKey,
558 KeyUsage::UnwrapKey,
559 ],
560 can_gc,
561 )
562}
563
564pub(crate) fn import_key_aes_gcm(
566 global: &GlobalScope,
567 format: KeyFormat,
568 key_data: &[u8],
569 extractable: bool,
570 usages: Vec<KeyUsage>,
571 can_gc: CanGc,
572) -> Result<DomRoot<CryptoKey>, Error> {
573 import_key_aes(
574 global,
575 format,
576 key_data,
577 extractable,
578 usages,
579 ALG_AES_GCM,
580 can_gc,
581 )
582}
583
584pub(crate) fn export_key_aes_gcm(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
586 export_key_aes(format, key)
587}
588
589pub(crate) fn get_key_length_aes_gcm(
591 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
592) -> Result<Option<u32>, Error> {
593 get_key_length_aes(normalized_derived_key_algorithm)
594}
595
596pub(crate) fn wrap_key_aes_kw(key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
598 if plaintext.len() % 8 != 0 {
600 return Err(Error::Operation);
601 }
602
603 let key_data = key.handle().as_bytes();
607 let ciphertext = match key_data.len() {
608 16 => {
609 let key_array = GenericArray::from_slice(key_data);
610 let kek = KekAes128::new(key_array);
611 match kek.wrap_vec(plaintext) {
612 Ok(key) => key,
613 Err(_) => return Err(Error::Operation),
614 }
615 },
616 24 => {
617 let key_array = GenericArray::from_slice(key_data);
618 let kek = KekAes192::new(key_array);
619 match kek.wrap_vec(plaintext) {
620 Ok(key) => key,
621 Err(_) => return Err(Error::Operation),
622 }
623 },
624 32 => {
625 let key_array = GenericArray::from_slice(key_data);
626 let kek = KekAes256::new(key_array);
627 match kek.wrap_vec(plaintext) {
628 Ok(key) => key,
629 Err(_) => return Err(Error::Operation),
630 }
631 },
632 _ => return Err(Error::Operation),
633 };
634
635 Ok(ciphertext)
637}
638
639pub(crate) fn unwrap_key_aes_kw(key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
641 let key_data = key.handle().as_bytes();
646 let plaintext = match key_data.len() {
647 16 => {
648 let key_array = GenericArray::from_slice(key_data);
649 let kek = KekAes128::new(key_array);
650 match kek.unwrap_vec(ciphertext) {
651 Ok(key) => key,
652 Err(_) => return Err(Error::Operation),
653 }
654 },
655 24 => {
656 let key_array = GenericArray::from_slice(key_data);
657 let kek = KekAes192::new(key_array);
658 match kek.unwrap_vec(ciphertext) {
659 Ok(key) => key,
660 Err(_) => return Err(Error::Operation),
661 }
662 },
663 32 => {
664 let key_array = GenericArray::from_slice(key_data);
665 let kek = KekAes256::new(key_array);
666 match kek.unwrap_vec(ciphertext) {
667 Ok(key) => key,
668 Err(_) => return Err(Error::Operation),
669 }
670 },
671 _ => return Err(Error::Operation),
672 };
673
674 Ok(plaintext)
676}
677
678pub(crate) fn generate_key_aes_kw(
680 global: &GlobalScope,
681 normalized_algorithm: &SubtleAesKeyGenParams,
682 extractable: bool,
683 usages: Vec<KeyUsage>,
684 can_gc: CanGc,
685) -> Result<DomRoot<CryptoKey>, Error> {
686 generate_key_aes(
687 global,
688 normalized_algorithm,
689 extractable,
690 usages,
691 ALG_AES_KW,
692 &[KeyUsage::WrapKey, KeyUsage::UnwrapKey],
693 can_gc,
694 )
695}
696
697pub(crate) fn import_key_aes_kw(
699 global: &GlobalScope,
700 format: KeyFormat,
701 key_data: &[u8],
702 extractable: bool,
703 usages: Vec<KeyUsage>,
704 can_gc: CanGc,
705) -> Result<DomRoot<CryptoKey>, Error> {
706 import_key_aes(
707 global,
708 format,
709 key_data,
710 extractable,
711 usages,
712 ALG_AES_KW,
713 can_gc,
714 )
715}
716
717pub(crate) fn export_key_aes_kw(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
719 export_key_aes(format, key)
720}
721
722pub(crate) fn get_key_length_aes_kw(
724 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
725) -> Result<Option<u32>, Error> {
726 get_key_length_aes(normalized_derived_key_algorithm)
727}
728
729#[allow(clippy::too_many_arguments)]
735fn generate_key_aes(
736 global: &GlobalScope,
737 normalized_algorithm: &SubtleAesKeyGenParams,
738 extractable: bool,
739 usages: Vec<KeyUsage>,
740 alg_name: &str,
741 allowed_usages: &[KeyUsage],
742 can_gc: CanGc,
743) -> Result<DomRoot<CryptoKey>, Error> {
744 if usages.iter().any(|usage| !allowed_usages.contains(usage)) {
746 return Err(Error::Syntax(None));
747 }
748
749 if !matches!(normalized_algorithm.length, 128 | 192 | 256) {
752 return Err(Error::Operation);
753 }
754
755 let mut rand = vec![0; normalized_algorithm.length as usize / 8];
758 if OsRng.try_fill_bytes(&mut rand).is_err() {
759 return Err(Error::JSFailed);
760 }
761
762 let handle = match normalized_algorithm.length {
763 128 => Handle::Aes128(rand),
764 192 => Handle::Aes192(rand),
765 256 => Handle::Aes256(rand),
766 _ => return Err(Error::Operation),
767 };
768
769 let algorithm = SubtleAesKeyAlgorithm {
773 name: alg_name.to_string(),
774 length: normalized_algorithm.length,
775 };
776
777 let crypto_key = CryptoKey::new(
783 global,
784 KeyType::Secret,
785 extractable,
786 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm),
787 usages,
788 handle,
789 can_gc,
790 );
791
792 Ok(crypto_key)
794}
795
796fn import_key_aes(
802 global: &GlobalScope,
803 format: KeyFormat,
804 key_data: &[u8],
805 extractable: bool,
806 usages: Vec<KeyUsage>,
807 alg_name: &str,
808 can_gc: CanGc,
809) -> Result<DomRoot<CryptoKey>, Error> {
810 if usages.iter().any(|usage| {
813 !matches!(
814 usage,
815 KeyUsage::Encrypt | KeyUsage::Decrypt | KeyUsage::WrapKey | KeyUsage::UnwrapKey
816 )
817 }) || usages.is_empty()
818 {
819 return Err(Error::Syntax(None));
820 }
821
822 let data;
824 match format {
825 KeyFormat::Raw => {
827 data = key_data.to_vec();
829
830 if !matches!(data.len() * 8, 128 | 192 | 256) {
832 return Err(Error::Data);
833 }
834 },
835 KeyFormat::Jwk => {
837 let jwk = JsonWebKey::parse(GlobalScope::get_cx(), key_data)?;
841
842 if jwk.kty.as_ref().is_none_or(|kty| kty != "oct") {
844 return Err(Error::Data);
845 }
846
847 data = Base64UrlUnpadded::decode_vec(&jwk.k.as_ref().ok_or(Error::Data)?.str())
853 .map_err(|_| Error::Data)?;
854
855 let alg_matching = match alg_name {
858 ALG_AES_CBC => ["A128CBC", "A192CBC", "A256CBC"],
859 ALG_AES_CTR => ["A128CTR", "A192CTR", "A256CTR"],
860 ALG_AES_GCM => ["A128GCM", "A192GCM", "A256GCM"],
861 ALG_AES_KW => ["A128KW", "A192KW", "A256KW"],
862 _ => unreachable!(),
863 };
864
865 match data.len() * 8 {
867 128 => {
869 if jwk.alg.as_ref().is_some_and(|alg| alg != alg_matching[0]) {
875 return Err(Error::Data);
876 }
877 },
878 192 => {
880 if jwk.alg.as_ref().is_some_and(|alg| alg != alg_matching[1]) {
886 return Err(Error::Data);
887 }
888 },
889 256 => {
891 if jwk.alg.as_ref().is_some_and(|alg| alg != alg_matching[2]) {
897 return Err(Error::Data);
898 }
899 },
900 _ => {
902 return Err(Error::Data);
904 },
905 }
906
907 if !usages.is_empty() && jwk.use_.as_ref().is_some_and(|use_| use_ != "enc") {
910 return Err(Error::Data);
911 }
912
913 jwk.check_key_ops(&usages)?;
917
918 if jwk.ext.is_some_and(|ext| !ext) && extractable {
921 return Err(Error::Data);
922 }
923 },
924 _ => {
926 return Err(Error::NotSupported);
928 },
929 };
930
931 let algorithm = SubtleAesKeyAlgorithm {
935 name: alg_name.to_string(),
936 length: (data.len() * 8) as u16,
937 };
938
939 let handle = match data.len() * 8 {
943 128 => Handle::Aes128(data.to_vec()),
944 192 => Handle::Aes192(data.to_vec()),
945 256 => Handle::Aes256(data.to_vec()),
946 _ => {
947 return Err(Error::Data);
948 },
949 };
950 let key = CryptoKey::new(
951 global,
952 KeyType::Secret,
953 extractable,
954 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm),
955 usages,
956 handle,
957 can_gc,
958 );
959
960 Ok(key)
962}
963
964fn export_key_aes(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
970 let result;
976 match format {
977 KeyFormat::Raw => match key.handle() {
979 Handle::Aes128(key_data) => {
983 result = ExportedKey::Raw(key_data.clone());
984 },
985 Handle::Aes192(key_data) => {
986 result = ExportedKey::Raw(key_data.clone());
987 },
988 Handle::Aes256(key_data) => {
989 result = ExportedKey::Raw(key_data.clone());
990 },
991 _ => unreachable!(),
992 },
993 KeyFormat::Jwk => {
995 let k = match key.handle() {
999 Handle::Aes128(key) => Base64UrlUnpadded::encode_string(key),
1000 Handle::Aes192(key) => Base64UrlUnpadded::encode_string(key),
1001 Handle::Aes256(key) => Base64UrlUnpadded::encode_string(key),
1002 _ => unreachable!(),
1003 };
1004
1005 let alg = match (key.handle(), key.algorithm().name()) {
1024 (Handle::Aes128(_), ALG_AES_CTR) => "A128CTR",
1025 (Handle::Aes192(_), ALG_AES_CTR) => "A192CTR",
1026 (Handle::Aes256(_), ALG_AES_CTR) => "A256CTR",
1027 (Handle::Aes128(_), ALG_AES_CBC) => "A128CBC",
1028 (Handle::Aes192(_), ALG_AES_CBC) => "A192CBC",
1029 (Handle::Aes256(_), ALG_AES_CBC) => "A256CBC",
1030 (Handle::Aes128(_), ALG_AES_GCM) => "A128GCM",
1031 (Handle::Aes192(_), ALG_AES_GCM) => "A192GCM",
1032 (Handle::Aes256(_), ALG_AES_GCM) => "A256GCM",
1033 (Handle::Aes128(_), ALG_AES_KW) => "A128KW",
1034 (Handle::Aes192(_), ALG_AES_KW) => "A192KW",
1035 (Handle::Aes256(_), ALG_AES_KW) => "A256KW",
1036 _ => unreachable!(),
1037 };
1038
1039 let key_ops = key
1041 .usages()
1042 .iter()
1043 .map(|usage| DOMString::from(usage.as_str()))
1044 .collect::<Vec<DOMString>>();
1045
1046 let jwk = JsonWebKey {
1050 kty: Some(DOMString::from("oct")),
1051 k: Some(DOMString::from(k)),
1052 alg: Some(DOMString::from(alg)),
1053 key_ops: Some(key_ops),
1054 ext: Some(key.Extractable()),
1055 ..Default::default()
1056 };
1057
1058 result = ExportedKey::Jwk(Box::new(jwk));
1060 },
1061 _ => {
1063 return Err(Error::NotSupported);
1065 },
1066 };
1067
1068 Ok(result)
1070}
1071
1072pub(crate) fn get_key_length_aes(
1078 normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
1079) -> Result<Option<u32>, Error> {
1080 if !matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256) {
1083 return Err(Error::Operation);
1084 }
1085
1086 Ok(Some(normalized_derived_key_algorithm.length as u32))
1088}