1mod aes_operation;
6mod argon2_operation;
7mod chacha20_poly1305_operation;
8mod cshake_operation;
9mod ecdh_operation;
10mod ecdsa_operation;
11mod ed25519_operation;
12mod hkdf_operation;
13mod hmac_operation;
14mod pbkdf2_operation;
15mod sha3_operation;
16mod sha_operation;
17mod x25519_operation;
18
19use std::ptr;
20use std::rc::Rc;
21use std::str::FromStr;
22
23use dom_struct::dom_struct;
24use js::conversions::ConversionResult;
25use js::jsapi::{Heap, JSObject};
26use js::jsval::{ObjectValue, UndefinedValue};
27use js::rust::wrappers::JS_ParseJSON;
28use js::rust::{HandleValue, MutableHandleValue};
29use js::typedarray::ArrayBufferU8;
30
31use crate::dom::bindings::buffer_source::create_buffer_source;
32use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
33 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
34};
35use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
36 AeadParams, AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
37 AesKeyGenParams, Algorithm, AlgorithmIdentifier, Argon2Params, CShakeParams, EcKeyAlgorithm,
38 EcKeyGenParams, EcKeyImportParams, EcdhKeyDeriveParams, EcdsaParams, HkdfParams,
39 HmacImportParams, HmacKeyAlgorithm, HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat,
40 Pbkdf2Params, RsaOtherPrimesInfo, SubtleCryptoMethods,
41};
42use crate::dom::bindings::codegen::UnionTypes::{
43 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
44};
45use crate::dom::bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
46use crate::dom::bindings::error::{Error, Fallible};
47use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
48use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
49use crate::dom::bindings::root::DomRoot;
50use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
51use crate::dom::bindings::trace::RootedTraceableBox;
52use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
53use crate::dom::globalscope::GlobalScope;
54use crate::dom::promise::Promise;
55use crate::realms::InRealm;
56use crate::script_runtime::{CanGc, JSContext};
57
58const ALG_RSASSA_PKCS1: &str = "RSASSA-PKCS1-v1_5";
60const ALG_RSA_PSS: &str = "RSA-PSS";
61const ALG_RSA_OAEP: &str = "RSA-OAEP";
62const ALG_ECDSA: &str = "ECDSA";
63const ALG_ECDH: &str = "ECDH";
64const ALG_ED25519: &str = "Ed25519";
65const ALG_X25519: &str = "X25519";
66const ALG_AES_CTR: &str = "AES-CTR";
67const ALG_AES_CBC: &str = "AES-CBC";
68const ALG_AES_GCM: &str = "AES-GCM";
69const ALG_AES_KW: &str = "AES-KW";
70const ALG_HMAC: &str = "HMAC";
71const ALG_SHA1: &str = "SHA-1";
72const ALG_SHA256: &str = "SHA-256";
73const ALG_SHA384: &str = "SHA-384";
74const ALG_SHA512: &str = "SHA-512";
75const ALG_HKDF: &str = "HKDF";
76const ALG_PBKDF2: &str = "PBKDF2";
77
78const ALG_CHACHA20_POLY1305: &str = "ChaCha20-Poly1305";
80const ALG_SHA3_256: &str = "SHA3-256";
81const ALG_SHA3_384: &str = "SHA3-384";
82const ALG_SHA3_512: &str = "SHA3-512";
83const ALG_CSHAKE_128: &str = "cSHAKE128";
84const ALG_CSHAKE_256: &str = "cSHAKE256";
85const ALG_ARGON2D: &str = "Argon2d";
86const ALG_ARGON2I: &str = "Argon2i";
87const ALG_ARGON2ID: &str = "Argon2id";
88
89static SUPPORTED_ALGORITHMS: &[&str] = &[
90 ALG_RSASSA_PKCS1,
91 ALG_RSA_PSS,
92 ALG_RSA_OAEP,
93 ALG_ECDSA,
94 ALG_ECDH,
95 ALG_ED25519,
96 ALG_X25519,
97 ALG_AES_CTR,
98 ALG_AES_CBC,
99 ALG_AES_GCM,
100 ALG_AES_KW,
101 ALG_HMAC,
102 ALG_SHA1,
103 ALG_SHA256,
104 ALG_SHA384,
105 ALG_SHA512,
106 ALG_HKDF,
107 ALG_PBKDF2,
108 ALG_CHACHA20_POLY1305,
109 ALG_SHA3_256,
110 ALG_SHA3_384,
111 ALG_SHA3_512,
112 ALG_CSHAKE_128,
113 ALG_CSHAKE_256,
114 ALG_ARGON2D,
115 ALG_ARGON2I,
116 ALG_ARGON2ID,
117];
118
119const NAMED_CURVE_P256: &str = "P-256";
121const NAMED_CURVE_P384: &str = "P-384";
122const NAMED_CURVE_P521: &str = "P-521";
123
124static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
125
126#[expect(dead_code)]
128enum Operation {
129 Encrypt,
130 Decrypt,
131 Sign,
132 Verify,
133 Digest,
134 GenerateKey,
135 DeriveKey,
136 DeriveBits,
137 ImportKey,
138 ExportKey,
139 WrapKey,
140 UnwrapKey,
141 GetKeyLength,
142}
143
144#[dom_struct]
145pub(crate) struct SubtleCrypto {
146 reflector_: Reflector,
147}
148
149impl SubtleCrypto {
150 fn new_inherited() -> SubtleCrypto {
151 SubtleCrypto {
152 reflector_: Reflector::new(),
153 }
154 }
155
156 pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<SubtleCrypto> {
157 reflect_dom_object(Box::new(SubtleCrypto::new_inherited()), global, can_gc)
158 }
159
160 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
164 let trusted_promise = TrustedPromise::new(promise);
165 self.global().task_manager().crypto_task_source().queue(
166 task!(resolve_data: move || {
167 let promise = trusted_promise.root();
168
169 let cx = GlobalScope::get_cx();
170 rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
171 match create_buffer_source::<ArrayBufferU8>(cx, &data, array_buffer_ptr.handle_mut(), CanGc::note()) {
172 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
173 Err(_) => promise.reject_error(Error::JSFailed, CanGc::note()),
174 }
175 }),
176 );
177 }
178
179 fn resolve_promise_with_jwk(&self, promise: Rc<Promise>, jwk: Box<JsonWebKey>) {
183 let cx = GlobalScope::get_cx();
186 let stringified_jwk = match jwk.stringify(cx) {
187 Ok(stringified_jwk) => stringified_jwk.to_string(),
188 Err(error) => {
189 self.reject_promise_with_error(promise, error);
190 return;
191 },
192 };
193
194 let trusted_subtle = Trusted::new(self);
195 let trusted_promise = TrustedPromise::new(promise);
196 self.global()
197 .task_manager()
198 .crypto_task_source()
199 .queue(task!(resolve_jwk: move || {
200 let subtle = trusted_subtle.root();
201 let promise = trusted_promise.root();
202
203 let cx = GlobalScope::get_cx();
204 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
205 Ok(jwk) => {
206 rooted!(in(*cx) let mut rval = UndefinedValue());
207 jwk.safe_to_jsval(cx, rval.handle_mut(), CanGc::note());
208 rooted!(in(*cx) let mut object = rval.to_object());
209 promise.resolve_native(&*object, CanGc::note());
210 },
211 Err(error) => {
212 subtle.reject_promise_with_error(promise, error);
213 return;
214 },
215 }
216 }));
217 }
218
219 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
222 let trusted_key = Trusted::new(&*key);
223 let trusted_promise = TrustedPromise::new(promise);
224 self.global()
225 .task_manager()
226 .crypto_task_source()
227 .queue(task!(resolve_key: move || {
228 let key = trusted_key.root();
229 let promise = trusted_promise.root();
230 promise.resolve_native(&key, CanGc::note());
231 }));
232 }
233
234 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
237 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
238 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
239 let trusted_promise = TrustedPromise::new(promise);
240 self.global()
241 .task_manager()
242 .crypto_task_source()
243 .queue(task!(resolve_key: move || {
244 let key_pair = CryptoKeyPair {
245 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
246 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
247 };
248 let promise = trusted_promise.root();
249 promise.resolve_native(&key_pair, CanGc::note());
250 }));
251 }
252
253 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
256 let trusted_promise = TrustedPromise::new(promise);
257 self.global().task_manager().crypto_task_source().queue(
258 task!(generate_key_result: move || {
259 let promise = trusted_promise.root();
260 promise.resolve_native(&result, CanGc::note());
261 }),
262 );
263 }
264
265 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
268 let trusted_promise = TrustedPromise::new(promise);
269 self.global()
270 .task_manager()
271 .crypto_task_source()
272 .queue(task!(reject_error: move || {
273 let promise = trusted_promise.root();
274 promise.reject_error(error, CanGc::note());
275 }));
276 }
277}
278
279impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
280 fn Encrypt(
282 &self,
283 cx: JSContext,
284 algorithm: AlgorithmIdentifier,
285 key: &CryptoKey,
286 data: ArrayBufferViewOrArrayBuffer,
287 comp: InRealm,
288 can_gc: CanGc,
289 ) -> Rc<Promise> {
290 let data = match data {
297 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
298 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
299 };
300
301 let promise = Promise::new_in_current_realm(comp, can_gc);
305 let normalized_algorithm =
306 match normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc) {
307 Ok(normalized_algorithm) => normalized_algorithm,
308 Err(error) => {
309 promise.reject_error(error, can_gc);
310 return promise;
311 },
312 };
313
314 let this = Trusted::new(self);
320 let trusted_promise = TrustedPromise::new(promise.clone());
321 let trusted_key = Trusted::new(key);
322 self.global()
323 .task_manager()
324 .dom_manipulation_task_source()
325 .queue(task!(encrypt: move || {
326 let subtle = this.root();
327 let promise = trusted_promise.root();
328 let key = trusted_key.root();
329
330 if normalized_algorithm.name() != key.algorithm().name() {
338 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
339 return;
340 }
341
342 if !key.usages().contains(&KeyUsage::Encrypt) {
345 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
346 return;
347 }
348
349 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
353 Ok(ciphertext) => ciphertext,
354 Err(error) => {
355 subtle.reject_promise_with_error(promise, error);
356 return;
357 },
358 };
359
360 subtle.resolve_promise_with_data(promise, ciphertext);
366 }));
367 promise
368 }
369
370 fn Decrypt(
372 &self,
373 cx: JSContext,
374 algorithm: AlgorithmIdentifier,
375 key: &CryptoKey,
376 data: ArrayBufferViewOrArrayBuffer,
377 comp: InRealm,
378 can_gc: CanGc,
379 ) -> Rc<Promise> {
380 let data = match data {
387 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
388 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
389 };
390
391 let promise = Promise::new_in_current_realm(comp, can_gc);
395 let normalized_algorithm =
396 match normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc) {
397 Ok(normalized_algorithm) => normalized_algorithm,
398 Err(error) => {
399 promise.reject_error(error, can_gc);
400 return promise;
401 },
402 };
403
404 let this = Trusted::new(self);
410 let trusted_promise = TrustedPromise::new(promise.clone());
411 let trusted_key = Trusted::new(key);
412 self.global()
413 .task_manager()
414 .dom_manipulation_task_source()
415 .queue(task!(decrypt: move || {
416 let subtle = this.root();
417 let promise = trusted_promise.root();
418 let key = trusted_key.root();
419
420 if normalized_algorithm.name() != key.algorithm().name() {
428 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
429 return;
430 }
431
432 if !key.usages().contains(&KeyUsage::Decrypt) {
435 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
436 return;
437 }
438
439 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
443 Ok(plaintext) => plaintext,
444 Err(error) => {
445 subtle.reject_promise_with_error(promise, error);
446 return;
447 },
448 };
449
450 subtle.resolve_promise_with_data(promise, plaintext);
456 }));
457 promise
458 }
459
460 fn Sign(
462 &self,
463 cx: JSContext,
464 algorithm: AlgorithmIdentifier,
465 key: &CryptoKey,
466 data: ArrayBufferViewOrArrayBuffer,
467 comp: InRealm,
468 can_gc: CanGc,
469 ) -> Rc<Promise> {
470 let data = match &data {
477 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
478 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
479 };
480
481 let promise = Promise::new_in_current_realm(comp, can_gc);
485 let normalized_algorithm =
486 match normalize_algorithm(cx, &Operation::Sign, &algorithm, can_gc) {
487 Ok(normalized_algorithm) => normalized_algorithm,
488 Err(error) => {
489 promise.reject_error(error, can_gc);
490 return promise;
491 },
492 };
493
494 let this = Trusted::new(self);
500 let trusted_promise = TrustedPromise::new(promise.clone());
501 let trusted_key = Trusted::new(key);
502 self.global()
503 .task_manager()
504 .dom_manipulation_task_source()
505 .queue(task!(sign: move || {
506 let subtle = this.root();
507 let promise = trusted_promise.root();
508 let key = trusted_key.root();
509
510 if normalized_algorithm.name() != key.algorithm().name() {
518 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
519 return;
520 }
521
522 if !key.usages().contains(&KeyUsage::Sign) {
525 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
526 return;
527 }
528
529 let signature = match normalized_algorithm.sign(&key, &data) {
532 Ok(signature) => signature,
533 Err(error) => {
534 subtle.reject_promise_with_error(promise, error);
535 return;
536 },
537 };
538
539 subtle.resolve_promise_with_data(promise, signature);
545 }));
546 promise
547 }
548
549 fn Verify(
551 &self,
552 cx: JSContext,
553 algorithm: AlgorithmIdentifier,
554 key: &CryptoKey,
555 signature: ArrayBufferViewOrArrayBuffer,
556 data: ArrayBufferViewOrArrayBuffer,
557 comp: InRealm,
558 can_gc: CanGc,
559 ) -> Rc<Promise> {
560 let signature = match &signature {
567 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
568 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
569 };
570
571 let data = match &data {
574 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
575 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
576 };
577
578 let promise = Promise::new_in_current_realm(comp, can_gc);
582 let normalized_algorithm =
583 match normalize_algorithm(cx, &Operation::Verify, &algorithm, can_gc) {
584 Ok(algorithm) => algorithm,
585 Err(error) => {
586 promise.reject_error(error, can_gc);
587 return promise;
588 },
589 };
590
591 let this = Trusted::new(self);
597 let trusted_promise = TrustedPromise::new(promise.clone());
598 let trusted_key = Trusted::new(key);
599 self.global()
600 .task_manager()
601 .dom_manipulation_task_source()
602 .queue(task!(sign: move || {
603 let subtle = this.root();
604 let promise = trusted_promise.root();
605 let key = trusted_key.root();
606
607 if normalized_algorithm.name() != key.algorithm().name() {
615 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
616 return;
617 }
618
619 if !key.usages().contains(&KeyUsage::Verify) {
622 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
623 return;
624 }
625
626 let result = match normalized_algorithm.verify(&key, &data, &signature) {
630 Ok(result) => result,
631 Err(error) => {
632 subtle.reject_promise_with_error(promise, error);
633 return;
634 },
635 };
636
637 subtle.resolve_promise_with_bool(promise, result);
641 }));
642 promise
643 }
644
645 fn Digest(
647 &self,
648 cx: JSContext,
649 algorithm: AlgorithmIdentifier,
650 data: ArrayBufferViewOrArrayBuffer,
651 comp: InRealm,
652 can_gc: CanGc,
653 ) -> Rc<Promise> {
654 let data = match data {
660 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
661 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
662 };
663
664 let promise = Promise::new_in_current_realm(comp, can_gc);
668 let normalized_algorithm =
669 match normalize_algorithm(cx, &Operation::Digest, &algorithm, can_gc) {
670 Ok(normalized_algorithm) => normalized_algorithm,
671 Err(error) => {
672 promise.reject_error(error, can_gc);
673 return promise;
674 },
675 };
676
677 let this = Trusted::new(self);
683 let trusted_promise = TrustedPromise::new(promise.clone());
684 self.global()
685 .task_manager()
686 .dom_manipulation_task_source()
687 .queue(task!(generate_key: move || {
688 let subtle = this.root();
689 let promise = trusted_promise.root();
690
691 let digest = match normalized_algorithm.digest(&data) {
698 Ok(digest) => digest,
699 Err(error) => {
700 subtle.reject_promise_with_error(promise, error);
701 return;
702 }
703 };
704
705 subtle.resolve_promise_with_data(promise, digest);
711 }));
712 promise
713 }
714
715 fn GenerateKey(
717 &self,
718 cx: JSContext,
719 algorithm: AlgorithmIdentifier,
720 extractable: bool,
721 key_usages: Vec<KeyUsage>,
722 comp: InRealm,
723 can_gc: CanGc,
724 ) -> Rc<Promise> {
725 let promise = Promise::new_in_current_realm(comp, can_gc);
732 let normalized_algorithm =
733 match normalize_algorithm(cx, &Operation::GenerateKey, &algorithm, can_gc) {
734 Ok(normalized_algorithm) => normalized_algorithm,
735 Err(error) => {
736 promise.reject_error(error, can_gc);
737 return promise;
738 },
739 };
740
741 let trusted_subtle = Trusted::new(self);
747 let trusted_promise = TrustedPromise::new(promise.clone());
748 self.global()
749 .task_manager()
750 .dom_manipulation_task_source()
751 .queue(task!(generate_key: move || {
752 let subtle = trusted_subtle.root();
753 let promise = trusted_promise.root();
754
755 let result = match normalized_algorithm.generate_key(
762 &subtle.global(),
763 extractable,
764 key_usages,
765 CanGc::note(),
766 ) {
767 Ok(result) => result,
768 Err(error) => {
769 subtle.reject_promise_with_error(promise, error);
770 return;
771 }
772 };
773
774 match &result {
783 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
784 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
785 && crpyto_key.usages().is_empty()
786 {
787 subtle.reject_promise_with_error(promise, Error::Syntax(None));
788 return;
789 }
790 },
791 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
792 if crypto_key_pair.privateKey.as_ref().is_none_or(|private_key| private_key.usages().is_empty()) {
793 subtle.reject_promise_with_error(promise, Error::Syntax(None));
794 return;
795 }
796 }
797 };
798
799 match result {
805 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
806 subtle.resolve_promise_with_key(promise, key);
807 },
808 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
809 subtle.resolve_promise_with_key_pair(promise, key_pair);
810 },
811 }
812 }));
813
814 promise
815 }
816
817 fn DeriveKey(
819 &self,
820 cx: JSContext,
821 algorithm: AlgorithmIdentifier,
822 base_key: &CryptoKey,
823 derived_key_type: AlgorithmIdentifier,
824 extractable: bool,
825 usages: Vec<KeyUsage>,
826 comp: InRealm,
827 can_gc: CanGc,
828 ) -> Rc<Promise> {
829 let promise = Promise::new_in_current_realm(comp, can_gc);
838 let normalized_algorithm =
839 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
840 Ok(normalized_algorithm) => normalized_algorithm,
841 Err(error) => {
842 promise.reject_error(error, can_gc);
843 return promise;
844 },
845 };
846
847 let normalized_derived_key_algorithm_import =
852 match normalize_algorithm(cx, &Operation::ImportKey, &derived_key_type, can_gc) {
853 Ok(normalized_algorithm) => normalized_algorithm,
854 Err(error) => {
855 promise.reject_error(error, can_gc);
856 return promise;
857 },
858 };
859
860 let normalized_derived_key_algorithm_length =
865 match normalize_algorithm(cx, &Operation::GetKeyLength, &derived_key_type, can_gc) {
866 Ok(normalized_algorithm) => normalized_algorithm,
867 Err(error) => {
868 promise.reject_error(error, can_gc);
869 return promise;
870 },
871 };
872
873 let trusted_subtle = Trusted::new(self);
879 let trusted_base_key = Trusted::new(base_key);
880 let trusted_promise = TrustedPromise::new(promise.clone());
881 self.global().task_manager().dom_manipulation_task_source().queue(
882 task!(derive_key: move || {
883 let subtle = trusted_subtle.root();
884 let base_key = trusted_base_key.root();
885 let promise = trusted_promise.root();
886
887 if normalized_algorithm.name() != base_key.algorithm().name() {
895 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
896 return;
897 }
898
899 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
902 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
903 return;
904 }
905
906 let length = match normalized_derived_key_algorithm_length.get_key_length() {
909 Ok(length) => length,
910 Err(error) => {
911 subtle.reject_promise_with_error(promise, error);
912 return;
913 }
914 };
915
916 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
919 Ok(secret) => secret,
920 Err(error) => {
921 subtle.reject_promise_with_error(promise, error);
922 return;
923 }
924 };
925
926 let result = match normalized_derived_key_algorithm_import.import_key(
932 &subtle.global(),
933 KeyFormat::Raw_secret,
934 &secret,
935 extractable,
936 usages.clone(),
937 CanGc::note(),
938 ) {
939 Ok(algorithm) => algorithm,
940 Err(error) => {
941 subtle.reject_promise_with_error(promise, error);
942 return;
943 },
944 };
945
946 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
949 subtle.reject_promise_with_error(promise, Error::Syntax(None));
950 return;
951 }
952
953 subtle.resolve_promise_with_key(promise, result);
964 }),
965 );
966 promise
967 }
968
969 fn DeriveBits(
971 &self,
972 cx: JSContext,
973 algorithm: AlgorithmIdentifier,
974 base_key: &CryptoKey,
975 length: Option<u32>,
976 comp: InRealm,
977 can_gc: CanGc,
978 ) -> Rc<Promise> {
979 let promise = Promise::new_in_current_realm(comp, can_gc);
987 let normalized_algorithm =
988 match normalize_algorithm(cx, &Operation::DeriveBits, &algorithm, can_gc) {
989 Ok(normalized_algorithm) => normalized_algorithm,
990 Err(error) => {
991 promise.reject_error(error, can_gc);
992 return promise;
993 },
994 };
995
996 let trsuted_subtle = Trusted::new(self);
1002 let trusted_base_key = Trusted::new(base_key);
1003 let trusted_promise = TrustedPromise::new(promise.clone());
1004 self.global()
1005 .task_manager()
1006 .dom_manipulation_task_source()
1007 .queue(task!(import_key: move || {
1008 let subtle = trsuted_subtle.root();
1009 let base_key = trusted_base_key.root();
1010 let promise = trusted_promise.root();
1011
1012 if normalized_algorithm.name() != base_key.algorithm().name() {
1020 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1021 return;
1022 }
1023
1024 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1027 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1028 return;
1029 }
1030
1031 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1034 Ok(bits) => bits,
1035 Err(error) => {
1036 subtle.reject_promise_with_error(promise, error);
1037 return;
1038 }
1039 };
1040
1041 subtle.resolve_promise_with_data(promise, bits);
1047 }));
1048 promise
1049 }
1050
1051 fn ImportKey(
1053 &self,
1054 cx: JSContext,
1055 format: KeyFormat,
1056 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1057 algorithm: AlgorithmIdentifier,
1058 extractable: bool,
1059 key_usages: Vec<KeyUsage>,
1060 comp: InRealm,
1061 can_gc: CanGc,
1062 ) -> Rc<Promise> {
1063 let promise = Promise::new_in_current_realm(comp, can_gc);
1069
1070 let key_data = match format {
1072 KeyFormat::Raw |
1075 KeyFormat::Pkcs8 |
1076 KeyFormat::Spki |
1077 KeyFormat::Raw_public |
1078 KeyFormat::Raw_private |
1079 KeyFormat::Raw_seed |
1080 KeyFormat::Raw_secret => {
1081 match key_data {
1082 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1085 promise.reject_error(
1086 Error::Type("The keyData type does not match the format".to_string()),
1087 can_gc,
1088 );
1089 return promise;
1090 },
1091
1092 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1095 view.to_vec()
1096 },
1097 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1098 buffer.to_vec()
1099 },
1100 }
1101 },
1102 KeyFormat::Jwk => {
1104 match key_data {
1105 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1106 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1107 promise.reject_error(
1110 Error::Type("The keyData type does not match the format".to_string()),
1111 can_gc,
1112 );
1113 return promise;
1114 },
1115
1116 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1117 match jwk.stringify(cx) {
1124 Ok(stringified) => stringified.as_bytes().to_vec(),
1125 Err(error) => {
1126 promise.reject_error(error, can_gc);
1127 return promise;
1128 },
1129 }
1130 },
1131 }
1132 },
1133 };
1134
1135 let normalized_algorithm =
1139 match normalize_algorithm(cx, &Operation::ImportKey, &algorithm, can_gc) {
1140 Ok(algorithm) => algorithm,
1141 Err(error) => {
1142 promise.reject_error(error, can_gc);
1143 return promise;
1144 },
1145 };
1146
1147 let this = Trusted::new(self);
1149 let trusted_promise = TrustedPromise::new(promise.clone());
1150 self.global()
1151 .task_manager()
1152 .dom_manipulation_task_source()
1153 .queue(task!(import_key: move || {
1154 let subtle = this.root();
1155 let promise = trusted_promise.root();
1156
1157 let result = match normalized_algorithm.import_key(
1165 &subtle.global(),
1166 format,
1167 &key_data,
1168 extractable,
1169 key_usages.clone(),
1170 CanGc::note()
1171 ) {
1172 Ok(key) => key,
1173 Err(error) => {
1174 subtle.reject_promise_with_error(promise, error);
1175 return;
1176 },
1177 };
1178
1179 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1182 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1183 return;
1184 }
1185
1186 result.set_extractable(extractable);
1188
1189 result.set_usages(&key_usages);
1191
1192 subtle.resolve_promise_with_key(promise, result);
1198 }));
1199
1200 promise
1201 }
1202
1203 fn ExportKey(
1205 &self,
1206 format: KeyFormat,
1207 key: &CryptoKey,
1208 comp: InRealm,
1209 can_gc: CanGc,
1210 ) -> Rc<Promise> {
1211 let promise = Promise::new_in_current_realm(comp, can_gc);
1218
1219 let trusted_subtle = Trusted::new(self);
1221 let trusted_promise = TrustedPromise::new(promise.clone());
1222 let trusted_key = Trusted::new(key);
1223 self.global()
1224 .task_manager()
1225 .dom_manipulation_task_source()
1226 .queue(task!(export_key: move || {
1227 let subtle = trusted_subtle.root();
1228 let promise = trusted_promise.root();
1229 let key = trusted_key.root();
1230
1231 if matches!(
1239 key.algorithm().name(),
1240 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1241 ) {
1242 subtle.reject_promise_with_error(promise, Error::NotSupported(None));
1243 return;
1244 }
1245
1246 if !key.Extractable() {
1249 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1250 return;
1251 }
1252
1253 let result = match perform_export_key_operation(format, &key) {
1256 Ok(exported_key) => exported_key,
1257 Err(error) => {
1258 subtle.reject_promise_with_error(promise, error);
1259 return;
1260 },
1261 };
1262
1263 match result {
1276 ExportedKey::Bytes(bytes) => {
1277 subtle.resolve_promise_with_data(promise, bytes);
1278 },
1279 ExportedKey::Jwk(jwk) => {
1280 subtle.resolve_promise_with_jwk(promise, jwk);
1281 },
1282 }
1283 }));
1284 promise
1285 }
1286
1287 fn WrapKey(
1289 &self,
1290 cx: JSContext,
1291 format: KeyFormat,
1292 key: &CryptoKey,
1293 wrapping_key: &CryptoKey,
1294 algorithm: AlgorithmIdentifier,
1295 comp: InRealm,
1296 can_gc: CanGc,
1297 ) -> Rc<Promise> {
1298 let mut normalized_algorithm_result =
1305 normalize_algorithm(cx, &Operation::WrapKey, &algorithm, can_gc);
1306
1307 if normalized_algorithm_result.is_err() {
1310 normalized_algorithm_result =
1311 normalize_algorithm(cx, &Operation::Encrypt, &algorithm, can_gc);
1312 }
1313
1314 let promise = Promise::new_in_current_realm(comp, can_gc);
1316 let normalized_algorithm = match normalized_algorithm_result {
1317 Ok(normalized_algorithm) => normalized_algorithm,
1318 Err(error) => {
1319 promise.reject_error(error, can_gc);
1320 return promise;
1321 },
1322 };
1323
1324 let trusted_subtle = Trusted::new(self);
1330 let trusted_key = Trusted::new(key);
1331 let trusted_wrapping_key = Trusted::new(wrapping_key);
1332 let trusted_promise = TrustedPromise::new(promise.clone());
1333 self.global()
1334 .task_manager()
1335 .dom_manipulation_task_source()
1336 .queue(task!(wrap_key: move || {
1337 let subtle = trusted_subtle.root();
1338 let key = trusted_key.root();
1339 let wrapping_key = trusted_wrapping_key.root();
1340 let promise = trusted_promise.root();
1341
1342 if normalized_algorithm.name() != wrapping_key.algorithm().name() {
1350 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1351 return;
1352 }
1353
1354 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1357 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1358 return;
1359 }
1360
1361 if matches!(
1365 key.algorithm().name(),
1366 ALG_SHA1 | ALG_SHA256 | ALG_SHA384 | ALG_SHA512 | ALG_HKDF | ALG_PBKDF2
1367 ) {
1368 subtle.reject_promise_with_error(promise, Error::NotSupported(None));
1369 return;
1370 }
1371
1372
1373 if !key.Extractable() {
1376 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1377 return;
1378 }
1379
1380 let exported_key = match perform_export_key_operation(format, &key) {
1383 Ok(exported_key) => exported_key,
1384 Err(error) => {
1385 subtle.reject_promise_with_error(promise, error);
1386 return;
1387 },
1388 };
1389
1390 let cx = GlobalScope::get_cx();
1402 let bytes = match exported_key {
1403 ExportedKey::Bytes(bytes) => bytes,
1404 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1405 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1406 Err(error) => {
1407 subtle.reject_promise_with_error(promise, error);
1408 return;
1409 },
1410 },
1411 };
1412
1413 let mut result = normalized_algorithm.wrap_key(&wrapping_key, &bytes);
1425 if result.is_err() {
1426 result = normalized_algorithm.encrypt(&wrapping_key, &bytes);
1427 }
1428 let result = match result {
1429 Ok(result) => result,
1430 Err(error) => {
1431 subtle.reject_promise_with_error(promise, error);
1432 return;
1433 },
1434 };
1435
1436 subtle.resolve_promise_with_data(promise, result);
1442 }));
1443 promise
1444 }
1445
1446 fn UnwrapKey(
1448 &self,
1449 cx: JSContext,
1450 format: KeyFormat,
1451 wrapped_key: ArrayBufferViewOrArrayBuffer,
1452 unwrapping_key: &CryptoKey,
1453 algorithm: AlgorithmIdentifier,
1454 unwrapped_key_algorithm: AlgorithmIdentifier,
1455 extractable: bool,
1456 usages: Vec<KeyUsage>,
1457 comp: InRealm,
1458 can_gc: CanGc,
1459 ) -> Rc<Promise> {
1460 let wrapped_key = match wrapped_key {
1468 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1469 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1470 };
1471
1472 let mut normalized_algorithm =
1475 normalize_algorithm(cx, &Operation::UnwrapKey, &algorithm, can_gc);
1476
1477 if normalized_algorithm.is_err() {
1480 normalized_algorithm = normalize_algorithm(cx, &Operation::Decrypt, &algorithm, can_gc);
1481 }
1482
1483 let promise = Promise::new_in_current_realm(comp, can_gc);
1485 let normalized_algorithm = match normalized_algorithm {
1486 Ok(algorithm) => algorithm,
1487 Err(error) => {
1488 promise.reject_error(error, can_gc);
1489 return promise;
1490 },
1491 };
1492
1493 let normalized_key_algorithm = match normalize_algorithm(
1497 cx,
1498 &Operation::ImportKey,
1499 &unwrapped_key_algorithm,
1500 can_gc,
1501 ) {
1502 Ok(algorithm) => algorithm,
1503 Err(error) => {
1504 promise.reject_error(error, can_gc);
1505 return promise;
1506 },
1507 };
1508
1509 let trusted_subtle = Trusted::new(self);
1515 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1516 let trusted_promise = TrustedPromise::new(promise.clone());
1517 self.global().task_manager().dom_manipulation_task_source().queue(
1518 task!(unwrap_key: move || {
1519 let subtle = trusted_subtle.root();
1520 let unwrapping_key = trusted_unwrapping_key.root();
1521 let promise = trusted_promise.root();
1522
1523 if normalized_algorithm.name() != unwrapping_key.algorithm().name() {
1531 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1532 return;
1533 }
1534
1535 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1538 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1539 return;
1540 }
1541
1542 let mut bytes = normalized_algorithm.unwrap_key(&unwrapping_key, &wrapped_key);
1554 if bytes.is_err() {
1555 bytes = normalized_algorithm.decrypt(&unwrapping_key, &wrapped_key);
1556 }
1557 let bytes = match bytes {
1558 Ok(bytes) => bytes,
1559 Err(error) => {
1560 subtle.reject_promise_with_error(promise, error);
1561 return;
1562 },
1563 };
1564
1565 let cx = GlobalScope::get_cx();
1575 if format == KeyFormat::Jwk {
1576 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1577 subtle.reject_promise_with_error(promise, error);
1578 return;
1579 }
1580 }
1581 let key = bytes;
1582
1583 let result = match normalized_key_algorithm.import_key(
1587 &subtle.global(),
1588 format,
1589 &key,
1590 extractable,
1591 usages.clone(),
1592 CanGc::note(),
1593 ) {
1594 Ok(result) => result,
1595 Err(error) => {
1596 subtle.reject_promise_with_error(promise, error);
1597 return;
1598 },
1599 };
1600
1601 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1604 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1605 return;
1606 }
1607
1608 subtle.resolve_promise_with_key(promise, result);
1619 }),
1620 );
1621 promise
1622 }
1623}
1624
1625#[derive(Clone, Debug, MallocSizeOf)]
1630struct SubtleAlgorithm {
1631 name: String,
1633}
1634
1635impl From<Algorithm> for SubtleAlgorithm {
1636 fn from(params: Algorithm) -> Self {
1637 SubtleAlgorithm {
1638 name: params.name.to_string(),
1639 }
1640 }
1641}
1642
1643#[derive(Clone, Debug, MallocSizeOf)]
1645pub(crate) struct SubtleKeyAlgorithm {
1646 name: String,
1648}
1649
1650impl SubtleKeyAlgorithm {
1651 fn block_size_in_bits(&self) -> Result<u32, Error> {
1652 let size = match self.name.as_str() {
1653 ALG_SHA1 => 512,
1654 ALG_SHA256 => 512,
1655 ALG_SHA384 => 1024,
1656 ALG_SHA512 => 1024,
1657 _ => {
1658 return Err(Error::NotSupported(None));
1659 },
1660 };
1661
1662 Ok(size)
1663 }
1664}
1665
1666impl From<NormalizedAlgorithm> for SubtleKeyAlgorithm {
1667 fn from(value: NormalizedAlgorithm) -> Self {
1668 SubtleKeyAlgorithm {
1669 name: value.name().to_string(),
1670 }
1671 }
1672}
1673
1674impl SafeToJSValConvertible for SubtleKeyAlgorithm {
1675 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1676 let dictionary = KeyAlgorithm {
1677 name: self.name.clone().into(),
1678 };
1679 dictionary.safe_to_jsval(cx, rval, can_gc);
1680 }
1681}
1682
1683#[derive(Clone, Debug, MallocSizeOf)]
1685struct SubtleEcdsaParams {
1686 name: String,
1688
1689 hash: SubtleKeyAlgorithm,
1691}
1692
1693impl TryFrom<RootedTraceableBox<EcdsaParams>> for SubtleEcdsaParams {
1694 type Error = Error;
1695
1696 fn try_from(value: RootedTraceableBox<EcdsaParams>) -> Result<Self, Error> {
1697 let cx = GlobalScope::get_cx();
1698 let hash = normalize_algorithm(cx, &Operation::Digest, &value.hash, CanGc::note())?;
1699 Ok(SubtleEcdsaParams {
1700 name: value.parent.name.to_string(),
1701 hash: hash.into(),
1702 })
1703 }
1704}
1705
1706#[derive(Clone, Debug, MallocSizeOf)]
1708struct SubtleEcKeyGenParams {
1709 name: String,
1711
1712 named_curve: String,
1714}
1715
1716impl From<EcKeyGenParams> for SubtleEcKeyGenParams {
1717 fn from(value: EcKeyGenParams) -> Self {
1718 SubtleEcKeyGenParams {
1719 name: value.parent.name.to_string(),
1720 named_curve: value.namedCurve.to_string(),
1721 }
1722 }
1723}
1724
1725#[derive(Clone, Debug, MallocSizeOf)]
1727pub(crate) struct SubtleEcKeyAlgorithm {
1728 name: String,
1730
1731 named_curve: String,
1733}
1734
1735impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
1736 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1737 let parent = KeyAlgorithm {
1738 name: self.name.clone().into(),
1739 };
1740 let dictionary = EcKeyAlgorithm {
1741 parent,
1742 namedCurve: self.named_curve.clone().into(),
1743 };
1744 dictionary.safe_to_jsval(cx, rval, can_gc);
1745 }
1746}
1747
1748#[derive(Clone, Debug, MallocSizeOf)]
1750struct SubtleEcKeyImportParams {
1751 name: String,
1753
1754 named_curve: String,
1756}
1757
1758impl From<EcKeyImportParams> for SubtleEcKeyImportParams {
1759 fn from(value: EcKeyImportParams) -> Self {
1760 SubtleEcKeyImportParams {
1761 name: value.parent.name.to_string(),
1762 named_curve: value.namedCurve.to_string(),
1763 }
1764 }
1765}
1766
1767#[derive(Clone, MallocSizeOf)]
1769struct SubtleEcdhKeyDeriveParams {
1770 name: String,
1772
1773 public: Trusted<CryptoKey>,
1775}
1776
1777impl From<EcdhKeyDeriveParams> for SubtleEcdhKeyDeriveParams {
1778 fn from(value: EcdhKeyDeriveParams) -> Self {
1779 SubtleEcdhKeyDeriveParams {
1780 name: value.parent.name.to_string(),
1781 public: Trusted::new(&value.public),
1782 }
1783 }
1784}
1785
1786#[derive(Clone, Debug, MallocSizeOf)]
1788struct SubtleAesCtrParams {
1789 name: String,
1791
1792 counter: Vec<u8>,
1794
1795 length: u8,
1797}
1798
1799impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
1800 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
1801 let counter = match ¶ms.counter {
1802 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1803 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1804 };
1805 SubtleAesCtrParams {
1806 name: params.parent.name.to_string(),
1807 counter,
1808 length: params.length,
1809 }
1810 }
1811}
1812
1813#[derive(Clone, Debug, MallocSizeOf)]
1815pub(crate) struct SubtleAesKeyAlgorithm {
1816 name: String,
1818
1819 length: u16,
1821}
1822
1823impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
1824 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1825 let parent = KeyAlgorithm {
1826 name: self.name.clone().into(),
1827 };
1828 let dictionary = AesKeyAlgorithm {
1829 parent,
1830 length: self.length,
1831 };
1832 dictionary.safe_to_jsval(cx, rval, can_gc);
1833 }
1834}
1835
1836#[derive(Clone, Debug, MallocSizeOf)]
1838struct SubtleAesKeyGenParams {
1839 name: String,
1841
1842 length: u16,
1844}
1845
1846impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
1847 fn from(params: AesKeyGenParams) -> Self {
1848 SubtleAesKeyGenParams {
1849 name: params.parent.name.to_string(),
1850 length: params.length,
1851 }
1852 }
1853}
1854
1855#[derive(Clone, Debug, MallocSizeOf)]
1857struct SubtleAesDerivedKeyParams {
1858 name: String,
1860
1861 length: u16,
1863}
1864
1865impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
1866 fn from(params: AesDerivedKeyParams) -> Self {
1867 SubtleAesDerivedKeyParams {
1868 name: params.parent.name.to_string(),
1869 length: params.length,
1870 }
1871 }
1872}
1873
1874#[derive(Clone, Debug, MallocSizeOf)]
1876struct SubtleAesCbcParams {
1877 name: String,
1879
1880 iv: Vec<u8>,
1882}
1883
1884impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
1885 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
1886 let iv = match ¶ms.iv {
1887 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1888 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1889 };
1890 SubtleAesCbcParams {
1891 name: params.parent.name.to_string(),
1892 iv,
1893 }
1894 }
1895}
1896
1897#[derive(Clone, Debug, MallocSizeOf)]
1899struct SubtleAesGcmParams {
1900 name: String,
1902
1903 iv: Vec<u8>,
1905
1906 additional_data: Option<Vec<u8>>,
1908
1909 tag_length: Option<u8>,
1911}
1912
1913impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
1914 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
1915 let iv = match ¶ms.iv {
1916 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1917 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1918 };
1919 let additional_data = params.additionalData.as_ref().map(|data| match data {
1920 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1921 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1922 });
1923
1924 SubtleAesGcmParams {
1925 name: params.parent.name.to_string(),
1926 iv,
1927 additional_data,
1928 tag_length: params.tagLength,
1929 }
1930 }
1931}
1932
1933#[derive(Clone, Debug, MallocSizeOf)]
1935struct SubtleHmacImportParams {
1936 name: String,
1938
1939 hash: SubtleKeyAlgorithm,
1941
1942 length: Option<u32>,
1944}
1945
1946impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
1947 type Error = Error;
1948
1949 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
1950 let cx = GlobalScope::get_cx();
1951 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
1952 Ok(SubtleHmacImportParams {
1953 name: params.parent.name.to_string(),
1954 hash: hash.into(),
1955 length: params.length,
1956 })
1957 }
1958}
1959
1960#[derive(Clone, Debug, MallocSizeOf)]
1962pub(crate) struct SubtleHmacKeyAlgorithm {
1963 name: String,
1965
1966 hash: SubtleKeyAlgorithm,
1968
1969 length: u32,
1971}
1972
1973impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
1974 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
1975 let parent = KeyAlgorithm {
1976 name: self.name.clone().into(),
1977 };
1978 let hash = KeyAlgorithm {
1979 name: self.hash.name.clone().into(),
1980 };
1981 let dictionary = HmacKeyAlgorithm {
1982 parent,
1983 hash,
1984 length: self.length,
1985 };
1986 dictionary.safe_to_jsval(cx, rval, can_gc);
1987 }
1988}
1989
1990#[derive(Clone, Debug, MallocSizeOf)]
1992struct SubtleHmacKeyGenParams {
1993 name: String,
1995
1996 hash: SubtleKeyAlgorithm,
1998
1999 length: Option<u32>,
2001}
2002
2003impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
2004 type Error = Error;
2005
2006 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
2007 let cx = GlobalScope::get_cx();
2008 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
2009 Ok(SubtleHmacKeyGenParams {
2010 name: params.parent.name.to_string(),
2011 hash: hash.into(),
2012 length: params.length,
2013 })
2014 }
2015}
2016
2017#[derive(Clone, Debug, MallocSizeOf)]
2019pub(crate) struct SubtleHkdfParams {
2020 name: String,
2022
2023 hash: SubtleKeyAlgorithm,
2025
2026 salt: Vec<u8>,
2028
2029 info: Vec<u8>,
2031}
2032
2033impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
2034 type Error = Error;
2035
2036 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
2037 let cx = GlobalScope::get_cx();
2038 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
2039 let salt = match ¶ms.salt {
2040 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2041 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2042 };
2043 let info = match ¶ms.info {
2044 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2045 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2046 };
2047 Ok(SubtleHkdfParams {
2048 name: params.parent.name.to_string(),
2049 hash: hash.into(),
2050 salt,
2051 info,
2052 })
2053 }
2054}
2055
2056#[derive(Clone, Debug, MallocSizeOf)]
2058pub(crate) struct SubtlePbkdf2Params {
2059 name: String,
2061
2062 salt: Vec<u8>,
2064
2065 iterations: u32,
2067
2068 hash: SubtleKeyAlgorithm,
2070}
2071
2072impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
2073 type Error = Error;
2074
2075 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
2076 let cx = GlobalScope::get_cx();
2077 let salt = match ¶ms.salt {
2078 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2079 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2080 };
2081 let hash = normalize_algorithm(cx, &Operation::Digest, ¶ms.hash, CanGc::note())?;
2082 Ok(SubtlePbkdf2Params {
2083 name: params.parent.name.to_string(),
2084 salt,
2085 iterations: params.iterations,
2086 hash: hash.into(),
2087 })
2088 }
2089}
2090
2091#[derive(Clone, Debug, MallocSizeOf)]
2093struct SubtleAeadParams {
2094 name: String,
2096
2097 iv: Vec<u8>,
2099
2100 additional_data: Option<Vec<u8>>,
2102
2103 tag_length: Option<u8>,
2105}
2106
2107impl From<RootedTraceableBox<AeadParams>> for SubtleAeadParams {
2108 fn from(value: RootedTraceableBox<AeadParams>) -> Self {
2109 let iv = match &value.iv {
2110 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2111 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2112 };
2113 let additional_data = value.additionalData.as_ref().map(|data| match data {
2114 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2115 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2116 });
2117
2118 SubtleAeadParams {
2119 name: value.parent.name.to_string(),
2120 iv,
2121 additional_data,
2122 tag_length: value.tagLength,
2123 }
2124 }
2125}
2126
2127#[derive(Clone, Debug, MallocSizeOf)]
2129struct SubtleCShakeParams {
2130 name: String,
2132
2133 length: u32,
2135
2136 function_name: Option<Vec<u8>>,
2138
2139 customization: Option<Vec<u8>>,
2141}
2142
2143impl From<RootedTraceableBox<CShakeParams>> for SubtleCShakeParams {
2144 fn from(value: RootedTraceableBox<CShakeParams>) -> Self {
2145 let function_name = value
2146 .functionName
2147 .as_ref()
2148 .map(|function_name| match function_name {
2149 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2150 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2151 });
2152 let customization = value
2153 .customization
2154 .as_ref()
2155 .map(|customization| match customization {
2156 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2157 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2158 });
2159 SubtleCShakeParams {
2160 name: value.parent.name.to_string(),
2161 length: value.length,
2162 function_name,
2163 customization,
2164 }
2165 }
2166}
2167
2168#[derive(Clone, Debug, MallocSizeOf)]
2170struct SubtleArgon2Params {
2171 name: String,
2173
2174 nonce: Vec<u8>,
2176
2177 parallelism: u32,
2179
2180 memory: u32,
2182
2183 passes: u32,
2185
2186 version: Option<u8>,
2188
2189 secret_value: Option<Vec<u8>>,
2191
2192 associated_data: Option<Vec<u8>>,
2194}
2195
2196impl From<RootedTraceableBox<Argon2Params>> for SubtleArgon2Params {
2197 fn from(value: RootedTraceableBox<Argon2Params>) -> Self {
2198 let nonce = match &value.nonce {
2199 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2200 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2201 };
2202 let secret_value = value
2203 .secretValue
2204 .as_ref()
2205 .map(|secret_value| match secret_value {
2206 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2207 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2208 });
2209 let associated_data =
2210 value
2211 .associatedData
2212 .as_ref()
2213 .map(|associated_data| match associated_data {
2214 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2215 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2216 });
2217 SubtleArgon2Params {
2218 name: value.parent.name.to_string(),
2219 nonce,
2220 parallelism: value.parallelism,
2221 memory: value.memory,
2222 passes: value.passes,
2223 version: value.version,
2224 secret_value,
2225 associated_data,
2226 }
2227 }
2228}
2229
2230fn dictionary_from_jsval<T>(cx: JSContext, value: HandleValue, can_gc: CanGc) -> Fallible<T>
2232where
2233 T: SafeFromJSValConvertible<Config = ()>,
2234{
2235 let conversion = T::safe_from_jsval(cx, value, (), can_gc).map_err(|_| Error::JSFailed)?;
2236 match conversion {
2237 ConversionResult::Success(dictionary) => Ok(dictionary),
2238 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
2239 }
2240}
2241
2242enum ExportedKey {
2246 Bytes(Vec<u8>),
2247 Jwk(Box<JsonWebKey>),
2248}
2249
2250#[derive(Clone, Debug, MallocSizeOf)]
2254#[expect(clippy::enum_variant_names)]
2255pub(crate) enum KeyAlgorithmAndDerivatives {
2256 KeyAlgorithm(SubtleKeyAlgorithm),
2257 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
2258 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
2259 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
2260}
2261
2262impl KeyAlgorithmAndDerivatives {
2263 fn name(&self) -> &str {
2264 match self {
2265 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
2266 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => &algo.name,
2267 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
2268 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
2269 }
2270 }
2271}
2272
2273impl From<NormalizedAlgorithm> for KeyAlgorithmAndDerivatives {
2274 fn from(value: NormalizedAlgorithm) -> Self {
2275 KeyAlgorithmAndDerivatives::KeyAlgorithm(SubtleKeyAlgorithm {
2276 name: value.name().to_string(),
2277 })
2278 }
2279}
2280
2281impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
2282 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2283 match self {
2284 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
2285 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
2286 algo.safe_to_jsval(cx, rval, can_gc)
2287 },
2288 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
2289 algo.safe_to_jsval(cx, rval, can_gc)
2290 },
2291 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
2292 algo.safe_to_jsval(cx, rval, can_gc)
2293 },
2294 }
2295 }
2296}
2297
2298#[expect(unused)]
2299trait RsaOtherPrimesInfoExt {
2300 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error>;
2301}
2302
2303impl RsaOtherPrimesInfoExt for RsaOtherPrimesInfo {
2304 fn from_value(value: &serde_json::Value) -> Result<RsaOtherPrimesInfo, Error> {
2305 let serde_json::Value::Object(object) = value else {
2306 return Err(Error::Data(None));
2307 };
2308
2309 let mut rsa_other_primes_info: RsaOtherPrimesInfo = Default::default();
2310 for (key, value) in object {
2311 match key.as_str() {
2312 "r" => {
2313 rsa_other_primes_info.r =
2314 Some(DOMString::from(value.as_str().ok_or(Error::Data(None))?))
2315 },
2316 "d" => {
2317 rsa_other_primes_info.d =
2318 Some(DOMString::from(value.as_str().ok_or(Error::Data(None))?))
2319 },
2320 "t" => {
2321 rsa_other_primes_info.t =
2322 Some(DOMString::from(value.as_str().ok_or(Error::Data(None))?))
2323 },
2324 _ => {
2325 },
2328 }
2329 }
2330
2331 Ok(rsa_other_primes_info)
2332 }
2333}
2334
2335trait JsonWebKeyExt {
2336 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
2337 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
2338 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
2339 #[expect(unused)]
2340 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error>;
2341 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
2342}
2343
2344impl JsonWebKeyExt for JsonWebKey {
2345 #[expect(unsafe_code)]
2347 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
2348 let json = String::from_utf8_lossy(data);
2353
2354 let json: Vec<_> = json.encode_utf16().collect();
2356
2357 rooted!(in(*cx) let mut result = UndefinedValue());
2361 unsafe {
2362 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
2363 return Err(Error::JSFailed);
2364 }
2365 }
2366
2367 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
2369 Ok(ConversionResult::Success(key)) => key,
2370 Ok(ConversionResult::Failure(error)) => {
2371 return Err(Error::Type(error.to_string()));
2372 },
2373 Err(()) => {
2374 return Err(Error::JSFailed);
2375 },
2376 };
2377
2378 if key.kty.is_none() {
2380 return Err(Error::Data(None));
2381 }
2382
2383 Ok(key)
2385 }
2386
2387 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
2393 rooted!(in(*cx) let mut data = UndefinedValue());
2394 self.safe_to_jsval(cx, data.handle_mut(), CanGc::note());
2395 serialize_jsval_to_json_utf8(cx, data.handle())
2396 }
2397
2398 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
2399 let mut usages = vec![];
2400 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
2401 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
2402 }
2403 Ok(usages)
2404 }
2405
2406 fn get_rsa_other_primes_info_from_oth(&self) -> Result<&[RsaOtherPrimesInfo], Error> {
2407 self.oth.as_deref().ok_or(Error::Data(None))
2408 }
2409
2410 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
2414 if let Some(ref key_ops) = self.key_ops {
2416 if key_ops
2419 .iter()
2420 .collect::<std::collections::HashSet<_>>()
2421 .len() <
2422 key_ops.len()
2423 {
2424 return Err(Error::Data(None));
2425 }
2426 if let Some(ref use_) = self.use_ {
2429 if key_ops.iter().any(|op| op != use_) {
2430 return Err(Error::Data(None));
2431 }
2432 }
2433
2434 let key_ops_as_usages = self.get_usages_from_key_ops()?;
2436 if !specified_usages
2437 .iter()
2438 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
2439 {
2440 return Err(Error::Data(None));
2441 }
2442 }
2443
2444 Ok(())
2445 }
2446}
2447
2448#[derive(Clone, MallocSizeOf)]
2453enum NormalizedAlgorithm {
2454 Algorithm(SubtleAlgorithm),
2455 EcdsaParams(SubtleEcdsaParams),
2456 EcKeyGenParams(SubtleEcKeyGenParams),
2457 EcKeyImportParams(SubtleEcKeyImportParams),
2458 EcdhKeyDeriveParams(SubtleEcdhKeyDeriveParams),
2459 AesCtrParams(SubtleAesCtrParams),
2460 AesKeyGenParams(SubtleAesKeyGenParams),
2461 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
2462 AesCbcParams(SubtleAesCbcParams),
2463 AesGcmParams(SubtleAesGcmParams),
2464 HmacImportParams(SubtleHmacImportParams),
2465 HmacKeyGenParams(SubtleHmacKeyGenParams),
2466 HkdfParams(SubtleHkdfParams),
2467 Pbkdf2Params(SubtlePbkdf2Params),
2468 AeadParams(SubtleAeadParams),
2469 CShakeParams(SubtleCShakeParams),
2470 Argon2Params(SubtleArgon2Params),
2471}
2472
2473fn normalize_algorithm(
2475 cx: JSContext,
2476 op: &Operation,
2477 alg: &AlgorithmIdentifier,
2478 can_gc: CanGc,
2479) -> Result<NormalizedAlgorithm, Error> {
2480 match alg {
2481 ObjectOrString::String(name) => {
2483 let alg = Algorithm {
2487 name: name.to_owned(),
2488 };
2489 rooted!(in(*cx) let mut alg_value = UndefinedValue());
2490 alg.safe_to_jsval(cx, alg_value.handle_mut(), CanGc::note());
2491 let alg_obj = RootedTraceableBox::new(Heap::default());
2492 alg_obj.set(alg_value.to_object());
2493 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj), can_gc)
2494 },
2495 ObjectOrString::Object(obj) => {
2497 rooted!(in(*cx) let value = ObjectValue(obj.get()));
2506 let initial_alg = dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2507
2508 let Some(&alg_name) = SUPPORTED_ALGORITHMS.iter().find(|supported_algorithm| {
2516 supported_algorithm.eq_ignore_ascii_case(&initial_alg.name.str())
2517 }) else {
2518 return Err(Error::NotSupported(None));
2519 };
2520
2521 let normalized_algorithm = match (alg_name, op) {
2557 (ALG_ECDSA, Operation::Sign) => {
2559 let mut params = dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(
2560 cx,
2561 value.handle(),
2562 can_gc,
2563 )?;
2564 params.parent.name = DOMString::from(alg_name);
2565 NormalizedAlgorithm::EcdsaParams(params.try_into()?)
2566 },
2567 (ALG_ECDSA, Operation::Verify) => {
2568 let mut params = dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(
2569 cx,
2570 value.handle(),
2571 can_gc,
2572 )?;
2573 params.parent.name = DOMString::from(alg_name);
2574 NormalizedAlgorithm::EcdsaParams(params.try_into()?)
2575 },
2576 (ALG_ECDSA, Operation::GenerateKey) => {
2577 let mut params =
2578 dictionary_from_jsval::<EcKeyGenParams>(cx, value.handle(), can_gc)?;
2579 params.parent.name = DOMString::from(alg_name);
2580 NormalizedAlgorithm::EcKeyGenParams(params.into())
2581 },
2582 (ALG_ECDSA, Operation::ImportKey) => {
2583 let mut params =
2584 dictionary_from_jsval::<EcKeyImportParams>(cx, value.handle(), can_gc)?;
2585 params.parent.name = DOMString::from(alg_name);
2586 NormalizedAlgorithm::EcKeyImportParams(params.into())
2587 },
2588 (ALG_ECDSA, Operation::ExportKey) => {
2589 let mut params =
2590 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2591 params.name = DOMString::from(alg_name);
2592 NormalizedAlgorithm::Algorithm(params.into())
2593 },
2594
2595 (ALG_ECDH, Operation::GenerateKey) => {
2597 let mut params =
2598 dictionary_from_jsval::<EcKeyGenParams>(cx, value.handle(), can_gc)?;
2599 params.parent.name = DOMString::from(alg_name);
2600 NormalizedAlgorithm::EcKeyGenParams(params.into())
2601 },
2602 (ALG_ECDH, Operation::DeriveBits) => {
2603 let mut params =
2604 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value.handle(), can_gc)?;
2605 params.parent.name = DOMString::from(alg_name);
2606 NormalizedAlgorithm::EcdhKeyDeriveParams(params.into())
2607 },
2608 (ALG_ECDH, Operation::ImportKey) => {
2609 let mut params =
2610 dictionary_from_jsval::<EcKeyImportParams>(cx, value.handle(), can_gc)?;
2611 params.parent.name = DOMString::from(alg_name);
2612 NormalizedAlgorithm::EcKeyImportParams(params.into())
2613 },
2614 (ALG_ECDH, Operation::ExportKey) => {
2615 let mut params =
2616 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2617 params.name = DOMString::from(alg_name);
2618 NormalizedAlgorithm::Algorithm(params.into())
2619 },
2620
2621 (ALG_ED25519, Operation::Sign) => {
2623 let mut params =
2624 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2625 params.name = DOMString::from(alg_name);
2626 NormalizedAlgorithm::Algorithm(params.into())
2627 },
2628 (ALG_ED25519, Operation::Verify) => {
2629 let mut params =
2630 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2631 params.name = DOMString::from(alg_name);
2632 NormalizedAlgorithm::Algorithm(params.into())
2633 },
2634 (ALG_ED25519, Operation::GenerateKey) => {
2635 let mut params =
2636 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2637 params.name = DOMString::from(alg_name);
2638 NormalizedAlgorithm::Algorithm(params.into())
2639 },
2640 (ALG_ED25519, Operation::ImportKey) => {
2641 let mut params =
2642 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2643 params.name = DOMString::from(alg_name);
2644 NormalizedAlgorithm::Algorithm(params.into())
2645 },
2646 (ALG_ED25519, Operation::ExportKey) => {
2647 let mut params =
2648 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2649 params.name = DOMString::from(alg_name);
2650 NormalizedAlgorithm::Algorithm(params.into())
2651 },
2652
2653 (ALG_X25519, Operation::DeriveBits) => {
2655 let mut params =
2656 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value.handle(), can_gc)?;
2657 params.parent.name = DOMString::from(alg_name);
2658 NormalizedAlgorithm::EcdhKeyDeriveParams(params.into())
2659 },
2660 (ALG_X25519, Operation::GenerateKey) => {
2661 let mut params =
2662 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2663 params.name = DOMString::from(alg_name);
2664 NormalizedAlgorithm::Algorithm(params.into())
2665 },
2666 (ALG_X25519, Operation::ImportKey) => {
2667 let mut params =
2668 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2669 params.name = DOMString::from(alg_name);
2670 NormalizedAlgorithm::Algorithm(params.into())
2671 },
2672 (ALG_X25519, Operation::ExportKey) => {
2673 let mut params =
2674 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2675 params.name = DOMString::from(alg_name);
2676 NormalizedAlgorithm::Algorithm(params.into())
2677 },
2678
2679 (ALG_AES_CTR, Operation::Encrypt) => {
2681 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2682 cx,
2683 value.handle(),
2684 can_gc,
2685 )?;
2686 params.parent.name = DOMString::from(alg_name);
2687 NormalizedAlgorithm::AesCtrParams(params.into())
2688 },
2689 (ALG_AES_CTR, Operation::Decrypt) => {
2690 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(
2691 cx,
2692 value.handle(),
2693 can_gc,
2694 )?;
2695 params.parent.name = DOMString::from(alg_name);
2696 NormalizedAlgorithm::AesCtrParams(params.into())
2697 },
2698 (ALG_AES_CTR, Operation::GenerateKey) => {
2699 let mut params =
2700 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2701 params.parent.name = DOMString::from(alg_name);
2702 NormalizedAlgorithm::AesKeyGenParams(params.into())
2703 },
2704 (ALG_AES_CTR, Operation::ImportKey) => {
2705 let mut params =
2706 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2707 params.name = DOMString::from(alg_name);
2708 NormalizedAlgorithm::Algorithm(params.into())
2709 },
2710 (ALG_AES_CTR, Operation::ExportKey) => {
2711 let mut params =
2712 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2713 params.name = DOMString::from(alg_name);
2714 NormalizedAlgorithm::Algorithm(params.into())
2715 },
2716 (ALG_AES_CTR, Operation::GetKeyLength) => {
2717 let mut params =
2718 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2719 params.parent.name = DOMString::from(alg_name);
2720 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2721 },
2722
2723 (ALG_AES_CBC, Operation::Encrypt) => {
2725 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2726 cx,
2727 value.handle(),
2728 can_gc,
2729 )?;
2730 params.parent.name = DOMString::from(alg_name);
2731 NormalizedAlgorithm::AesCbcParams(params.into())
2732 },
2733 (ALG_AES_CBC, Operation::Decrypt) => {
2734 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(
2735 cx,
2736 value.handle(),
2737 can_gc,
2738 )?;
2739 params.parent.name = DOMString::from(alg_name);
2740 NormalizedAlgorithm::AesCbcParams(params.into())
2741 },
2742 (ALG_AES_CBC, Operation::GenerateKey) => {
2743 let mut params =
2744 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2745 params.parent.name = DOMString::from(alg_name);
2746 NormalizedAlgorithm::AesKeyGenParams(params.into())
2747 },
2748 (ALG_AES_CBC, Operation::ImportKey) => {
2749 let mut params =
2750 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2751 params.name = DOMString::from(alg_name);
2752 NormalizedAlgorithm::Algorithm(params.into())
2753 },
2754 (ALG_AES_CBC, Operation::ExportKey) => {
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_AES_CBC, Operation::GetKeyLength) => {
2761 let mut params =
2762 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2763 params.parent.name = DOMString::from(alg_name);
2764 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2765 },
2766
2767 (ALG_AES_GCM, Operation::Encrypt) => {
2769 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2770 cx,
2771 value.handle(),
2772 can_gc,
2773 )?;
2774 params.parent.name = DOMString::from(alg_name);
2775 NormalizedAlgorithm::AesGcmParams(params.into())
2776 },
2777 (ALG_AES_GCM, Operation::Decrypt) => {
2778 let mut params = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(
2779 cx,
2780 value.handle(),
2781 can_gc,
2782 )?;
2783 params.parent.name = DOMString::from(alg_name);
2784 NormalizedAlgorithm::AesGcmParams(params.into())
2785 },
2786 (ALG_AES_GCM, Operation::GenerateKey) => {
2787 let mut params =
2788 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2789 params.parent.name = DOMString::from(alg_name);
2790 NormalizedAlgorithm::AesKeyGenParams(params.into())
2791 },
2792 (ALG_AES_GCM, Operation::ImportKey) => {
2793 let mut params =
2794 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2795 params.name = DOMString::from(alg_name);
2796 NormalizedAlgorithm::Algorithm(params.into())
2797 },
2798 (ALG_AES_GCM, Operation::ExportKey) => {
2799 let mut params =
2800 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2801 params.name = DOMString::from(alg_name);
2802 NormalizedAlgorithm::Algorithm(params.into())
2803 },
2804 (ALG_AES_GCM, Operation::GetKeyLength) => {
2805 let mut params =
2806 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2807 params.parent.name = DOMString::from(alg_name);
2808 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2809 },
2810
2811 (ALG_AES_KW, Operation::WrapKey) => {
2813 let mut params =
2814 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2815 params.name = DOMString::from(alg_name);
2816 NormalizedAlgorithm::Algorithm(params.into())
2817 },
2818 (ALG_AES_KW, Operation::UnwrapKey) => {
2819 let mut params =
2820 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2821 params.name = DOMString::from(alg_name);
2822 NormalizedAlgorithm::Algorithm(params.into())
2823 },
2824 (ALG_AES_KW, Operation::GenerateKey) => {
2825 let mut params =
2826 dictionary_from_jsval::<AesKeyGenParams>(cx, value.handle(), can_gc)?;
2827 params.parent.name = DOMString::from(alg_name);
2828 NormalizedAlgorithm::AesKeyGenParams(params.into())
2829 },
2830 (ALG_AES_KW, Operation::ImportKey) => {
2831 let mut params =
2832 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2833 params.name = DOMString::from(alg_name);
2834 NormalizedAlgorithm::Algorithm(params.into())
2835 },
2836 (ALG_AES_KW, Operation::ExportKey) => {
2837 let mut params =
2838 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2839 params.name = DOMString::from(alg_name);
2840 NormalizedAlgorithm::Algorithm(params.into())
2841 },
2842 (ALG_AES_KW, Operation::GetKeyLength) => {
2843 let mut params =
2844 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value.handle(), can_gc)?;
2845 params.parent.name = DOMString::from(alg_name);
2846 NormalizedAlgorithm::AesDerivedKeyParams(params.into())
2847 },
2848
2849 (ALG_HMAC, Operation::Sign) => {
2851 let mut params =
2852 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2853 params.name = DOMString::from(alg_name);
2854 NormalizedAlgorithm::Algorithm(params.into())
2855 },
2856 (ALG_HMAC, Operation::Verify) => {
2857 let mut params =
2858 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2859 params.name = DOMString::from(alg_name);
2860 NormalizedAlgorithm::Algorithm(params.into())
2861 },
2862 (ALG_HMAC, Operation::GenerateKey) => {
2863 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(
2864 cx,
2865 value.handle(),
2866 can_gc,
2867 )?;
2868 params.parent.name = DOMString::from(alg_name);
2869 NormalizedAlgorithm::HmacKeyGenParams(params.try_into()?)
2870 },
2871 (ALG_HMAC, Operation::ImportKey) => {
2872 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2873 cx,
2874 value.handle(),
2875 can_gc,
2876 )?;
2877 params.parent.name = DOMString::from(alg_name);
2878 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2879 },
2880 (ALG_HMAC, Operation::ExportKey) => {
2881 let mut params =
2882 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2883 params.name = DOMString::from(alg_name);
2884 NormalizedAlgorithm::Algorithm(params.into())
2885 },
2886 (ALG_HMAC, Operation::GetKeyLength) => {
2887 let mut params = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(
2888 cx,
2889 value.handle(),
2890 can_gc,
2891 )?;
2892 params.parent.name = DOMString::from(alg_name);
2893 NormalizedAlgorithm::HmacImportParams(params.try_into()?)
2894 },
2895
2896 (ALG_SHA1, Operation::Digest) => {
2898 let mut params =
2899 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2900 params.name = DOMString::from(alg_name);
2901 NormalizedAlgorithm::Algorithm(params.into())
2902 },
2903 (ALG_SHA256, Operation::Digest) => {
2904 let mut params =
2905 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2906 params.name = DOMString::from(alg_name);
2907 NormalizedAlgorithm::Algorithm(params.into())
2908 },
2909 (ALG_SHA384, Operation::Digest) => {
2910 let mut params =
2911 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2912 params.name = DOMString::from(alg_name);
2913 NormalizedAlgorithm::Algorithm(params.into())
2914 },
2915 (ALG_SHA512, Operation::Digest) => {
2916 let mut params =
2917 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2918 params.name = DOMString::from(alg_name);
2919 NormalizedAlgorithm::Algorithm(params.into())
2920 },
2921
2922 (ALG_HKDF, Operation::DeriveBits) => {
2924 let mut params = dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(
2925 cx,
2926 value.handle(),
2927 can_gc,
2928 )?;
2929 params.parent.name = DOMString::from(alg_name);
2930 NormalizedAlgorithm::HkdfParams(params.try_into()?)
2931 },
2932 (ALG_HKDF, Operation::ImportKey) => {
2933 let mut params =
2934 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2935 params.name = DOMString::from(alg_name);
2936 NormalizedAlgorithm::Algorithm(params.into())
2937 },
2938 (ALG_HKDF, Operation::GetKeyLength) => {
2939 let mut params =
2940 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2941 params.name = DOMString::from(alg_name);
2942 NormalizedAlgorithm::Algorithm(params.into())
2943 },
2944
2945 (ALG_PBKDF2, Operation::DeriveBits) => {
2947 let mut params = dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(
2948 cx,
2949 value.handle(),
2950 can_gc,
2951 )?;
2952 params.parent.name = DOMString::from(alg_name);
2953 NormalizedAlgorithm::Pbkdf2Params(params.try_into()?)
2954 },
2955 (ALG_PBKDF2, Operation::ImportKey) => {
2956 let mut params =
2957 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2958 params.name = DOMString::from(alg_name);
2959 NormalizedAlgorithm::Algorithm(params.into())
2960 },
2961 (ALG_PBKDF2, Operation::GetKeyLength) => {
2962 let mut params =
2963 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2964 params.name = DOMString::from(alg_name);
2965 NormalizedAlgorithm::Algorithm(params.into())
2966 },
2967
2968 (ALG_CHACHA20_POLY1305, Operation::Encrypt) => {
2970 let mut params = dictionary_from_jsval::<RootedTraceableBox<AeadParams>>(
2971 cx,
2972 value.handle(),
2973 can_gc,
2974 )?;
2975 params.parent.name = DOMString::from(alg_name);
2976 NormalizedAlgorithm::AeadParams(params.into())
2977 },
2978 (ALG_CHACHA20_POLY1305, Operation::Decrypt) => {
2979 let mut params = dictionary_from_jsval::<RootedTraceableBox<AeadParams>>(
2980 cx,
2981 value.handle(),
2982 can_gc,
2983 )?;
2984 params.parent.name = DOMString::from(alg_name);
2985 NormalizedAlgorithm::AeadParams(params.into())
2986 },
2987 (ALG_CHACHA20_POLY1305, Operation::GenerateKey) => {
2988 let mut params =
2989 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2990 params.name = DOMString::from(alg_name);
2991 NormalizedAlgorithm::Algorithm(params.into())
2992 },
2993 (ALG_CHACHA20_POLY1305, Operation::ImportKey) => {
2994 let mut params =
2995 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
2996 params.name = DOMString::from(alg_name);
2997 NormalizedAlgorithm::Algorithm(params.into())
2998 },
2999 (ALG_CHACHA20_POLY1305, Operation::ExportKey) => {
3000 let mut params =
3001 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3002 params.name = DOMString::from(alg_name);
3003 NormalizedAlgorithm::Algorithm(params.into())
3004 },
3005 (ALG_CHACHA20_POLY1305, Operation::GetKeyLength) => {
3006 let mut params =
3007 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3008 params.name = DOMString::from(alg_name);
3009 NormalizedAlgorithm::Algorithm(params.into())
3010 },
3011
3012 (ALG_SHA3_256, Operation::Digest) => {
3014 let mut params =
3015 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3016 params.name = DOMString::from(alg_name);
3017 NormalizedAlgorithm::Algorithm(params.into())
3018 },
3019 (ALG_SHA3_384, Operation::Digest) => {
3020 let mut params =
3021 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3022 params.name = DOMString::from(alg_name);
3023 NormalizedAlgorithm::Algorithm(params.into())
3024 },
3025 (ALG_SHA3_512, Operation::Digest) => {
3026 let mut params =
3027 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3028 params.name = DOMString::from(alg_name);
3029 NormalizedAlgorithm::Algorithm(params.into())
3030 },
3031
3032 (ALG_CSHAKE_128, Operation::Digest) => {
3034 let mut params = dictionary_from_jsval::<RootedTraceableBox<CShakeParams>>(
3035 cx,
3036 value.handle(),
3037 can_gc,
3038 )?;
3039 params.parent.name = DOMString::from(alg_name);
3040 NormalizedAlgorithm::CShakeParams(params.into())
3041 },
3042 (ALG_CSHAKE_256, Operation::Digest) => {
3043 let mut params = dictionary_from_jsval::<RootedTraceableBox<CShakeParams>>(
3044 cx,
3045 value.handle(),
3046 can_gc,
3047 )?;
3048 params.parent.name = DOMString::from(alg_name);
3049 NormalizedAlgorithm::CShakeParams(params.into())
3050 },
3051
3052 (ALG_ARGON2D | ALG_ARGON2I | ALG_ARGON2ID, Operation::DeriveBits) => {
3054 let mut params = dictionary_from_jsval::<RootedTraceableBox<Argon2Params>>(
3055 cx,
3056 value.handle(),
3057 can_gc,
3058 )?;
3059 params.parent.name = DOMString::from(alg_name);
3060 NormalizedAlgorithm::Argon2Params(params.into())
3061 },
3062 (ALG_ARGON2D | ALG_ARGON2I | ALG_ARGON2ID, Operation::ImportKey) => {
3063 let mut params =
3064 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3065 params.name = DOMString::from(alg_name);
3066 NormalizedAlgorithm::Algorithm(params.into())
3067 },
3068 (ALG_ARGON2D | ALG_ARGON2I | ALG_ARGON2ID, Operation::GetKeyLength) => {
3069 let mut params =
3070 dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3071 params.name = DOMString::from(alg_name);
3072 NormalizedAlgorithm::Algorithm(params.into())
3073 },
3074
3075 _ => return Err(Error::NotSupported(None)),
3076 };
3077
3078 Ok(normalized_algorithm)
3080 },
3081 }
3082}
3083
3084impl NormalizedAlgorithm {
3085 fn name(&self) -> &str {
3087 match self {
3088 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
3089 NormalizedAlgorithm::EcdsaParams(algo) => &algo.name,
3090 NormalizedAlgorithm::EcKeyGenParams(algo) => &algo.name,
3091 NormalizedAlgorithm::EcKeyImportParams(algo) => &algo.name,
3092 NormalizedAlgorithm::EcdhKeyDeriveParams(algo) => &algo.name,
3093 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
3094 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
3095 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
3096 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
3097 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
3098 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
3099 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
3100 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
3101 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
3102 NormalizedAlgorithm::AeadParams(algo) => &algo.name,
3103 NormalizedAlgorithm::CShakeParams(algo) => &algo.name,
3104 NormalizedAlgorithm::Argon2Params(algo) => &algo.name,
3105 }
3106 }
3107
3108 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
3109 match (self.name(), self) {
3110 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
3111 aes_operation::encrypt_aes_ctr(algo, key, plaintext)
3112 },
3113 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
3114 aes_operation::encrypt_aes_cbc(algo, key, plaintext)
3115 },
3116 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
3117 aes_operation::encrypt_aes_gcm(algo, key, plaintext)
3118 },
3119 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
3120 chacha20_poly1305_operation::encrypt(algo, key, plaintext)
3121 },
3122 _ => Err(Error::NotSupported(None)),
3123 }
3124 }
3125
3126 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
3127 match (self.name(), self) {
3128 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
3129 aes_operation::decrypt_aes_ctr(algo, key, ciphertext)
3130 },
3131 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
3132 aes_operation::decrypt_aes_cbc(algo, key, ciphertext)
3133 },
3134 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
3135 aes_operation::decrypt_aes_gcm(algo, key, ciphertext)
3136 },
3137 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
3138 chacha20_poly1305_operation::decrypt(algo, key, ciphertext)
3139 },
3140 _ => Err(Error::NotSupported(None)),
3141 }
3142 }
3143
3144 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
3145 match (self.name(), self) {
3146 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
3147 ecdsa_operation::sign(algo, key, message)
3148 },
3149 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3150 ed25519_operation::sign(key, message)
3151 },
3152 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => hmac_operation::sign(key, message),
3153 _ => Err(Error::NotSupported(None)),
3154 }
3155 }
3156
3157 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
3158 match (self.name(), self) {
3159 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
3160 ecdsa_operation::verify(algo, key, message, signature)
3161 },
3162 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3163 ed25519_operation::verify(key, message, signature)
3164 },
3165 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => {
3166 hmac_operation::verify(key, message, signature)
3167 },
3168 _ => Err(Error::NotSupported(None)),
3169 }
3170 }
3171
3172 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
3173 match (self.name(), self) {
3174 (ALG_SHA1, NormalizedAlgorithm::Algorithm(algo)) => {
3175 sha_operation::digest(algo, message)
3176 },
3177 (ALG_SHA256, NormalizedAlgorithm::Algorithm(algo)) => {
3178 sha_operation::digest(algo, message)
3179 },
3180 (ALG_SHA384, NormalizedAlgorithm::Algorithm(algo)) => {
3181 sha_operation::digest(algo, message)
3182 },
3183 (ALG_SHA512, NormalizedAlgorithm::Algorithm(algo)) => {
3184 sha_operation::digest(algo, message)
3185 },
3186 (ALG_SHA3_256, NormalizedAlgorithm::Algorithm(algo)) => {
3187 sha3_operation::digest(algo, message)
3188 },
3189 (ALG_SHA3_384, NormalizedAlgorithm::Algorithm(algo)) => {
3190 sha3_operation::digest(algo, message)
3191 },
3192 (ALG_SHA3_512, NormalizedAlgorithm::Algorithm(algo)) => {
3193 sha3_operation::digest(algo, message)
3194 },
3195 (ALG_CSHAKE_128, NormalizedAlgorithm::CShakeParams(algo)) => {
3196 cshake_operation::digest(algo, message)
3197 },
3198 (ALG_CSHAKE_256, NormalizedAlgorithm::CShakeParams(algo)) => {
3199 cshake_operation::digest(algo, message)
3200 },
3201 _ => Err(Error::NotSupported(None)),
3202 }
3203 }
3204
3205 fn generate_key(
3206 &self,
3207 global: &GlobalScope,
3208 extractable: bool,
3209 usages: Vec<KeyUsage>,
3210 can_gc: CanGc,
3211 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
3212 match (self.name(), self) {
3213 (ALG_ECDSA, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
3214 ecdsa_operation::generate_key(global, algo, extractable, usages, can_gc)
3215 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
3216 },
3217 (ALG_ECDH, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
3218 ecdh_operation::generate_key(global, algo, extractable, usages, can_gc)
3219 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
3220 },
3221 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3222 ed25519_operation::generate_key(global, extractable, usages, can_gc)
3223 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
3224 },
3225 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3226 x25519_operation::generate_key(global, extractable, usages, can_gc)
3227 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
3228 },
3229 (ALG_AES_CTR, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
3230 aes_operation::generate_key_aes_ctr(global, algo, extractable, usages, can_gc)
3231 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3232 },
3233 (ALG_AES_CBC, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
3234 aes_operation::generate_key_aes_cbc(global, algo, extractable, usages, can_gc)
3235 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3236 },
3237 (ALG_AES_GCM, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
3238 aes_operation::generate_key_aes_gcm(global, algo, extractable, usages, can_gc)
3239 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3240 },
3241 (ALG_AES_KW, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
3242 aes_operation::generate_key_aes_kw(global, algo, extractable, usages, can_gc)
3243 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3244 },
3245 (ALG_HMAC, NormalizedAlgorithm::HmacKeyGenParams(algo)) => {
3246 hmac_operation::generate_key(global, algo, extractable, usages, can_gc)
3247 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3248 },
3249 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
3250 chacha20_poly1305_operation::generate_key(global, extractable, usages, can_gc)
3251 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
3252 },
3253 _ => Err(Error::NotSupported(None)),
3254 }
3255 }
3256
3257 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
3258 match (self.name(), self) {
3259 (ALG_ECDH, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
3260 ecdh_operation::derive_bits(algo, key, length)
3261 },
3262 (ALG_X25519, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
3263 x25519_operation::derive_bits(algo, key, length)
3264 },
3265 (ALG_HKDF, NormalizedAlgorithm::HkdfParams(algo)) => {
3266 hkdf_operation::derive_bits(algo, key, length)
3267 },
3268 (ALG_PBKDF2, NormalizedAlgorithm::Pbkdf2Params(algo)) => {
3269 pbkdf2_operation::derive_bits(algo, key, length)
3270 },
3271 (ALG_ARGON2D, NormalizedAlgorithm::Argon2Params(algo)) => {
3272 argon2_operation::derive_bits(algo, key, length)
3273 },
3274 (ALG_ARGON2I, NormalizedAlgorithm::Argon2Params(algo)) => {
3275 argon2_operation::derive_bits(algo, key, length)
3276 },
3277 (ALG_ARGON2ID, NormalizedAlgorithm::Argon2Params(algo)) => {
3278 argon2_operation::derive_bits(algo, key, length)
3279 },
3280 _ => Err(Error::NotSupported(None)),
3281 }
3282 }
3283
3284 fn import_key(
3285 &self,
3286 global: &GlobalScope,
3287 format: KeyFormat,
3288 key_data: &[u8],
3289 extractable: bool,
3290 usages: Vec<KeyUsage>,
3291 can_gc: CanGc,
3292 ) -> Result<DomRoot<CryptoKey>, Error> {
3293 match (self.name(), self) {
3294 (ALG_ECDSA, NormalizedAlgorithm::EcKeyImportParams(algo)) => {
3295 ecdsa_operation::import_key(
3296 global,
3297 algo,
3298 format,
3299 key_data,
3300 extractable,
3301 usages,
3302 can_gc,
3303 )
3304 },
3305 (ALG_ECDH, NormalizedAlgorithm::EcKeyImportParams(algo)) => ecdh_operation::import_key(
3306 global,
3307 algo,
3308 format,
3309 key_data,
3310 extractable,
3311 usages,
3312 can_gc,
3313 ),
3314 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3315 ed25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3316 },
3317 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
3318 x25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3319 },
3320 (ALG_AES_CTR, NormalizedAlgorithm::Algorithm(_algo)) => {
3321 aes_operation::import_key_aes_ctr(
3322 global,
3323 format,
3324 key_data,
3325 extractable,
3326 usages,
3327 can_gc,
3328 )
3329 },
3330 (ALG_AES_CBC, NormalizedAlgorithm::Algorithm(_algo)) => {
3331 aes_operation::import_key_aes_cbc(
3332 global,
3333 format,
3334 key_data,
3335 extractable,
3336 usages,
3337 can_gc,
3338 )
3339 },
3340 (ALG_AES_GCM, NormalizedAlgorithm::Algorithm(_algo)) => {
3341 aes_operation::import_key_aes_gcm(
3342 global,
3343 format,
3344 key_data,
3345 extractable,
3346 usages,
3347 can_gc,
3348 )
3349 },
3350 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3351 aes_operation::import_key_aes_kw(
3352 global,
3353 format,
3354 key_data,
3355 extractable,
3356 usages,
3357 can_gc,
3358 )
3359 },
3360 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => hmac_operation::import_key(
3361 global,
3362 algo,
3363 format,
3364 key_data,
3365 extractable,
3366 usages,
3367 can_gc,
3368 ),
3369 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => {
3370 hkdf_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3371 },
3372 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
3373 pbkdf2_operation::import_key(global, format, key_data, extractable, usages, can_gc)
3374 },
3375 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
3376 chacha20_poly1305_operation::import_key(
3377 global,
3378 format,
3379 key_data,
3380 extractable,
3381 usages,
3382 can_gc,
3383 )
3384 },
3385 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
3386 global,
3387 algo,
3388 format,
3389 key_data,
3390 extractable,
3391 usages,
3392 can_gc,
3393 ),
3394 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
3395 global,
3396 algo,
3397 format,
3398 key_data,
3399 extractable,
3400 usages,
3401 can_gc,
3402 ),
3403 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
3404 global,
3405 algo,
3406 format,
3407 key_data,
3408 extractable,
3409 usages,
3410 can_gc,
3411 ),
3412 _ => Err(Error::NotSupported(None)),
3413 }
3414 }
3415
3416 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
3417 match (self.name(), self) {
3418 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3419 aes_operation::wrap_key_aes_kw(key, plaintext)
3420 },
3421 _ => Err(Error::NotSupported(None)),
3422 }
3423 }
3424
3425 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
3426 match (self.name(), self) {
3427 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
3428 aes_operation::unwrap_key_aes_kw(key, ciphertext)
3429 },
3430 _ => Err(Error::NotSupported(None)),
3431 }
3432 }
3433
3434 fn get_key_length(&self) -> Result<Option<u32>, Error> {
3435 match (self.name(), self) {
3436 (ALG_AES_CTR, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3437 aes_operation::get_key_length_aes_ctr(algo)
3438 },
3439 (ALG_AES_CBC, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3440 aes_operation::get_key_length_aes_cbc(algo)
3441 },
3442 (ALG_AES_GCM, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3443 aes_operation::get_key_length_aes_gcm(algo)
3444 },
3445 (ALG_AES_KW, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
3446 aes_operation::get_key_length_aes_kw(algo)
3447 },
3448 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => {
3449 hmac_operation::get_key_length(algo)
3450 },
3451 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => hkdf_operation::get_key_length(),
3452 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
3453 pbkdf2_operation::get_key_length()
3454 },
3455 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
3456 chacha20_poly1305_operation::get_key_length()
3457 },
3458 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(_algo)) => {
3459 argon2_operation::get_key_length()
3460 },
3461 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(_algo)) => {
3462 argon2_operation::get_key_length()
3463 },
3464 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(_algo)) => {
3465 argon2_operation::get_key_length()
3466 },
3467 _ => Err(Error::NotSupported(None)),
3468 }
3469 }
3470}
3471
3472fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
3479 match key.algorithm().name() {
3480 ALG_ECDSA => ecdsa_operation::export_key(format, key),
3481 ALG_ECDH => ecdh_operation::export_key(format, key),
3482 ALG_ED25519 => ed25519_operation::export_key(format, key),
3483 ALG_X25519 => x25519_operation::export_key(format, key),
3484 ALG_AES_CTR => aes_operation::export_key_aes_ctr(format, key),
3485 ALG_AES_CBC => aes_operation::export_key_aes_cbc(format, key),
3486 ALG_AES_GCM => aes_operation::export_key_aes_gcm(format, key),
3487 ALG_AES_KW => aes_operation::export_key_aes_kw(format, key),
3488 ALG_HMAC => hmac_operation::export_key(format, key),
3489 ALG_CHACHA20_POLY1305 => chacha20_poly1305_operation::export_key(format, key),
3490 _ => Err(Error::NotSupported(None)),
3491 }
3492}