1mod aes_operation;
6mod ecdh_operation;
7mod ecdsa_operation;
8mod ed25519_operation;
9mod hkdf_operation;
10mod hmac_operation;
11mod pbkdf2_operation;
12mod sha_operation;
13mod x25519_operation;
14
15use std::ptr;
16use std::rc::Rc;
17use std::str::FromStr;
18
19use dom_struct::dom_struct;
20use js::conversions::ConversionResult;
21use js::jsapi::{Heap, JSObject};
22use js::jsval::{ObjectValue, UndefinedValue};
23use js::rust::wrappers::JS_ParseJSON;
24use js::rust::{HandleValue, MutableHandleValue};
25use js::typedarray::ArrayBufferU8;
26
27use crate::dom::bindings::buffer_source::create_buffer_source;
28use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
29 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
30};
31use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
32 AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
33 AesKeyGenParams, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EcKeyGenParams,
34 EcKeyImportParams, EcdhKeyDeriveParams, EcdsaParams, HkdfParams, HmacImportParams,
35 HmacKeyAlgorithm, HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params,
36 RsaOtherPrimesInfo, SubtleCryptoMethods,
37};
38use crate::dom::bindings::codegen::UnionTypes::{
39 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
40};
41use crate::dom::bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
42use crate::dom::bindings::error::{Error, Fallible};
43use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
44use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
45use crate::dom::bindings::root::DomRoot;
46use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
47use crate::dom::bindings::trace::RootedTraceableBox;
48use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
49use crate::dom::globalscope::GlobalScope;
50use crate::dom::promise::Promise;
51use crate::realms::InRealm;
52use crate::script_runtime::{CanGc, JSContext};
53
54const ALG_AES_CBC: &str = "AES-CBC";
56const ALG_AES_CTR: &str = "AES-CTR";
57const ALG_AES_GCM: &str = "AES-GCM";
58const ALG_AES_KW: &str = "AES-KW";
59const ALG_SHA1: &str = "SHA-1";
60const ALG_SHA256: &str = "SHA-256";
61const ALG_SHA384: &str = "SHA-384";
62const ALG_SHA512: &str = "SHA-512";
63const ALG_HMAC: &str = "HMAC";
64const ALG_HKDF: &str = "HKDF";
65const ALG_PBKDF2: &str = "PBKDF2";
66const ALG_RSASSA_PKCS1: &str = "RSASSA-PKCS1-v1_5";
67const ALG_RSA_OAEP: &str = "RSA-OAEP";
68const ALG_RSA_PSS: &str = "RSA-PSS";
69const ALG_ECDH: &str = "ECDH";
70const ALG_ECDSA: &str = "ECDSA";
71const ALG_ED25519: &str = "Ed25519";
72const ALG_X25519: &str = "X25519";
73
74static SUPPORTED_ALGORITHMS: &[&str] = &[
75 ALG_AES_CBC,
76 ALG_AES_CTR,
77 ALG_AES_GCM,
78 ALG_AES_KW,
79 ALG_SHA1,
80 ALG_SHA256,
81 ALG_SHA384,
82 ALG_SHA512,
83 ALG_HMAC,
84 ALG_HKDF,
85 ALG_PBKDF2,
86 ALG_RSASSA_PKCS1,
87 ALG_RSA_OAEP,
88 ALG_RSA_PSS,
89 ALG_ECDH,
90 ALG_ECDSA,
91 ALG_ED25519,
92 ALG_X25519,
93];
94
95const NAMED_CURVE_P256: &str = "P-256";
96const NAMED_CURVE_P384: &str = "P-384";
97const NAMED_CURVE_P521: &str = "P-521";
98
99static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
100
101#[expect(dead_code)]
103enum Operation {
104 Encrypt,
105 Decrypt,
106 Sign,
107 Verify,
108 Digest,
109 GenerateKey,
110 DeriveKey,
111 DeriveBits,
112 ImportKey,
113 ExportKey,
114 WrapKey,
115 UnwrapKey,
116 GetKeyLength,
117}
118
119#[dom_struct]
120pub(crate) struct SubtleCrypto {
121 reflector_: Reflector,
122}
123
124impl SubtleCrypto {
125 fn new_inherited() -> SubtleCrypto {
126 SubtleCrypto {
127 reflector_: Reflector::new(),
128 }
129 }
130
131 pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<SubtleCrypto> {
132 reflect_dom_object(Box::new(SubtleCrypto::new_inherited()), global, can_gc)
133 }
134
135 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
139 let trusted_promise = TrustedPromise::new(promise);
140 self.global().task_manager().crypto_task_source().queue(
141 task!(resolve_data: move || {
142 let promise = trusted_promise.root();
143
144 let cx = GlobalScope::get_cx();
145 rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
146 match create_buffer_source::<ArrayBufferU8>(cx, &data, array_buffer_ptr.handle_mut(), CanGc::note()) {
147 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
148 Err(_) => promise.reject_error(Error::JSFailed, CanGc::note()),
149 }
150 }),
151 );
152 }
153
154 fn resolve_promise_with_jwk(&self, promise: Rc<Promise>, jwk: Box<JsonWebKey>) {
158 let cx = GlobalScope::get_cx();
161 let stringified_jwk = match jwk.stringify(cx) {
162 Ok(stringified_jwk) => stringified_jwk.to_string(),
163 Err(error) => {
164 self.reject_promise_with_error(promise, error);
165 return;
166 },
167 };
168
169 let trusted_subtle = Trusted::new(self);
170 let trusted_promise = TrustedPromise::new(promise);
171 self.global()
172 .task_manager()
173 .crypto_task_source()
174 .queue(task!(resolve_jwk: move || {
175 let subtle = trusted_subtle.root();
176 let promise = trusted_promise.root();
177
178 let cx = GlobalScope::get_cx();
179 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
180 Ok(jwk) => {
181 rooted!(in(*cx) let mut rval = UndefinedValue());
182 jwk.safe_to_jsval(cx, rval.handle_mut(), CanGc::note());
183 rooted!(in(*cx) let mut object = rval.to_object());
184 promise.resolve_native(&*object, CanGc::note());
185 },
186 Err(error) => {
187 subtle.reject_promise_with_error(promise, error);
188 return;
189 },
190 }
191 }));
192 }
193
194 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
197 let trusted_key = Trusted::new(&*key);
198 let trusted_promise = TrustedPromise::new(promise);
199 self.global()
200 .task_manager()
201 .crypto_task_source()
202 .queue(task!(resolve_key: move || {
203 let key = trusted_key.root();
204 let promise = trusted_promise.root();
205 promise.resolve_native(&key, CanGc::note());
206 }));
207 }
208
209 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
212 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
213 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
214 let trusted_promise = TrustedPromise::new(promise);
215 self.global()
216 .task_manager()
217 .crypto_task_source()
218 .queue(task!(resolve_key: move || {
219 let key_pair = CryptoKeyPair {
220 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
221 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
222 };
223 let promise = trusted_promise.root();
224 promise.resolve_native(&key_pair, CanGc::note());
225 }));
226 }
227
228 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
231 let trusted_promise = TrustedPromise::new(promise);
232 self.global().task_manager().crypto_task_source().queue(
233 task!(generate_key_result: move || {
234 let promise = trusted_promise.root();
235 promise.resolve_native(&result, CanGc::note());
236 }),
237 );
238 }
239
240 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
243 let trusted_promise = TrustedPromise::new(promise);
244 self.global()
245 .task_manager()
246 .crypto_task_source()
247 .queue(task!(reject_error: move || {
248 let promise = trusted_promise.root();
249 promise.reject_error(error, CanGc::note());
250 }));
251 }
252}
253
254impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
255 fn Encrypt(
257 &self,
258 cx: JSContext,
259 algorithm: AlgorithmIdentifier,
260 key: &CryptoKey,
261 data: ArrayBufferViewOrArrayBuffer,
262 comp: InRealm,
263 can_gc: CanGc,
264 ) -> Rc<Promise> {
265 let data = match data {
272 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
273 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
274 };
275
276 let promise = Promise::new_in_current_realm(comp, can_gc);
280 let normalized_algorithm =
281 match normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc) {
282 Ok(normalized_algorithm) => normalized_algorithm,
283 Err(error) => {
284 promise.reject_error(error, can_gc);
285 return promise;
286 },
287 };
288
289 let this = Trusted::new(self);
295 let trusted_promise = TrustedPromise::new(promise.clone());
296 let trusted_key = Trusted::new(key);
297 self.global()
298 .task_manager()
299 .dom_manipulation_task_source()
300 .queue(task!(encrypt: move || {
301 let subtle = this.root();
302 let promise = trusted_promise.root();
303 let key = trusted_key.root();
304
305 if normalized_algorithm.name() != key.algorithm().name() {
313 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
314 return;
315 }
316
317 if !key.usages().contains(&KeyUsage::Encrypt) {
320 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
321 return;
322 }
323
324 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
328 Ok(ciphertext) => ciphertext,
329 Err(error) => {
330 subtle.reject_promise_with_error(promise, error);
331 return;
332 },
333 };
334
335 subtle.resolve_promise_with_data(promise, ciphertext);
341 }));
342 promise
343 }
344
345 fn Decrypt(
347 &self,
348 cx: JSContext,
349 algorithm: AlgorithmIdentifier,
350 key: &CryptoKey,
351 data: ArrayBufferViewOrArrayBuffer,
352 comp: InRealm,
353 can_gc: CanGc,
354 ) -> Rc<Promise> {
355 let data = match data {
362 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
363 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
364 };
365
366 let promise = Promise::new_in_current_realm(comp, can_gc);
370 let normalized_algorithm =
371 match normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc) {
372 Ok(normalized_algorithm) => normalized_algorithm,
373 Err(error) => {
374 promise.reject_error(error, can_gc);
375 return promise;
376 },
377 };
378
379 let this = Trusted::new(self);
385 let trusted_promise = TrustedPromise::new(promise.clone());
386 let trusted_key = Trusted::new(key);
387 self.global()
388 .task_manager()
389 .dom_manipulation_task_source()
390 .queue(task!(decrypt: move || {
391 let subtle = this.root();
392 let promise = trusted_promise.root();
393 let key = trusted_key.root();
394
395 if normalized_algorithm.name() != key.algorithm().name() {
403 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
404 return;
405 }
406
407 if !key.usages().contains(&KeyUsage::Decrypt) {
410 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
411 return;
412 }
413
414 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
418 Ok(plaintext) => plaintext,
419 Err(error) => {
420 subtle.reject_promise_with_error(promise, error);
421 return;
422 },
423 };
424
425 subtle.resolve_promise_with_data(promise, plaintext);
431 }));
432 promise
433 }
434
435 fn Sign(
437 &self,
438 cx: JSContext,
439 algorithm: AlgorithmIdentifier,
440 key: &CryptoKey,
441 data: ArrayBufferViewOrArrayBuffer,
442 comp: InRealm,
443 can_gc: CanGc,
444 ) -> Rc<Promise> {
445 let data = match &data {
452 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
453 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
454 };
455
456 let promise = Promise::new_in_current_realm(comp, can_gc);
460 let normalized_algorithm =
461 match normalize_algorithm(cx, &Operation::Sign, &algorithm, can_gc) {
462 Ok(normalized_algorithm) => normalized_algorithm,
463 Err(error) => {
464 promise.reject_error(error, can_gc);
465 return promise;
466 },
467 };
468
469 let this = Trusted::new(self);
475 let trusted_promise = TrustedPromise::new(promise.clone());
476 let trusted_key = Trusted::new(key);
477 self.global()
478 .task_manager()
479 .dom_manipulation_task_source()
480 .queue(task!(sign: move || {
481 let subtle = this.root();
482 let promise = trusted_promise.root();
483 let key = trusted_key.root();
484
485 if normalized_algorithm.name() != key.algorithm().name() {
493 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
494 return;
495 }
496
497 if !key.usages().contains(&KeyUsage::Sign) {
500 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
501 return;
502 }
503
504 let signature = match normalized_algorithm.sign(&key, &data) {
507 Ok(signature) => signature,
508 Err(error) => {
509 subtle.reject_promise_with_error(promise, error);
510 return;
511 },
512 };
513
514 subtle.resolve_promise_with_data(promise, signature);
520 }));
521 promise
522 }
523
524 fn Verify(
526 &self,
527 cx: JSContext,
528 algorithm: AlgorithmIdentifier,
529 key: &CryptoKey,
530 signature: ArrayBufferViewOrArrayBuffer,
531 data: ArrayBufferViewOrArrayBuffer,
532 comp: InRealm,
533 can_gc: CanGc,
534 ) -> Rc<Promise> {
535 let signature = match &signature {
542 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
543 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
544 };
545
546 let data = match &data {
549 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
550 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
551 };
552
553 let promise = Promise::new_in_current_realm(comp, can_gc);
557 let normalized_algorithm =
558 match normalize_algorithm(cx, &Operation::Verify, &algorithm, can_gc) {
559 Ok(algorithm) => algorithm,
560 Err(error) => {
561 promise.reject_error(error, can_gc);
562 return promise;
563 },
564 };
565
566 let this = Trusted::new(self);
572 let trusted_promise = TrustedPromise::new(promise.clone());
573 let trusted_key = Trusted::new(key);
574 self.global()
575 .task_manager()
576 .dom_manipulation_task_source()
577 .queue(task!(sign: move || {
578 let subtle = this.root();
579 let promise = trusted_promise.root();
580 let key = trusted_key.root();
581
582 if normalized_algorithm.name() != key.algorithm().name() {
590 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
591 return;
592 }
593
594 if !key.usages().contains(&KeyUsage::Verify) {
597 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
598 return;
599 }
600
601 let result = match normalized_algorithm.verify(&key, &data, &signature) {
605 Ok(result) => result,
606 Err(error) => {
607 subtle.reject_promise_with_error(promise, error);
608 return;
609 },
610 };
611
612 subtle.resolve_promise_with_bool(promise, result);
616 }));
617 promise
618 }
619
620 fn Digest(
622 &self,
623 cx: JSContext,
624 algorithm: AlgorithmIdentifier,
625 data: ArrayBufferViewOrArrayBuffer,
626 comp: InRealm,
627 can_gc: CanGc,
628 ) -> Rc<Promise> {
629 let data = match data {
635 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
636 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
637 };
638
639 let promise = Promise::new_in_current_realm(comp, can_gc);
643 let normalized_algorithm =
644 match normalize_algorithm(cx, &Operation::Digest, &algorithm, can_gc) {
645 Ok(normalized_algorithm) => normalized_algorithm,
646 Err(error) => {
647 promise.reject_error(error, can_gc);
648 return promise;
649 },
650 };
651
652 let this = Trusted::new(self);
658 let trusted_promise = TrustedPromise::new(promise.clone());
659 self.global()
660 .task_manager()
661 .dom_manipulation_task_source()
662 .queue(task!(generate_key: move || {
663 let subtle = this.root();
664 let promise = trusted_promise.root();
665
666 let digest = match normalized_algorithm.digest(&data) {
673 Ok(digest) => digest,
674 Err(error) => {
675 subtle.reject_promise_with_error(promise, error);
676 return;
677 }
678 };
679
680 subtle.resolve_promise_with_data(promise, digest);
686 }));
687 promise
688 }
689
690 fn GenerateKey(
692 &self,
693 cx: JSContext,
694 algorithm: AlgorithmIdentifier,
695 extractable: bool,
696 key_usages: Vec<KeyUsage>,
697 comp: InRealm,
698 can_gc: CanGc,
699 ) -> Rc<Promise> {
700 let promise = Promise::new_in_current_realm(comp, can_gc);
707 let normalized_algorithm =
708 match normalize_algorithm(cx, &Operation::GenerateKey, &algorithm, can_gc) {
709 Ok(normalized_algorithm) => normalized_algorithm,
710 Err(error) => {
711 promise.reject_error(error, can_gc);
712 return promise;
713 },
714 };
715
716 let trusted_subtle = Trusted::new(self);
722 let trusted_promise = TrustedPromise::new(promise.clone());
723 self.global()
724 .task_manager()
725 .dom_manipulation_task_source()
726 .queue(task!(generate_key: move || {
727 let subtle = trusted_subtle.root();
728 let promise = trusted_promise.root();
729
730 let result = match normalized_algorithm.generate_key(
737 &subtle.global(),
738 extractable,
739 key_usages,
740 CanGc::note(),
741 ) {
742 Ok(result) => result,
743 Err(error) => {
744 subtle.reject_promise_with_error(promise, error);
745 return;
746 }
747 };
748
749 match &result {
758 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
759 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
760 && crpyto_key.usages().is_empty()
761 {
762 subtle.reject_promise_with_error(promise, Error::Syntax(None));
763 return;
764 }
765 },
766 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
767 if crypto_key_pair.privateKey.as_ref().is_none_or(|private_key| private_key.usages().is_empty()) {
768 subtle.reject_promise_with_error(promise, Error::Syntax(None));
769 return;
770 }
771 }
772 };
773
774 match result {
780 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
781 subtle.resolve_promise_with_key(promise, key);
782 },
783 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
784 subtle.resolve_promise_with_key_pair(promise, key_pair);
785 },
786 }
787 }));
788
789 promise
790 }
791
792 fn DeriveKey(
794 &self,
795 cx: JSContext,
796 algorithm: AlgorithmIdentifier,
797 base_key: &CryptoKey,
798 derived_key_type: AlgorithmIdentifier,
799 extractable: bool,
800 usages: Vec<KeyUsage>,
801 comp: InRealm,
802 can_gc: CanGc,
803 ) -> Rc<Promise> {
804 let promise = Promise::new_in_current_realm(comp, can_gc);
813 let normalized_algorithm =
814 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
815 Ok(normalized_algorithm) => normalized_algorithm,
816 Err(error) => {
817 promise.reject_error(error, can_gc);
818 return promise;
819 },
820 };
821
822 let normalized_derived_key_algorithm_import =
827 match normalize_algorithm(cx, &Operation::ImportKey, &derived_key_type, can_gc) {
828 Ok(normalized_algorithm) => normalized_algorithm,
829 Err(error) => {
830 promise.reject_error(error, can_gc);
831 return promise;
832 },
833 };
834
835 let normalized_derived_key_algorithm_length =
840 match normalize_algorithm(cx, &Operation::GetKeyLength, &derived_key_type, can_gc) {
841 Ok(normalized_algorithm) => normalized_algorithm,
842 Err(error) => {
843 promise.reject_error(error, can_gc);
844 return promise;
845 },
846 };
847
848 let trusted_subtle = Trusted::new(self);
854 let trusted_base_key = Trusted::new(base_key);
855 let trusted_promise = TrustedPromise::new(promise.clone());
856 self.global().task_manager().dom_manipulation_task_source().queue(
857 task!(derive_key: move || {
858 let subtle = trusted_subtle.root();
859 let base_key = trusted_base_key.root();
860 let promise = trusted_promise.root();
861
862 if normalized_algorithm.name() != base_key.algorithm().name() {
870 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
871 return;
872 }
873
874 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
877 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
878 return;
879 }
880
881 let length = match normalized_derived_key_algorithm_length.get_key_length() {
884 Ok(length) => length,
885 Err(error) => {
886 subtle.reject_promise_with_error(promise, error);
887 return;
888 }
889 };
890
891 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
894 Ok(secret) => secret,
895 Err(error) => {
896 subtle.reject_promise_with_error(promise, error);
897 return;
898 }
899 };
900
901 let result = match normalized_derived_key_algorithm_import.import_key(
905 &subtle.global(),
906 KeyFormat::Raw,
907 &secret,
908 extractable,
909 usages.clone(),
910 CanGc::note(),
911 ) {
912 Ok(algorithm) => algorithm,
913 Err(error) => {
914 subtle.reject_promise_with_error(promise, error);
915 return;
916 },
917 };
918
919 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
922 subtle.reject_promise_with_error(promise, Error::Syntax(None));
923 return;
924 }
925
926 subtle.resolve_promise_with_key(promise, result);
937 }),
938 );
939 promise
940 }
941
942 fn DeriveBits(
944 &self,
945 cx: JSContext,
946 algorithm: AlgorithmIdentifier,
947 base_key: &CryptoKey,
948 length: Option<u32>,
949 comp: InRealm,
950 can_gc: CanGc,
951 ) -> Rc<Promise> {
952 let promise = Promise::new_in_current_realm(comp, can_gc);
960 let normalized_algorithm =
961 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
962 Ok(normalized_algorithm) => normalized_algorithm,
963 Err(error) => {
964 promise.reject_error(error, can_gc);
965 return promise;
966 },
967 };
968
969 let trsuted_subtle = Trusted::new(self);
975 let trusted_base_key = Trusted::new(base_key);
976 let trusted_promise = TrustedPromise::new(promise.clone());
977 self.global()
978 .task_manager()
979 .dom_manipulation_task_source()
980 .queue(task!(import_key: move || {
981 let subtle = trsuted_subtle.root();
982 let base_key = trusted_base_key.root();
983 let promise = trusted_promise.root();
984
985 if normalized_algorithm.name() != base_key.algorithm().name() {
993 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
994 return;
995 }
996
997 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1000 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1001 return;
1002 }
1003
1004 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1007 Ok(bits) => bits,
1008 Err(error) => {
1009 subtle.reject_promise_with_error(promise, error);
1010 return;
1011 }
1012 };
1013
1014 subtle.resolve_promise_with_data(promise, bits);
1020 }));
1021 promise
1022 }
1023
1024 fn ImportKey(
1026 &self,
1027 cx: JSContext,
1028 format: KeyFormat,
1029 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1030 algorithm: AlgorithmIdentifier,
1031 extractable: bool,
1032 key_usages: Vec<KeyUsage>,
1033 comp: InRealm,
1034 can_gc: CanGc,
1035 ) -> Rc<Promise> {
1036 let promise = Promise::new_in_current_realm(comp, can_gc);
1042
1043 let key_data = match format {
1045 KeyFormat::Raw | KeyFormat::Pkcs8 | KeyFormat::Spki => {
1047 match key_data {
1048 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1051 promise.reject_error(
1052 Error::Type("The keyData type does not match the format".to_string()),
1053 can_gc,
1054 );
1055 return promise;
1056 },
1057
1058 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1061 view.to_vec()
1062 },
1063 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1064 buffer.to_vec()
1065 },
1066 }
1067 },
1068 KeyFormat::Jwk => {
1070 match key_data {
1071 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1072 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1073 promise.reject_error(
1076 Error::Type("The keyData type does not match the format".to_string()),
1077 can_gc,
1078 );
1079 return promise;
1080 },
1081
1082 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1083 match jwk.stringify(cx) {
1090 Ok(stringified) => stringified.as_bytes().to_vec(),
1091 Err(error) => {
1092 promise.reject_error(error, can_gc);
1093 return promise;
1094 },
1095 }
1096 },
1097 }
1098 },
1099 };
1100
1101 let normalized_algorithm =
1105 match normalize_algorithm(cx, &Operation::ImportKey, &algorithm, can_gc) {
1106 Ok(algorithm) => algorithm,
1107 Err(error) => {
1108 promise.reject_error(error, can_gc);
1109 return promise;
1110 },
1111 };
1112
1113 let this = Trusted::new(self);
1115 let trusted_promise = TrustedPromise::new(promise.clone());
1116 self.global()
1117 .task_manager()
1118 .dom_manipulation_task_source()
1119 .queue(task!(import_key: move || {
1120 let subtle = this.root();
1121 let promise = trusted_promise.root();
1122
1123 let result = match normalized_algorithm.import_key(
1131 &subtle.global(),
1132 format,
1133 &key_data,
1134 extractable,
1135 key_usages.clone(),
1136 CanGc::note()
1137 ) {
1138 Ok(key) => key,
1139 Err(error) => {
1140 subtle.reject_promise_with_error(promise, error);
1141 return;
1142 },
1143 };
1144
1145 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1148 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1149 return;
1150 }
1151
1152 result.set_extractable(extractable);
1154
1155 result.set_usages(&key_usages);
1157
1158 subtle.resolve_promise_with_key(promise, result);
1164 }));
1165
1166 promise
1167 }
1168
1169 fn ExportKey(
1171 &self,
1172 format: KeyFormat,
1173 key: &CryptoKey,
1174 comp: InRealm,
1175 can_gc: CanGc,
1176 ) -> Rc<Promise> {
1177 let promise = Promise::new_in_current_realm(comp, can_gc);
1184
1185 let trusted_subtle = Trusted::new(self);
1187 let trusted_promise = TrustedPromise::new(promise.clone());
1188 let trusted_key = Trusted::new(key);
1189 self.global()
1190 .task_manager()
1191 .dom_manipulation_task_source()
1192 .queue(task!(export_key: move || {
1193 let subtle = trusted_subtle.root();
1194 let promise = trusted_promise.root();
1195 let key = trusted_key.root();
1196
1197 if matches!(
1205 key.algorithm().name(),
1206 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1207 ) {
1208 subtle.reject_promise_with_error(promise, Error::NotSupported);
1209 return;
1210 }
1211
1212 if !key.Extractable() {
1215 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1216 return;
1217 }
1218
1219 let result = match perform_export_key_operation(format, &key) {
1222 Ok(exported_key) => exported_key,
1223 Err(error) => {
1224 subtle.reject_promise_with_error(promise, error);
1225 return;
1226 },
1227 };
1228
1229 match result {
1240 ExportedKey::Raw(raw) => {
1241 subtle.resolve_promise_with_data(promise, raw);
1242 },
1243 ExportedKey::Jwk(jwk) => {
1244 subtle.resolve_promise_with_jwk(promise, jwk);
1245 },
1246 }
1247 }));
1248 promise
1249 }
1250
1251 fn WrapKey(
1253 &self,
1254 cx: JSContext,
1255 format: KeyFormat,
1256 key: &CryptoKey,
1257 wrapping_key: &CryptoKey,
1258 algorithm: AlgorithmIdentifier,
1259 comp: InRealm,
1260 can_gc: CanGc,
1261 ) -> Rc<Promise> {
1262 let mut normalized_algorithm_result =
1269 normalize_algorithm(cx, &Operation::WrapKey, &algorithm, can_gc);
1270
1271 if normalized_algorithm_result.is_err() {
1274 normalized_algorithm_result =
1275 normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc);
1276 }
1277
1278 let promise = Promise::new_in_current_realm(comp, can_gc);
1280 let normalized_algorithm = match normalized_algorithm_result {
1281 Ok(normalized_algorithm) => normalized_algorithm,
1282 Err(error) => {
1283 promise.reject_error(error, can_gc);
1284 return promise;
1285 },
1286 };
1287
1288 let trusted_subtle = Trusted::new(self);
1294 let trusted_key = Trusted::new(key);
1295 let trusted_wrapping_key = Trusted::new(wrapping_key);
1296 let trusted_promise = TrustedPromise::new(promise.clone());
1297 self.global()
1298 .task_manager()
1299 .dom_manipulation_task_source()
1300 .queue(task!(wrap_key: move || {
1301 let subtle = trusted_subtle.root();
1302 let key = trusted_key.root();
1303 let wrapping_key = trusted_wrapping_key.root();
1304 let promise = trusted_promise.root();
1305
1306 if normalized_algorithm.name() != wrapping_key.algorithm().name() {
1314 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1315 return;
1316 }
1317
1318 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1321 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1322 return;
1323 }
1324
1325 if matches!(
1329 key.algorithm().name(),
1330 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1331 ) {
1332 subtle.reject_promise_with_error(promise, Error::NotSupported);
1333 return;
1334 }
1335
1336
1337 if !key.Extractable() {
1340 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1341 return;
1342 }
1343
1344 let exported_key = match perform_export_key_operation(format, &key) {
1347 Ok(exported_key) => exported_key,
1348 Err(error) => {
1349 subtle.reject_promise_with_error(promise, error);
1350 return;
1351 },
1352 };
1353
1354 let cx = GlobalScope::get_cx();
1364 let bytes = match exported_key {
1365 ExportedKey::Raw(raw) => raw,
1366 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1367 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1368 Err(error) => {
1369 subtle.reject_promise_with_error(promise, error);
1370 return;
1371 },
1372 },
1373 };
1374
1375 let mut result = normalized_algorithm.wrap_key(&wrapping_key, &bytes);
1387 if result.is_err() {
1388 result = normalized_algorithm.encrypt(&wrapping_key, &bytes);
1389 }
1390 let result = match result {
1391 Ok(result) => result,
1392 Err(error) => {
1393 subtle.reject_promise_with_error(promise, error);
1394 return;
1395 },
1396 };
1397
1398 subtle.resolve_promise_with_data(promise, result);
1404 }));
1405 promise
1406 }
1407
1408 fn UnwrapKey(
1410 &self,
1411 cx: JSContext,
1412 format: KeyFormat,
1413 wrapped_key: ArrayBufferViewOrArrayBuffer,
1414 unwrapping_key: &CryptoKey,
1415 algorithm: AlgorithmIdentifier,
1416 unwrapped_key_algorithm: AlgorithmIdentifier,
1417 extractable: bool,
1418 usages: Vec<KeyUsage>,
1419 comp: InRealm,
1420 can_gc: CanGc,
1421 ) -> Rc<Promise> {
1422 let wrapped_key = match wrapped_key {
1430 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1431 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1432 };
1433
1434 let mut normalized_algorithm =
1437 normalize_algorithm(cx, &Operation::UnwrapKey, &algorithm, can_gc);
1438
1439 if normalized_algorithm.is_err() {
1442 normalized_algorithm = normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc);
1443 }
1444
1445 let promise = Promise::new_in_current_realm(comp, can_gc);
1447 let normalized_algorithm = match normalized_algorithm {
1448 Ok(algorithm) => algorithm,
1449 Err(error) => {
1450 promise.reject_error(error, can_gc);
1451 return promise;
1452 },
1453 };
1454
1455 let normalized_key_algorithm = match normalize_algorithm(
1459 cx,
1460 &Operation::ImportKey,
1461 &unwrapped_key_algorithm,
1462 can_gc,
1463 ) {
1464 Ok(algorithm) => algorithm,
1465 Err(error) => {
1466 promise.reject_error(error, can_gc);
1467 return promise;
1468 },
1469 };
1470
1471 let trusted_subtle = Trusted::new(self);
1477 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1478 let trusted_promise = TrustedPromise::new(promise.clone());
1479 self.global().task_manager().dom_manipulation_task_source().queue(
1480 task!(unwrap_key: move || {
1481 let subtle = trusted_subtle.root();
1482 let unwrapping_key = trusted_unwrapping_key.root();
1483 let promise = trusted_promise.root();
1484
1485 if normalized_algorithm.name() != unwrapping_key.algorithm().name() {
1493 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1494 return;
1495 }
1496
1497 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1500 subtle.reject_promise_with_error(promise, Error::InvalidAccess);
1501 return;
1502 }
1503
1504 let mut bytes = normalized_algorithm.unwrap_key(&unwrapping_key, &wrapped_key);
1516 if bytes.is_err() {
1517 bytes = normalized_algorithm.decrypt(&unwrapping_key, &wrapped_key);
1518 }
1519 let bytes = match bytes {
1520 Ok(bytes) => bytes,
1521 Err(error) => {
1522 subtle.reject_promise_with_error(promise, error);
1523 return;
1524 },
1525 };
1526
1527 let cx = GlobalScope::get_cx();
1537 if format == KeyFormat::Jwk {
1538 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1539 subtle.reject_promise_with_error(promise, error);
1540 return;
1541 }
1542 }
1543 let key = bytes;
1544
1545 let result = match normalized_key_algorithm.import_key(
1549 &subtle.global(),
1550 format,
1551 &key,
1552 extractable,
1553 usages.clone(),
1554 CanGc::note(),
1555 ) {
1556 Ok(result) => result,
1557 Err(error) => {
1558 subtle.reject_promise_with_error(promise, error);
1559 return;
1560 },
1561 };
1562
1563 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1566 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1567 return;
1568 }
1569
1570 subtle.resolve_promise_with_key(promise, result);
1581 }),
1582 );
1583 promise
1584 }
1585}
1586
1587#[derive(Clone, Debug, MallocSizeOf)]
1592struct SubtleAlgorithm {
1593 name: String,
1595}
1596
1597impl From<Algorithm> for SubtleAlgorithm {
1598 fn from(params: Algorithm) -> Self {
1599 SubtleAlgorithm {
1600 name: params.name.to_string(),
1601 }
1602 }
1603}
1604
1605#[derive(Clone, Debug, MallocSizeOf)]
1607pub(crate) struct SubtleKeyAlgorithm {
1608 name: String,
1610}
1611
1612impl SubtleKeyAlgorithm {
1613 fn block_size_in_bits(&self) -> Result<u32, Error> {
1614 let size = match self.name.as_str() {
1615 ALG_SHA1 => 512,
1616 ALG_SHA256 => 512,
1617 ALG_SHA384 => 1024,
1618 ALG_SHA512 => 1024,
1619 _ => {
1620 return Err(Error::NotSupported);
1621 },
1622 };
1623
1624 Ok(size)
1625 }
1626}
1627
1628impl From<NormalizedAlgorithm> for SubtleKeyAlgorithm {
1629 fn from(value: NormalizedAlgorithm) -> Self {
1630 SubtleKeyAlgorithm {
1631 name: value.name().to_string(),
1632 }
1633 }
1634}
1635
1636impl SafeToJSValConvertible for SubtleKeyAlgorithm {
1637 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1638 let dictionary = KeyAlgorithm {
1639 name: self.name.clone().into(),
1640 };
1641 dictionary.safe_to_jsval(cx, rval, can_gc);
1642 }
1643}
1644
1645#[derive(Clone, Debug, MallocSizeOf)]
1647struct SubtleEcdsaParams {
1648 name: String,
1650
1651 hash: SubtleKeyAlgorithm,
1653}
1654
1655impl TryFrom<RootedTraceableBox<EcdsaParams>> for SubtleEcdsaParams {
1656 type Error = Error;
1657
1658 fn try_from(value: RootedTraceableBox<EcdsaParams>) -> Result<Self, Error> {
1659 let cx = GlobalScope::get_cx();
1660 let hash = normalize_algorithm(cx, &Operation::Digest, &value.hash, CanGc::note())?;
1661 Ok(SubtleEcdsaParams {
1662 name: value.parent.name.to_string(),
1663 hash: hash.into(),
1664 })
1665 }
1666}
1667
1668#[derive(Clone, Debug, MallocSizeOf)]
1670struct SubtleEcKeyGenParams {
1671 name: String,
1673
1674 named_curve: String,
1676}
1677
1678impl From<EcKeyGenParams> for SubtleEcKeyGenParams {
1679 fn from(value: EcKeyGenParams) -> Self {
1680 SubtleEcKeyGenParams {
1681 name: value.parent.name.to_string(),
1682 named_curve: value.namedCurve.to_string(),
1683 }
1684 }
1685}
1686
1687#[derive(Clone, Debug, MallocSizeOf)]
1689pub(crate) struct SubtleEcKeyAlgorithm {
1690 name: String,
1692
1693 named_curve: String,
1695}
1696
1697impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
1698 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1699 let parent = KeyAlgorithm {
1700 name: self.name.clone().into(),
1701 };
1702 let dictionary = EcKeyAlgorithm {
1703 parent,
1704 namedCurve: self.named_curve.clone().into(),
1705 };
1706 dictionary.safe_to_jsval(cx, rval, can_gc);
1707 }
1708}
1709
1710#[derive(Clone, Debug, MallocSizeOf)]
1712struct SubtleEcKeyImportParams {
1713 name: String,
1715
1716 named_curve: String,
1718}
1719
1720impl From<EcKeyImportParams> for SubtleEcKeyImportParams {
1721 fn from(value: EcKeyImportParams) -> Self {
1722 SubtleEcKeyImportParams {
1723 name: value.parent.name.to_string(),
1724 named_curve: value.namedCurve.to_string(),
1725 }
1726 }
1727}
1728
1729#[derive(Clone, MallocSizeOf)]
1731struct SubtleEcdhKeyDeriveParams {
1732 name: String,
1734
1735 public: Trusted<CryptoKey>,
1737}
1738
1739impl From<EcdhKeyDeriveParams> for SubtleEcdhKeyDeriveParams {
1740 fn from(value: EcdhKeyDeriveParams) -> Self {
1741 SubtleEcdhKeyDeriveParams {
1742 name: value.parent.name.to_string(),
1743 public: Trusted::new(&value.public),
1744 }
1745 }
1746}
1747
1748#[derive(Clone, Debug, MallocSizeOf)]
1749pub(crate) struct SubtleAesCbcParams {
1750 pub(crate) name: String,
1751 pub(crate) iv: Vec<u8>,
1752}
1753
1754impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
1755 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
1756 let iv = match ¶ms.iv {
1757 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1758 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1759 };
1760 SubtleAesCbcParams {
1761 name: params.parent.name.to_string(),
1762 iv,
1763 }
1764 }
1765}
1766
1767#[derive(Clone, Debug, MallocSizeOf)]
1768pub(crate) struct SubtleAesCtrParams {
1769 pub(crate) name: String,
1770 pub(crate) counter: Vec<u8>,
1771 pub(crate) length: u8,
1772}
1773
1774impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
1775 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
1776 let counter = match ¶ms.counter {
1777 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1778 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1779 };
1780 SubtleAesCtrParams {
1781 name: params.parent.name.to_string(),
1782 counter,
1783 length: params.length,
1784 }
1785 }
1786}
1787
1788#[derive(Clone, Debug, MallocSizeOf)]
1789pub(crate) struct SubtleAesGcmParams {
1790 pub(crate) name: String,
1791 pub(crate) iv: Vec<u8>,
1792 pub(crate) additional_data: Option<Vec<u8>>,
1793 pub(crate) tag_length: Option<u8>,
1794}
1795
1796impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
1797 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
1798 let iv = match ¶ms.iv {
1799 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1800 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1801 };
1802 let additional_data = params.additionalData.as_ref().map(|data| match data {
1803 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1804 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1805 });
1806
1807 SubtleAesGcmParams {
1808 name: params.parent.name.to_string(),
1809 iv,
1810 additional_data,
1811 tag_length: params.tagLength,
1812 }
1813 }
1814}
1815
1816#[derive(Clone, Debug, MallocSizeOf)]
1818pub(crate) struct SubtleAesKeyAlgorithm {
1819 name: String,
1821
1822 length: u16,
1824}
1825
1826impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
1827 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1828 let parent = KeyAlgorithm {
1829 name: self.name.clone().into(),
1830 };
1831 let dictionary = AesKeyAlgorithm {
1832 parent,
1833 length: self.length,
1834 };
1835 dictionary.safe_to_jsval(cx, rval, can_gc);
1836 }
1837}
1838
1839#[derive(Clone, Debug, MallocSizeOf)]
1841struct SubtleAesKeyGenParams {
1842 name: String,
1844
1845 length: u16,
1847}
1848
1849impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
1850 fn from(params: AesKeyGenParams) -> Self {
1851 SubtleAesKeyGenParams {
1852 name: params.parent.name.to_string(),
1853 length: params.length,
1854 }
1855 }
1856}
1857
1858#[derive(Clone, Debug, MallocSizeOf)]
1860struct SubtleAesDerivedKeyParams {
1861 name: String,
1863
1864 length: u16,
1866}
1867
1868impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
1869 fn from(params: AesDerivedKeyParams) -> Self {
1870 SubtleAesDerivedKeyParams {
1871 name: params.parent.name.to_string(),
1872 length: params.length,
1873 }
1874 }
1875}
1876
1877#[derive(Clone, Debug, MallocSizeOf)]
1879struct SubtleHmacImportParams {
1880 name: String,
1882
1883 hash: SubtleKeyAlgorithm,
1885
1886 length: Option<u32>,
1888}
1889
1890impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
1891 type Error = Error;
1892
1893 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
1894 let cx = GlobalScope::get_cx();
1895 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1896 Ok(SubtleHmacImportParams {
1897 name: params.parent.name.to_string(),
1898 hash: hash.into(),
1899 length: params.length,
1900 })
1901 }
1902}
1903
1904#[derive(Clone, Debug, MallocSizeOf)]
1906pub(crate) struct SubtleHmacKeyAlgorithm {
1907 name: String,
1909
1910 hash: SubtleKeyAlgorithm,
1912
1913 length: u32,
1915}
1916
1917impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
1918 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1919 let parent = KeyAlgorithm {
1920 name: self.name.clone().into(),
1921 };
1922 let hash = KeyAlgorithm {
1923 name: self.hash.name.clone().into(),
1924 };
1925 let dictionary = HmacKeyAlgorithm {
1926 parent,
1927 hash,
1928 length: self.length,
1929 };
1930 dictionary.safe_to_jsval(cx, rval, can_gc);
1931 }
1932}
1933
1934#[derive(Clone, Debug, MallocSizeOf)]
1936struct SubtleHmacKeyGenParams {
1937 name: String,
1939
1940 hash: SubtleKeyAlgorithm,
1942
1943 length: Option<u32>,
1945}
1946
1947impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
1948 type Error = Error;
1949
1950 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
1951 let cx = GlobalScope::get_cx();
1952 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1953 Ok(SubtleHmacKeyGenParams {
1954 name: params.parent.name.to_string(),
1955 hash: hash.into(),
1956 length: params.length,
1957 })
1958 }
1959}
1960
1961#[derive(Clone, Debug, MallocSizeOf)]
1963pub(crate) struct SubtleHkdfParams {
1964 name: String,
1966
1967 hash: SubtleKeyAlgorithm,
1969
1970 salt: Vec<u8>,
1972
1973 info: Vec<u8>,
1975}
1976
1977impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
1978 type Error = Error;
1979
1980 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
1981 let cx = GlobalScope::get_cx();
1982 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1983 let salt = match ¶ms.salt {
1984 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1985 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1986 };
1987 let info = match ¶ms.info {
1988 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1989 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1990 };
1991 Ok(SubtleHkdfParams {
1992 name: params.parent.name.to_string(),
1993 hash: hash.into(),
1994 salt,
1995 info,
1996 })
1997 }
1998}
1999
2000#[derive(Clone, Debug, MallocSizeOf)]
2002pub(crate) struct SubtlePbkdf2Params {
2003 name: String,
2005
2006 salt: Vec<u8>,
2008
2009 iterations: u32,
2011
2012 hash: SubtleKeyAlgorithm,
2014}
2015
2016impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
2017 type Error = Error;
2018
2019 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
2020 let cx = GlobalScope::get_cx();
2021 let salt = match ¶ms.salt {
2022 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2023 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2024 };
2025 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
2026 Ok(SubtlePbkdf2Params {
2027 name: params.parent.name.to_string(),
2028 salt,
2029 iterations: params.iterations,
2030 hash: hash.into(),
2031 })
2032 }
2033}
2034
2035fn dictionary_from_jsval<T>(cx: JSContext, value: HandleValue, can_gc: CanGc) -> Fallible<T>
2037where
2038 T: SafeFromJSValConvertible<Config = ()>,
2039{
2040 let conversion = T::safe_from_jsval(cx, value, (), can_gc).map_err(|_| Error::JSFailed)?;
2041 match conversion {
2042 ConversionResult::Success(dictionary) => Ok(dictionary),
2043 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
2044 }
2045}
2046
2047pub(crate) enum ExportedKey {
2048 Raw(Vec<u8>),
2049 Jwk(Box<JsonWebKey>),
2050}
2051
2052#[derive(Clone, Debug, MallocSizeOf)]
2056#[expect(clippy::enum_variant_names)]
2057pub(crate) enum KeyAlgorithmAndDerivatives {
2058 KeyAlgorithm(SubtleKeyAlgorithm),
2059 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
2060 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
2061 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
2062}
2063
2064impl KeyAlgorithmAndDerivatives {
2065 fn name(&self) -> &str {
2066 match self {
2067 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
2068 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => &algo.name,
2069 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
2070 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
2071 }
2072 }
2073}
2074
2075impl From<NormalizedAlgorithm> for KeyAlgorithmAndDerivatives {
2076 fn from(value: NormalizedAlgorithm) -> Self {
2077 KeyAlgorithmAndDerivatives::KeyAlgorithm(SubtleKeyAlgorithm {
2078 name: value.name().to_string(),
2079 })
2080 }
2081}
2082
2083impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
2084 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2085 match self {
2086 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
2087 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
2088 algo.safe_to_jsval(cx, rval, can_gc)
2089 },
2090 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
2091 algo.safe_to_jsval(cx, rval, can_gc)
2092 },
2093 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
2094 algo.safe_to_jsval(cx, rval, can_gc)
2095 },
2096 }
2097 }
2098}
2099
2100#[expect(unused)]
2101trait RsaOtherPrimesInfoExt {
2102 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error>;
2103}
2104
2105impl RsaOtherPrimesInfoExt for RsaOtherPrimesInfo {
2106 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error> {
2107 let serde_json::Value::Object(object) = value else {
2108 return Err(Error::Data);
2109 };
2110
2111 let mut rsa_other_primes_info: RsaOtherPrimesInfo = Default::default();
2112 for (key, value) in object {
2113 match key.as_str() {
2114 "r" => {
2115 rsa_other_primes_info.r =
2116 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2117 },
2118 "d" => {
2119 rsa_other_primes_info.d =
2120 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2121 },
2122 "t" => {
2123 rsa_other_primes_info.t =
2124 Some(DOMString::from(value.as_str().ok_or(Error::Data)?))
2125 },
2126 _ => {
2127 },
2130 }
2131 }
2132
2133 Ok(rsa_other_primes_info)
2134 }
2135}
2136
2137trait JsonWebKeyExt {
2138 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
2139 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
2140 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
2141 #[expect(unused)]
2142 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error>;
2143 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
2144}
2145
2146impl JsonWebKeyExt for JsonWebKey {
2147 #[expect(unsafe_code)]
2149 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
2150 let json = String::from_utf8_lossy(data);
2155
2156 let json: Vec<_> = json.encode_utf16().collect();
2158
2159 rooted!(in(*cx) let mut result = UndefinedValue());
2163 unsafe {
2164 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
2165 return Err(Error::JSFailed);
2166 }
2167 }
2168
2169 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
2171 Ok(ConversionResult::Success(key)) => key,
2172 Ok(ConversionResult::Failure(error)) => {
2173 return Err(Error::Type(error.to_string()));
2174 },
2175 Err(()) => {
2176 return Err(Error::JSFailed);
2177 },
2178 };
2179
2180 if key.kty.is_none() {
2182 return Err(Error::Data);
2183 }
2184
2185 Ok(key)
2187 }
2188
2189 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
2195 rooted!(in(*cx) let mut data = UndefinedValue());
2196 self.safe_to_jsval(cx, data.handle_mut(), CanGc::note());
2197 serialize_jsval_to_json_utf8(cx, data.handle())
2198 }
2199
2200 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
2201 let mut usages = vec![];
2202 for op in self.key_ops.as_ref().ok_or(Error::Data)? {
2203 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data)?);
2204 }
2205 Ok(usages)
2206 }
2207
2208 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error> {
2209 self.oth.as_deref().ok_or(Error::Data)
2210 }
2211
2212 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
2216 if let Some(ref key_ops) = self.key_ops {
2218 if key_ops
2221 .iter()
2222 .collect::<std::collections::HashSet<_>>()
2223 .len() <
2224 key_ops.len()
2225 {
2226 return Err(Error::Data);
2227 }
2228 if let Some(ref use_) = self.use_ {
2231 if key_ops.iter().any(|op| op != use_) {
2232 return Err(Error::Data);
2233 }
2234 }
2235
2236 let key_ops_as_usages = self.get_usages_from_key_ops()?;
2238 if !specified_usages
2239 .iter()
2240 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
2241 {
2242 return Err(Error::Data);
2243 }
2244 }
2245
2246 Ok(())
2247 }
2248}
2249
2250#[derive(Clone, MallocSizeOf)]
2255enum NormalizedAlgorithm {
2256 Algorithm(SubtleAlgorithm),
2257 EcdsaParams(SubtleEcdsaParams),
2258 EcKeyGenParams(SubtleEcKeyGenParams),
2259 EcKeyImportParams(SubtleEcKeyImportParams),
2260 EcdhKeyDeriveParams(SubtleEcdhKeyDeriveParams),
2261 AesCtrParams(SubtleAesCtrParams),
2262 AesKeyGenParams(SubtleAesKeyGenParams),
2263 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
2264 AesCbcParams(SubtleAesCbcParams),
2265 AesGcmParams(SubtleAesGcmParams),
2266 HmacImportParams(SubtleHmacImportParams),
2267 HmacKeyGenParams(SubtleHmacKeyGenParams),
2268 HkdfParams(SubtleHkdfParams),
2269 Pbkdf2Params(SubtlePbkdf2Params),
2270}
2271
2272fn normalize_algorithm(
2274 cx: JSContext,
2275 op: &Operation,
2276 alg: &AlgorithmIdentifier,
2277 can_gc: CanGc,
2278) -> Result<NormalizedAlgorithm, Error> {
2279 match alg {
2280 ObjectOrString::String(name) => {
2282 let alg = Algorithm {
2286 name: name.to_owned(),
2287 };
2288 rooted!(in(*cx) let mut alg_value = UndefinedValue());
2289 alg.safe_to_jsval(cx, alg_value.handle_mut(), CanGc::note());
2290 let alg_obj = RootedTraceableBox::new(Heap::default());
2291 alg_obj.set(alg_value.to_object());
2292 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj), can_gc)
2293 },
2294 ObjectOrString::Object(obj) => {
2296 rooted!(in(*cx) let value = ObjectValue(obj.get()));
2305 let initial_alg = dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2306
2307 let Some(&alg_name) = SUPPORTED_ALGORITHMS.iter().find(|supported_algorithm| {
2315 supported_algorithm.eq_ignore_ascii_case(&initial_alg.name.str())
2316 }) else {
2317 return Err(Error::NotSupported);
2318 };
2319
2320 let normalized_algorithm = match (alg_name, op) {
2356 (ALG_ECDSA, Operation::Sign) => {
2358 let mut params = dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(
2359 cx,
2360 value.handle(),
2361 can_gc,
2362 )?;
2363 params.parent.name = DOMString::from(alg_name);
2364 NormalizedAlgorithm::EcdsaParams(params.try_into()?)
2365 },
2366 (ALG_ECDSA, Operation::Verify) => {
2367 let mut params = dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(
2368 cx,
2369 value.handle(),
2370 can_gc,
2371 )?;
2372 params.parent.name = DOMString::from(alg_name);
2373 NormalizedAlgorithm::EcdsaParams(params.try_into()?)
2374 },
2375 (ALG_ECDSA, Operation::GenerateKey) => {
2376 let mut params =
2377 dictionary_from_jsval::<EcKeyGenParams>(cx, value.handle(), can_gc)?;
2378 params.parent.name = DOMString::from(alg_name);
2379 NormalizedAlgorithm::EcKeyGenParams(params.into())
2380 },
2381 (ALG_ECDSA, Operation::ImportKey) => {
2382 let mut params =
2383 dictionary_from_jsval::<EcKeyImportParams>(cx, value.handle(), can_gc)?;
2384 params.parent.name = DOMString::from(alg_name);
2385 NormalizedAlgorithm::EcKeyImportParams(params.into())
2386 },
2387 (ALG_ECDSA, Operation::ExportKey) => {
2388 let mut params =
2389 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2390 params.name = DOMString::from(alg_name);
2391 NormalizedAlgorithm::Algorithm(params.into())
2392 },
2393
2394 (ALG_ECDH, Operation::GenerateKey) => {
2396 let mut params =
2397 dictionary_from_jsval::<EcKeyGenParams>(cx, value.handle(), can_gc)?;
2398 params.parent.name = DOMString::from(alg_name);
2399 NormalizedAlgorithm::EcKeyGenParams(params.into())
2400 },
2401 (ALG_ECDH, Operation::DeriveBits) => {
2402 let mut params =
2403 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value.handle(), can_gc)?;
2404 params.parent.name = DOMString::from(alg_name);
2405 NormalizedAlgorithm::EcdhKeyDeriveParams(params.into())
2406 },
2407 (ALG_ECDH, Operation::ImportKey) => {
2408 let mut params =
2409 dictionary_from_jsval::<EcKeyImportParams>(cx, value.handle(), can_gc)?;
2410 params.parent.name = DOMString::from(alg_name);
2411 NormalizedAlgorithm::EcKeyImportParams(params.into())
2412 },
2413 (ALG_ECDH, Operation::ExportKey) => {
2414 let mut params =
2415 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2416 params.name = DOMString::from(alg_name);
2417 NormalizedAlgorithm::Algorithm(params.into())
2418 },
2419
2420 (ALG_ED25519, Operation::Sign) => {
2422 let mut params =
2423 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2424 params.name = DOMString::from(alg_name);
2425 NormalizedAlgorithm::Algorithm(params.into())
2426 },
2427 (ALG_ED25519, Operation::Verify) => {
2428 let mut params =
2429 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2430 params.name = DOMString::from(alg_name);
2431 NormalizedAlgorithm::Algorithm(params.into())
2432 },
2433 (ALG_ED25519, Operation::GenerateKey) => {
2434 let mut params =
2435 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2436 params.name = DOMString::from(alg_name);
2437 NormalizedAlgorithm::Algorithm(params.into())
2438 },
2439 (ALG_ED25519, Operation::ImportKey) => {
2440 let mut params =
2441 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2442 params.name = DOMString::from(alg_name);
2443 NormalizedAlgorithm::Algorithm(params.into())
2444 },
2445 (ALG_ED25519, Operation::ExportKey) => {
2446 let mut params =
2447 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2448 params.name = DOMString::from(alg_name);
2449 NormalizedAlgorithm::Algorithm(params.into())
2450 },
2451
2452 (ALG_X25519, Operation::DeriveBits) => {
2454 let mut params =
2455 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value.handle(), can_gc)?;
2456 params.parent.name = DOMString::from(alg_name);
2457 NormalizedAlgorithm::EcdhKeyDeriveParams(params.into())
2458 },
2459 (ALG_X25519, Operation::GenerateKey) => {
2460 let mut params =
2461 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2462 params.name = DOMString::from(alg_name);
2463 NormalizedAlgorithm::Algorithm(params.into())
2464 },
2465 (ALG_X25519, Operation::ImportKey) => {
2466 let mut params =
2467 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2468 params.name = DOMString::from(alg_name);
2469 NormalizedAlgorithm::Algorithm(params.into())
2470 },
2471 (ALG_X25519, Operation::ExportKey) => {
2472 let mut params =
2473 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2474 params.name = DOMString::from(alg_name);
2475 NormalizedAlgorithm::Algorithm(params.into())
2476 },
2477
2478 (ALG_AES_CTR, Operation::Encrypt) => {
2480 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2481 cx,
2482 value.handle(),
2483 can_gc,
2484 )?;
2485 params.parent.name = DOMString::from(alg_name);
2486 NormalizedAlgorithm::AesCtrParams(params.into())
2487 },
2488 (ALG_AES_CTR, Operation::Decrypt) => {
2489 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2490 cx,
2491 value.handle(),
2492 can_gc,
2493 )?;
2494 params.parent.name = DOMString::from(alg_name);
2495 NormalizedAlgorithm::AesCtrParams(params.into())
2496 },
2497 (ALG_AES_CTR, Operation::GenerateKey) => {
2498 let mut params =
2499 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2500 params.parent.name = DOMString::from(alg_name);
2501 NormalizedAlgorithm::AesKeyGenParams(params.into())
2502 },
2503 (ALG_AES_CTR, Operation::ImportKey) => {
2504 let mut params =
2505 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2506 params.name = DOMString::from(alg_name);
2507 NormalizedAlgorithm::Algorithm(params.into())
2508 },
2509 (ALG_AES_CTR, Operation::ExportKey) => {
2510 let mut params =
2511 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2512 params.name = DOMString::from(alg_name);
2513 NormalizedAlgorithm::Algorithm(params.into())
2514 },
2515 (ALG_AES_CTR, Operation::GetKeyLength) => {
2516 let mut params =
2517 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2518 params.parent.name = DOMString::from(alg_name);
2519 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2520 },
2521
2522 (ALG_AES_CBC, Operation::Encrypt) => {
2524 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2525 cx,
2526 value.handle(),
2527 can_gc,
2528 )?;
2529 params.parent.name = DOMString::from(alg_name);
2530 NormalizedAlgorithm::AesCbcParams(params.into())
2531 },
2532 (ALG_AES_CBC, Operation::Decrypt) => {
2533 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2534 cx,
2535 value.handle(),
2536 can_gc,
2537 )?;
2538 params.parent.name = DOMString::from(alg_name);
2539 NormalizedAlgorithm::AesCbcParams(params.into())
2540 },
2541 (ALG_AES_CBC, Operation::GenerateKey) => {
2542 let mut params =
2543 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2544 params.parent.name = DOMString::from(alg_name);
2545 NormalizedAlgorithm::AesKeyGenParams(params.into())
2546 },
2547 (ALG_AES_CBC, Operation::ImportKey) => {
2548 let mut params =
2549 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2550 params.name = DOMString::from(alg_name);
2551 NormalizedAlgorithm::Algorithm(params.into())
2552 },
2553 (ALG_AES_CBC, Operation::ExportKey) => {
2554 let mut params =
2555 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2556 params.name = DOMString::from(alg_name);
2557 NormalizedAlgorithm::Algorithm(params.into())
2558 },
2559 (ALG_AES_CBC, Operation::GetKeyLength) => {
2560 let mut params =
2561 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2562 params.parent.name = DOMString::from(alg_name);
2563 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2564 },
2565
2566 (ALG_AES_GCM, Operation::Encrypt) => {
2568 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2569 cx,
2570 value.handle(),
2571 can_gc,
2572 )?;
2573 params.parent.name = DOMString::from(alg_name);
2574 NormalizedAlgorithm::AesGcmParams(params.into())
2575 },
2576 (ALG_AES_GCM, Operation::Decrypt) => {
2577 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2578 cx,
2579 value.handle(),
2580 can_gc,
2581 )?;
2582 params.parent.name = DOMString::from(alg_name);
2583 NormalizedAlgorithm::AesGcmParams(params.into())
2584 },
2585 (ALG_AES_GCM, Operation::GenerateKey) => {
2586 let mut params =
2587 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2588 params.parent.name = DOMString::from(alg_name);
2589 NormalizedAlgorithm::AesKeyGenParams(params.into())
2590 },
2591 (ALG_AES_GCM, Operation::ImportKey) => {
2592 let mut params =
2593 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2594 params.name = DOMString::from(alg_name);
2595 NormalizedAlgorithm::Algorithm(params.into())
2596 },
2597 (ALG_AES_GCM, Operation::ExportKey) => {
2598 let mut params =
2599 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2600 params.name = DOMString::from(alg_name);
2601 NormalizedAlgorithm::Algorithm(params.into())
2602 },
2603 (ALG_AES_GCM, Operation::GetKeyLength) => {
2604 let mut params =
2605 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2606 params.parent.name = DOMString::from(alg_name);
2607 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2608 },
2609
2610 (ALG_AES_KW, Operation::WrapKey) => {
2612 let mut params =
2613 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2614 params.name = DOMString::from(alg_name);
2615 NormalizedAlgorithm::Algorithm(params.into())
2616 },
2617 (ALG_AES_KW, Operation::UnwrapKey) => {
2618 let mut params =
2619 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2620 params.name = DOMString::from(alg_name);
2621 NormalizedAlgorithm::Algorithm(params.into())
2622 },
2623 (ALG_AES_KW, Operation::GenerateKey) => {
2624 let mut params =
2625 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2626 params.parent.name = DOMString::from(alg_name);
2627 NormalizedAlgorithm::AesKeyGenParams(params.into())
2628 },
2629 (ALG_AES_KW, Operation::ImportKey) => {
2630 let mut params =
2631 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2632 params.name = DOMString::from(alg_name);
2633 NormalizedAlgorithm::Algorithm(params.into())
2634 },
2635 (ALG_AES_KW, Operation::ExportKey) => {
2636 let mut params =
2637 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2638 params.name = DOMString::from(alg_name);
2639 NormalizedAlgorithm::Algorithm(params.into())
2640 },
2641 (ALG_AES_KW, Operation::GetKeyLength) => {
2642 let mut params =
2643 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2644 params.parent.name = DOMString::from(alg_name);
2645 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2646 },
2647
2648 (ALG_HMAC, Operation::Sign) => {
2650 let mut params =
2651 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2652 params.name = DOMString::from(alg_name);
2653 NormalizedAlgorithm::Algorithm(params.into())
2654 },
2655 (ALG_HMAC, Operation::Verify) => {
2656 let mut params =
2657 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2658 params.name = DOMString::from(alg_name);
2659 NormalizedAlgorithm::Algorithm(params.into())
2660 },
2661 (ALG_HMAC, Operation::GenerateKey) => {
2662 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(
2663 cx,
2664 value.handle(),
2665 can_gc,
2666 )?;
2667 params.parent.name = DOMString::from(alg_name);
2668 NormalizedAlgorithm::HmacKeyGenParams(params.try_into()?)
2669 },
2670 (ALG_HMAC, Operation::ImportKey) => {
2671 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2672 cx,
2673 value.handle(),
2674 can_gc,
2675 )?;
2676 params.parent.name = DOMString::from(alg_name);
2677 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2678 },
2679 (ALG_HMAC, Operation::ExportKey) => {
2680 let mut params =
2681 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2682 params.name = DOMString::from(alg_name);
2683 NormalizedAlgorithm::Algorithm(params.into())
2684 },
2685 (ALG_HMAC, Operation::GetKeyLength) => {
2686 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2687 cx,
2688 value.handle(),
2689 can_gc,
2690 )?;
2691 params.parent.name = DOMString::from(alg_name);
2692 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2693 },
2694
2695 (ALG_SHA1, Operation::Digest) => {
2697 let mut params =
2698 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2699 params.name = DOMString::from(alg_name);
2700 NormalizedAlgorithm::Algorithm(params.into())
2701 },
2702 (ALG_SHA256, Operation::Digest) => {
2703 let mut params =
2704 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2705 params.name = DOMString::from(alg_name);
2706 NormalizedAlgorithm::Algorithm(params.into())
2707 },
2708 (ALG_SHA384, Operation::Digest) => {
2709 let mut params =
2710 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2711 params.name = DOMString::from(alg_name);
2712 NormalizedAlgorithm::Algorithm(params.into())
2713 },
2714 (ALG_SHA512, Operation::Digest) => {
2715 let mut params =
2716 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2717 params.name = DOMString::from(alg_name);
2718 NormalizedAlgorithm::Algorithm(params.into())
2719 },
2720
2721 (ALG_HKDF, Operation::DeriveBits) => {
2723 let mut params = dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(
2724 cx,
2725 value.handle(),
2726 can_gc,
2727 )?;
2728 params.parent.name = DOMString::from(alg_name);
2729 NormalizedAlgorithm::HkdfParams(params.try_into()?)
2730 },
2731 (ALG_HKDF, Operation::ImportKey) => {
2732 let mut params =
2733 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2734 params.name = DOMString::from(alg_name);
2735 NormalizedAlgorithm::Algorithm(params.into())
2736 },
2737 (ALG_HKDF, Operation::GetKeyLength) => {
2738 let mut params =
2739 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2740 params.name = DOMString::from(alg_name);
2741 NormalizedAlgorithm::Algorithm(params.into())
2742 },
2743
2744 (ALG_PBKDF2, Operation::DeriveBits) => {
2746 let mut params = dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(
2747 cx,
2748 value.handle(),
2749 can_gc,
2750 )?;
2751 params.parent.name = DOMString::from(alg_name);
2752 NormalizedAlgorithm::Pbkdf2Params(params.try_into()?)
2753 },
2754 (ALG_PBKDF2, Operation::ImportKey) => {
2755 let mut params =
2756 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2757 params.name = DOMString::from(alg_name);
2758 NormalizedAlgorithm::Algorithm(params.into())
2759 },
2760 (ALG_PBKDF2, Operation::GetKeyLength) => {
2761 let mut params =
2762 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2763 params.name = DOMString::from(alg_name);
2764 NormalizedAlgorithm::Algorithm(params.into())
2765 },
2766
2767 _ => return Err(Error::NotSupported),
2768 };
2769
2770 Ok(normalized_algorithm)
2772 },
2773 }
2774}
2775
2776impl NormalizedAlgorithm {
2777 fn name(&self) -> &str {
2779 match self {
2780 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
2781 NormalizedAlgorithm::EcdsaParams(algo) => &algo.name,
2782 NormalizedAlgorithm::EcKeyGenParams(algo) => &algo.name,
2783 NormalizedAlgorithm::EcKeyImportParams(algo) => &algo.name,
2784 NormalizedAlgorithm::EcdhKeyDeriveParams(algo) => &algo.name,
2785 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
2786 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
2787 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
2788 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
2789 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
2790 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
2791 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
2792 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
2793 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
2794 }
2795 }
2796
2797 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
2798 match (self.name(), self) {
2799 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
2800 aes_operation::encrypt_aes_ctr(algo, key, plaintext)
2801 },
2802 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
2803 aes_operation::encrypt_aes_cbc(algo, key, plaintext)
2804 },
2805 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
2806 aes_operation::encrypt_aes_gcm(algo, key, plaintext)
2807 },
2808 _ => Err(Error::NotSupported),
2809 }
2810 }
2811
2812 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
2813 match (self.name(), self) {
2814 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
2815 aes_operation::decrypt_aes_ctr(algo, key, ciphertext)
2816 },
2817 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
2818 aes_operation::decrypt_aes_cbc(algo, key, ciphertext)
2819 },
2820 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
2821 aes_operation::decrypt_aes_gcm(algo, key, ciphertext)
2822 },
2823 _ => Err(Error::NotSupported),
2824 }
2825 }
2826
2827 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
2828 match (self.name(), self) {
2829 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
2830 ecdsa_operation::sign(algo, key, message)
2831 },
2832 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2833 ed25519_operation::sign(key, message)
2834 },
2835 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => hmac_operation::sign(key, message),
2836 _ => Err(Error::NotSupported),
2837 }
2838 }
2839
2840 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
2841 match (self.name(), self) {
2842 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
2843 ecdsa_operation::verify(algo, key, message, signature)
2844 },
2845 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2846 ed25519_operation::verify(key, message, signature)
2847 },
2848 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => {
2849 hmac_operation::verify(key, message, signature)
2850 },
2851 _ => Err(Error::NotSupported),
2852 }
2853 }
2854
2855 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
2856 match (self.name(), self) {
2857 (ALG_SHA1, NormalizedAlgorithm::Algorithm(algo)) => {
2858 sha_operation::digest(algo, message)
2859 },
2860 (ALG_SHA256, NormalizedAlgorithm::Algorithm(algo)) => {
2861 sha_operation::digest(algo, message)
2862 },
2863 (ALG_SHA384, NormalizedAlgorithm::Algorithm(algo)) => {
2864 sha_operation::digest(algo, message)
2865 },
2866 (ALG_SHA512, NormalizedAlgorithm::Algorithm(algo)) => {
2867 sha_operation::digest(algo, message)
2868 },
2869 _ => Err(Error::NotSupported),
2870 }
2871 }
2872
2873 fn generate_key(
2874 &self,
2875 global: &GlobalScope,
2876 extractable: bool,
2877 usages: Vec<KeyUsage>,
2878 can_gc: CanGc,
2879 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
2880 match (self.name(), self) {
2881 (ALG_ECDSA, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
2882 ecdsa_operation::generate_key(global, algo, extractable, usages, can_gc)
2883 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
2884 },
2885 (ALG_ECDH, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
2886 ecdh_operation::generate_key(global, algo, extractable, usages, can_gc)
2887 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
2888 },
2889 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2890 ed25519_operation::generate_key(global, extractable, usages, can_gc)
2891 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
2892 },
2893 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2894 x25519_operation::generate_key(global, extractable, usages, can_gc)
2895 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
2896 },
2897 (ALG_AES_CTR, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
2898 aes_operation::generate_key_aes_ctr(global, algo, extractable, usages, can_gc)
2899 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2900 },
2901 (ALG_AES_CBC, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
2902 aes_operation::generate_key_aes_cbc(global, algo, extractable, usages, can_gc)
2903 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2904 },
2905 (ALG_AES_GCM, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
2906 aes_operation::generate_key_aes_gcm(global, algo, extractable, usages, can_gc)
2907 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2908 },
2909 (ALG_AES_KW, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
2910 aes_operation::generate_key_aes_kw(global, algo, extractable, usages, can_gc)
2911 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2912 },
2913 (ALG_HMAC, NormalizedAlgorithm::HmacKeyGenParams(algo)) => {
2914 hmac_operation::generate_key(global, algo, extractable, usages, can_gc)
2915 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
2916 },
2917 _ => Err(Error::NotSupported),
2918 }
2919 }
2920
2921 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
2922 match (self.name(), self) {
2923 (ALG_ECDH, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
2924 ecdh_operation::derive_bits(algo, key, length)
2925 },
2926 (ALG_X25519, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
2927 x25519_operation::derive_bits(algo, key, length)
2928 },
2929 (ALG_HKDF, NormalizedAlgorithm::HkdfParams(algo)) => {
2930 hkdf_operation::derive_bits(algo, key, length)
2931 },
2932 (ALG_PBKDF2, NormalizedAlgorithm::Pbkdf2Params(algo)) => {
2933 pbkdf2_operation::derive_bits(algo, key, length)
2934 },
2935 _ => Err(Error::NotSupported),
2936 }
2937 }
2938
2939 fn import_key(
2940 &self,
2941 global: &GlobalScope,
2942 format: KeyFormat,
2943 key_data: &[u8],
2944 extractable: bool,
2945 usages: Vec<KeyUsage>,
2946 can_gc: CanGc,
2947 ) -> Result<DomRoot<CryptoKey>, Error> {
2948 match (self.name(), self) {
2949 (ALG_ECDSA, NormalizedAlgorithm::EcKeyImportParams(algo)) => {
2950 ecdsa_operation::import_key(
2951 global,
2952 algo,
2953 format,
2954 key_data,
2955 extractable,
2956 usages,
2957 can_gc,
2958 )
2959 },
2960 (ALG_ECDH, NormalizedAlgorithm::EcKeyImportParams(algo)) => ecdh_operation::import_key(
2961 global,
2962 algo,
2963 format,
2964 key_data,
2965 extractable,
2966 usages,
2967 can_gc,
2968 ),
2969 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2970 ed25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
2971 },
2972 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
2973 x25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
2974 },
2975 (ALG_AES_CTR, NormalizedAlgorithm::Algorithm(_algo)) => {
2976 aes_operation::import_key_aes_ctr(
2977 global,
2978 format,
2979 key_data,
2980 extractable,
2981 usages,
2982 can_gc,
2983 )
2984 },
2985 (ALG_AES_CBC, NormalizedAlgorithm::Algorithm(_algo)) => {
2986 aes_operation::import_key_aes_cbc(
2987 global,
2988 format,
2989 key_data,
2990 extractable,
2991 usages,
2992 can_gc,
2993 )
2994 },
2995 (ALG_AES_GCM, NormalizedAlgorithm::Algorithm(_algo)) => {
2996 aes_operation::import_key_aes_gcm(
2997 global,
2998 format,
2999 key_data,
3000 extractable,
3001 usages,
3002 can_gc,
3003 )
3004 },
3005 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3006 aes_operation::import_key_aes_kw(
3007 global,
3008 format,
3009 key_data,
3010 extractable,
3011 usages,
3012 can_gc,
3013 )
3014 },
3015 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => hmac_operation::import_key(
3016 global,
3017 algo,
3018 format,
3019 key_data,
3020 extractable,
3021 usages,
3022 can_gc,
3023 ),
3024 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => {
3025 hkdf_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3026 },
3027 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
3028 pbkdf2_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3029 },
3030 _ => Err(Error::NotSupported),
3031 }
3032 }
3033
3034 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
3035 match (self.name(), self) {
3036 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3037 aes_operation::wrap_key_aes_kw(key, plaintext)
3038 },
3039 _ => Err(Error::NotSupported),
3040 }
3041 }
3042
3043 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
3044 match (self.name(), self) {
3045 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3046 aes_operation::unwrap_key_aes_kw(key, ciphertext)
3047 },
3048 _ => Err(Error::NotSupported),
3049 }
3050 }
3051
3052 fn get_key_length(&self) -> Result<Option<u32>, Error> {
3053 match (self.name(), self) {
3054 (ALG_AES_CTR, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3055 aes_operation::get_key_length_aes_ctr(algo)
3056 },
3057 (ALG_AES_CBC, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3058 aes_operation::get_key_length_aes_cbc(algo)
3059 },
3060 (ALG_AES_GCM, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3061 aes_operation::get_key_length_aes_gcm(algo)
3062 },
3063 (ALG_AES_KW, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3064 aes_operation::get_key_length_aes_kw(algo)
3065 },
3066 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => {
3067 hmac_operation::get_key_length(algo)
3068 },
3069 (ALG_HKDF, NormalizedAlgorithm::HkdfParams(_algo)) => hkdf_operation::get_key_length(),
3070 (ALG_PBKDF2, NormalizedAlgorithm::Pbkdf2Params(_algo)) => {
3071 pbkdf2_operation::get_key_length()
3072 },
3073 _ => Err(Error::NotSupported),
3074 }
3075 }
3076}
3077
3078fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
3085 match key.algorithm().name() {
3086 ALG_ECDSA => ecdsa_operation::export_key(format, key),
3087 ALG_ECDH => ecdh_operation::export_key(format, key),
3088 ALG_ED25519 => ed25519_operation::export_key(format, key),
3089 ALG_X25519 => x25519_operation::export_key(format, key),
3090 ALG_AES_CTR => aes_operation::export_key_aes_ctr(format, key),
3091 ALG_AES_CBC => aes_operation::export_key_aes_cbc(format, key),
3092 ALG_AES_GCM => aes_operation::export_key_aes_gcm(format, key),
3093 ALG_AES_KW => aes_operation::export_key_aes_kw(format, key),
3094 ALG_HMAC => hmac_operation::export_key(format, key),
3095 _ => Err(Error::NotSupported),
3096 }
3097}