1mod aes_cbc_operation;
6mod aes_common;
7mod aes_ctr_operation;
8mod aes_gcm_operation;
9mod aes_kw_operation;
10mod aes_ocb_operation;
11mod argon2_operation;
12mod chacha20_poly1305_operation;
13mod cshake_operation;
14mod ecdh_operation;
15mod ecdsa_operation;
16mod ed25519_operation;
17mod hkdf_operation;
18mod hmac_operation;
19mod ml_dsa_operation;
20mod ml_kem_operation;
21mod pbkdf2_operation;
22mod rsa_common;
23mod rsa_oaep_operation;
24mod rsa_pss_operation;
25mod rsassa_pkcs1_v1_5_operation;
26mod sha3_operation;
27mod sha_operation;
28mod x25519_operation;
29
30use std::fmt::Display;
31use std::ptr;
32use std::rc::Rc;
33use std::str::FromStr;
34
35use base64ct::{Base64UrlUnpadded, Encoding};
36use dom_struct::dom_struct;
37use js::conversions::ConversionResult;
38use js::jsapi::{Heap, JSObject};
39use js::jsval::{ObjectValue, UndefinedValue};
40use js::rust::wrappers::JS_ParseJSON;
41use js::rust::{HandleValue, MutableHandleValue};
42use js::typedarray::ArrayBufferU8;
43
44use crate::dom::bindings::buffer_source::create_buffer_source;
45use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
46 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
47};
48use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
49 AeadParams, AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
50 AesKeyGenParams, Algorithm, AlgorithmIdentifier, Argon2Params, CShakeParams, ContextParams,
51 EcKeyAlgorithm, EcKeyGenParams, EcKeyImportParams, EcdhKeyDeriveParams, EcdsaParams,
52 EncapsulatedBits, EncapsulatedKey, HkdfParams, HmacImportParams, HmacKeyAlgorithm,
53 HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, RsaHashedImportParams,
54 RsaHashedKeyAlgorithm, RsaHashedKeyGenParams, RsaKeyAlgorithm, RsaOaepParams, RsaPssParams,
55 SubtleCryptoMethods,
56};
57use crate::dom::bindings::codegen::UnionTypes::{
58 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
59};
60use crate::dom::bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
61use crate::dom::bindings::error::{Error, Fallible};
62use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
63use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
64use crate::dom::bindings::root::DomRoot;
65use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
66use crate::dom::bindings::trace::RootedTraceableBox;
67use crate::dom::bindings::utils::set_dictionary_property;
68use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
69use crate::dom::globalscope::GlobalScope;
70use crate::dom::promise::Promise;
71use crate::realms::InRealm;
72use crate::script_runtime::{CanGc, JSContext};
73
74const ALG_RSASSA_PKCS1_V1_5: &str = "RSASSA-PKCS1-v1_5";
76const ALG_RSA_PSS: &str = "RSA-PSS";
77const ALG_RSA_OAEP: &str = "RSA-OAEP";
78const ALG_ECDSA: &str = "ECDSA";
79const ALG_ECDH: &str = "ECDH";
80const ALG_ED25519: &str = "Ed25519";
81const ALG_X25519: &str = "X25519";
82const ALG_AES_CTR: &str = "AES-CTR";
83const ALG_AES_CBC: &str = "AES-CBC";
84const ALG_AES_GCM: &str = "AES-GCM";
85const ALG_AES_KW: &str = "AES-KW";
86const ALG_HMAC: &str = "HMAC";
87const ALG_SHA1: &str = "SHA-1";
88const ALG_SHA256: &str = "SHA-256";
89const ALG_SHA384: &str = "SHA-384";
90const ALG_SHA512: &str = "SHA-512";
91const ALG_HKDF: &str = "HKDF";
92const ALG_PBKDF2: &str = "PBKDF2";
93
94const ALG_ML_KEM_512: &str = "ML-KEM-512";
96const ALG_ML_KEM_768: &str = "ML-KEM-768";
97const ALG_ML_KEM_1024: &str = "ML-KEM-1024";
98const ALG_ML_DSA_44: &str = "ML-DSA-44";
99const ALG_ML_DSA_65: &str = "ML-DSA-65";
100const ALG_ML_DSA_87: &str = "ML-DSA-87";
101const ALG_AES_OCB: &str = "AES-OCB";
102const ALG_CHACHA20_POLY1305: &str = "ChaCha20-Poly1305";
103const ALG_SHA3_256: &str = "SHA3-256";
104const ALG_SHA3_384: &str = "SHA3-384";
105const ALG_SHA3_512: &str = "SHA3-512";
106const ALG_CSHAKE_128: &str = "cSHAKE128";
107const ALG_CSHAKE_256: &str = "cSHAKE256";
108const ALG_ARGON2D: &str = "Argon2d";
109const ALG_ARGON2I: &str = "Argon2i";
110const ALG_ARGON2ID: &str = "Argon2id";
111
112static SUPPORTED_ALGORITHMS: &[&str] = &[
113 ALG_RSASSA_PKCS1_V1_5,
114 ALG_RSA_PSS,
115 ALG_RSA_OAEP,
116 ALG_ECDSA,
117 ALG_ECDH,
118 ALG_ED25519,
119 ALG_X25519,
120 ALG_AES_CTR,
121 ALG_AES_CBC,
122 ALG_AES_GCM,
123 ALG_AES_KW,
124 ALG_HMAC,
125 ALG_SHA1,
126 ALG_SHA256,
127 ALG_SHA384,
128 ALG_SHA512,
129 ALG_HKDF,
130 ALG_PBKDF2,
131 ALG_ML_KEM_512,
132 ALG_ML_KEM_768,
133 ALG_ML_KEM_1024,
134 ALG_ML_DSA_44,
135 ALG_ML_DSA_65,
136 ALG_ML_DSA_87,
137 ALG_AES_OCB,
138 ALG_CHACHA20_POLY1305,
139 ALG_SHA3_256,
140 ALG_SHA3_384,
141 ALG_SHA3_512,
142 ALG_CSHAKE_128,
143 ALG_CSHAKE_256,
144 ALG_ARGON2D,
145 ALG_ARGON2I,
146 ALG_ARGON2ID,
147];
148
149const NAMED_CURVE_P256: &str = "P-256";
151const NAMED_CURVE_P384: &str = "P-384";
152const NAMED_CURVE_P521: &str = "P-521";
153
154static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
155
156enum Operation {
158 Encrypt,
159 Decrypt,
160 Sign,
161 Verify,
162 Digest,
163 DeriveBits,
164 WrapKey,
165 UnwrapKey,
166 GenerateKey,
167 ImportKey,
168 ExportKey,
169 GetKeyLength,
170 Encapsulate,
171 Decapsulate,
172}
173
174impl Operation {
175 fn as_str(&self) -> &'static str {
176 match self {
177 Operation::Encrypt => "encrypt",
178 Operation::Decrypt => "decrypt",
179 Operation::Sign => "sign",
180 Operation::Verify => "verify",
181 Operation::Digest => "digest",
182 Operation::DeriveBits => "deriveBits",
183 Operation::WrapKey => "wrapKey",
184 Operation::UnwrapKey => "unwrapKey",
185 Operation::GenerateKey => "generateKey",
186 Operation::ImportKey => "importKey",
187 Operation::ExportKey => "exportKey",
188 Operation::GetKeyLength => "get key length",
189 Operation::Encapsulate => "encapsulate",
190 Operation::Decapsulate => "decapsulate",
191 }
192 }
193}
194
195#[dom_struct]
196pub(crate) struct SubtleCrypto {
197 reflector_: Reflector,
198}
199
200impl SubtleCrypto {
201 fn new_inherited() -> SubtleCrypto {
202 SubtleCrypto {
203 reflector_: Reflector::new(),
204 }
205 }
206
207 pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<SubtleCrypto> {
208 reflect_dom_object(Box::new(SubtleCrypto::new_inherited()), global, can_gc)
209 }
210
211 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
215 let trusted_promise = TrustedPromise::new(promise);
216 self.global().task_manager().crypto_task_source().queue(
217 task!(resolve_data: move || {
218 let promise = trusted_promise.root();
219
220 let cx = GlobalScope::get_cx();
221 rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
222 match create_buffer_source::<ArrayBufferU8>(cx, &data, array_buffer_ptr.handle_mut(), CanGc::note()) {
223 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::note()),
224 Err(_) => promise.reject_error(Error::JSFailed, CanGc::note()),
225 }
226 }),
227 );
228 }
229
230 fn resolve_promise_with_jwk(&self, promise: Rc<Promise>, jwk: Box<JsonWebKey>) {
234 let cx = GlobalScope::get_cx();
237 let stringified_jwk = match jwk.stringify(cx) {
238 Ok(stringified_jwk) => stringified_jwk.to_string(),
239 Err(error) => {
240 self.reject_promise_with_error(promise, error);
241 return;
242 },
243 };
244
245 let trusted_subtle = Trusted::new(self);
246 let trusted_promise = TrustedPromise::new(promise);
247 self.global()
248 .task_manager()
249 .crypto_task_source()
250 .queue(task!(resolve_jwk: move || {
251 let subtle = trusted_subtle.root();
252 let promise = trusted_promise.root();
253
254 let cx = GlobalScope::get_cx();
255 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
256 Ok(jwk) => {
257 rooted!(in(*cx) let mut rval = UndefinedValue());
258 jwk.safe_to_jsval(cx, rval.handle_mut(), CanGc::note());
259 rooted!(in(*cx) let mut object = rval.to_object());
260 promise.resolve_native(&*object, CanGc::note());
261 },
262 Err(error) => {
263 subtle.reject_promise_with_error(promise, error);
264 return;
265 },
266 }
267 }));
268 }
269
270 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
273 let trusted_key = Trusted::new(&*key);
274 let trusted_promise = TrustedPromise::new(promise);
275 self.global()
276 .task_manager()
277 .crypto_task_source()
278 .queue(task!(resolve_key: move || {
279 let key = trusted_key.root();
280 let promise = trusted_promise.root();
281 promise.resolve_native(&key, CanGc::note());
282 }));
283 }
284
285 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
288 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
289 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
290 let trusted_promise = TrustedPromise::new(promise);
291 self.global()
292 .task_manager()
293 .crypto_task_source()
294 .queue(task!(resolve_key: move || {
295 let key_pair = CryptoKeyPair {
296 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
297 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
298 };
299 let promise = trusted_promise.root();
300 promise.resolve_native(&key_pair, CanGc::note());
301 }));
302 }
303
304 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
307 let trusted_promise = TrustedPromise::new(promise);
308 self.global().task_manager().crypto_task_source().queue(
309 task!(generate_key_result: move || {
310 let promise = trusted_promise.root();
311 promise.resolve_native(&result, CanGc::note());
312 }),
313 );
314 }
315
316 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
319 let trusted_promise = TrustedPromise::new(promise);
320 self.global()
321 .task_manager()
322 .crypto_task_source()
323 .queue(task!(reject_error: move || {
324 let promise = trusted_promise.root();
325 promise.reject_error(error, CanGc::note());
326 }));
327 }
328
329 fn resolve_promise_with_encapsulated_key(
333 &self,
334 promise: Rc<Promise>,
335 encapsulated_key: SubtleEncapsulatedKey,
336 ) {
337 let trusted_promise = TrustedPromise::new(promise);
338 self.global().task_manager().crypto_task_source().queue(
339 task!(resolve_encapsulated_key: move || {
340 let promise = trusted_promise.root();
341 promise.resolve_native(&encapsulated_key, CanGc::note());
342 }),
343 );
344 }
345
346 fn resolve_promise_with_encapsulated_bits(
350 &self,
351 promise: Rc<Promise>,
352 encapsulated_bits: SubtleEncapsulatedBits,
353 ) {
354 let trusted_promise = TrustedPromise::new(promise);
355 self.global().task_manager().crypto_task_source().queue(
356 task!(resolve_encapsulated_bits: move || {
357 let promise = trusted_promise.root();
358 promise.resolve_native(&encapsulated_bits, CanGc::note());
359 }),
360 );
361 }
362}
363
364impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
365 fn Encrypt(
367 &self,
368 cx: JSContext,
369 algorithm: AlgorithmIdentifier,
370 key: &CryptoKey,
371 data: ArrayBufferViewOrArrayBuffer,
372 comp: InRealm,
373 can_gc: CanGc,
374 ) -> Rc<Promise> {
375 let data = match data {
382 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
383 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
384 };
385
386 let promise = Promise::new_in_current_realm(comp, can_gc);
390 let normalized_algorithm =
391 match normalize_algorithm(cx, Operation::Encrypt, &algorithm, can_gc) {
392 Ok(normalized_algorithm) => normalized_algorithm,
393 Err(error) => {
394 promise.reject_error(error, can_gc);
395 return promise;
396 },
397 };
398
399 let this = Trusted::new(self);
405 let trusted_promise = TrustedPromise::new(promise.clone());
406 let trusted_key = Trusted::new(key);
407 self.global()
408 .task_manager()
409 .dom_manipulation_task_source()
410 .queue(task!(encrypt: move || {
411 let subtle = this.root();
412 let promise = trusted_promise.root();
413 let key = trusted_key.root();
414
415 if normalized_algorithm.name() != key.algorithm().name() {
423 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
424 return;
425 }
426
427 if !key.usages().contains(&KeyUsage::Encrypt) {
430 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
431 return;
432 }
433
434 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
438 Ok(ciphertext) => ciphertext,
439 Err(error) => {
440 subtle.reject_promise_with_error(promise, error);
441 return;
442 },
443 };
444
445 subtle.resolve_promise_with_data(promise, ciphertext);
451 }));
452 promise
453 }
454
455 fn Decrypt(
457 &self,
458 cx: JSContext,
459 algorithm: AlgorithmIdentifier,
460 key: &CryptoKey,
461 data: ArrayBufferViewOrArrayBuffer,
462 comp: InRealm,
463 can_gc: CanGc,
464 ) -> Rc<Promise> {
465 let data = match data {
472 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
473 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
474 };
475
476 let promise = Promise::new_in_current_realm(comp, can_gc);
480 let normalized_algorithm =
481 match normalize_algorithm(cx, Operation::Decrypt, &algorithm, can_gc) {
482 Ok(normalized_algorithm) => normalized_algorithm,
483 Err(error) => {
484 promise.reject_error(error, can_gc);
485 return promise;
486 },
487 };
488
489 let this = Trusted::new(self);
495 let trusted_promise = TrustedPromise::new(promise.clone());
496 let trusted_key = Trusted::new(key);
497 self.global()
498 .task_manager()
499 .dom_manipulation_task_source()
500 .queue(task!(decrypt: move || {
501 let subtle = this.root();
502 let promise = trusted_promise.root();
503 let key = trusted_key.root();
504
505 if normalized_algorithm.name() != key.algorithm().name() {
513 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
514 return;
515 }
516
517 if !key.usages().contains(&KeyUsage::Decrypt) {
520 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
521 return;
522 }
523
524 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
528 Ok(plaintext) => plaintext,
529 Err(error) => {
530 subtle.reject_promise_with_error(promise, error);
531 return;
532 },
533 };
534
535 subtle.resolve_promise_with_data(promise, plaintext);
541 }));
542 promise
543 }
544
545 fn Sign(
547 &self,
548 cx: JSContext,
549 algorithm: AlgorithmIdentifier,
550 key: &CryptoKey,
551 data: ArrayBufferViewOrArrayBuffer,
552 comp: InRealm,
553 can_gc: CanGc,
554 ) -> Rc<Promise> {
555 let data = match &data {
562 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
563 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
564 };
565
566 let promise = Promise::new_in_current_realm(comp, can_gc);
570 let normalized_algorithm =
571 match normalize_algorithm(cx, Operation::Sign, &algorithm, can_gc) {
572 Ok(normalized_algorithm) => normalized_algorithm,
573 Err(error) => {
574 promise.reject_error(error, can_gc);
575 return promise;
576 },
577 };
578
579 let this = Trusted::new(self);
585 let trusted_promise = TrustedPromise::new(promise.clone());
586 let trusted_key = Trusted::new(key);
587 self.global()
588 .task_manager()
589 .dom_manipulation_task_source()
590 .queue(task!(sign: move || {
591 let subtle = this.root();
592 let promise = trusted_promise.root();
593 let key = trusted_key.root();
594
595 if normalized_algorithm.name() != key.algorithm().name() {
603 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
604 return;
605 }
606
607 if !key.usages().contains(&KeyUsage::Sign) {
610 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
611 return;
612 }
613
614 let signature = match normalized_algorithm.sign(&key, &data) {
617 Ok(signature) => signature,
618 Err(error) => {
619 subtle.reject_promise_with_error(promise, error);
620 return;
621 },
622 };
623
624 subtle.resolve_promise_with_data(promise, signature);
630 }));
631 promise
632 }
633
634 fn Verify(
636 &self,
637 cx: JSContext,
638 algorithm: AlgorithmIdentifier,
639 key: &CryptoKey,
640 signature: ArrayBufferViewOrArrayBuffer,
641 data: ArrayBufferViewOrArrayBuffer,
642 comp: InRealm,
643 can_gc: CanGc,
644 ) -> Rc<Promise> {
645 let signature = match &signature {
652 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
653 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
654 };
655
656 let data = match &data {
659 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
660 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
661 };
662
663 let promise = Promise::new_in_current_realm(comp, can_gc);
667 let normalized_algorithm =
668 match normalize_algorithm(cx, Operation::Verify, &algorithm, can_gc) {
669 Ok(algorithm) => algorithm,
670 Err(error) => {
671 promise.reject_error(error, can_gc);
672 return promise;
673 },
674 };
675
676 let this = Trusted::new(self);
682 let trusted_promise = TrustedPromise::new(promise.clone());
683 let trusted_key = Trusted::new(key);
684 self.global()
685 .task_manager()
686 .dom_manipulation_task_source()
687 .queue(task!(sign: move || {
688 let subtle = this.root();
689 let promise = trusted_promise.root();
690 let key = trusted_key.root();
691
692 if normalized_algorithm.name() != key.algorithm().name() {
700 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
701 return;
702 }
703
704 if !key.usages().contains(&KeyUsage::Verify) {
707 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
708 return;
709 }
710
711 let result = match normalized_algorithm.verify(&key, &data, &signature) {
715 Ok(result) => result,
716 Err(error) => {
717 subtle.reject_promise_with_error(promise, error);
718 return;
719 },
720 };
721
722 subtle.resolve_promise_with_bool(promise, result);
726 }));
727 promise
728 }
729
730 fn Digest(
732 &self,
733 cx: JSContext,
734 algorithm: AlgorithmIdentifier,
735 data: ArrayBufferViewOrArrayBuffer,
736 comp: InRealm,
737 can_gc: CanGc,
738 ) -> Rc<Promise> {
739 let data = match data {
745 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
746 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
747 };
748
749 let promise = Promise::new_in_current_realm(comp, can_gc);
753 let normalized_algorithm =
754 match normalize_algorithm(cx, Operation::Digest, &algorithm, can_gc) {
755 Ok(normalized_algorithm) => normalized_algorithm,
756 Err(error) => {
757 promise.reject_error(error, can_gc);
758 return promise;
759 },
760 };
761
762 let this = Trusted::new(self);
768 let trusted_promise = TrustedPromise::new(promise.clone());
769 self.global()
770 .task_manager()
771 .dom_manipulation_task_source()
772 .queue(task!(generate_key: move || {
773 let subtle = this.root();
774 let promise = trusted_promise.root();
775
776 let digest = match normalized_algorithm.digest(&data) {
783 Ok(digest) => digest,
784 Err(error) => {
785 subtle.reject_promise_with_error(promise, error);
786 return;
787 }
788 };
789
790 subtle.resolve_promise_with_data(promise, digest);
796 }));
797 promise
798 }
799
800 fn GenerateKey(
802 &self,
803 cx: JSContext,
804 algorithm: AlgorithmIdentifier,
805 extractable: bool,
806 key_usages: Vec<KeyUsage>,
807 comp: InRealm,
808 can_gc: CanGc,
809 ) -> Rc<Promise> {
810 let promise = Promise::new_in_current_realm(comp, can_gc);
817 let normalized_algorithm =
818 match normalize_algorithm(cx, Operation::GenerateKey, &algorithm, can_gc) {
819 Ok(normalized_algorithm) => normalized_algorithm,
820 Err(error) => {
821 promise.reject_error(error, can_gc);
822 return promise;
823 },
824 };
825
826 let trusted_subtle = Trusted::new(self);
832 let trusted_promise = TrustedPromise::new(promise.clone());
833 self.global()
834 .task_manager()
835 .dom_manipulation_task_source()
836 .queue(task!(generate_key: move || {
837 let subtle = trusted_subtle.root();
838 let promise = trusted_promise.root();
839
840 let result = match normalized_algorithm.generate_key(
847 &subtle.global(),
848 extractable,
849 key_usages,
850 CanGc::note(),
851 ) {
852 Ok(result) => result,
853 Err(error) => {
854 subtle.reject_promise_with_error(promise, error);
855 return;
856 }
857 };
858
859 match &result {
868 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
869 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
870 && crpyto_key.usages().is_empty()
871 {
872 subtle.reject_promise_with_error(promise, Error::Syntax(None));
873 return;
874 }
875 },
876 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
877 if crypto_key_pair.privateKey.as_ref().is_none_or(|private_key| private_key.usages().is_empty()) {
878 subtle.reject_promise_with_error(promise, Error::Syntax(None));
879 return;
880 }
881 }
882 };
883
884 match result {
890 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
891 subtle.resolve_promise_with_key(promise, key);
892 },
893 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
894 subtle.resolve_promise_with_key_pair(promise, key_pair);
895 },
896 }
897 }));
898
899 promise
900 }
901
902 fn DeriveKey(
904 &self,
905 cx: JSContext,
906 algorithm: AlgorithmIdentifier,
907 base_key: &CryptoKey,
908 derived_key_type: AlgorithmIdentifier,
909 extractable: bool,
910 usages: Vec<KeyUsage>,
911 comp: InRealm,
912 can_gc: CanGc,
913 ) -> Rc<Promise> {
914 let promise = Promise::new_in_current_realm(comp, can_gc);
923 let normalized_algorithm =
924 match normalize_algorithm(cx, Operation::DeriveBits, &algorithm, can_gc) {
925 Ok(normalized_algorithm) => normalized_algorithm,
926 Err(error) => {
927 promise.reject_error(error, can_gc);
928 return promise;
929 },
930 };
931
932 let normalized_derived_key_algorithm_import =
937 match normalize_algorithm(cx, Operation::ImportKey, &derived_key_type, can_gc) {
938 Ok(normalized_algorithm) => normalized_algorithm,
939 Err(error) => {
940 promise.reject_error(error, can_gc);
941 return promise;
942 },
943 };
944
945 let normalized_derived_key_algorithm_length =
950 match normalize_algorithm(cx, Operation::GetKeyLength, &derived_key_type, can_gc) {
951 Ok(normalized_algorithm) => normalized_algorithm,
952 Err(error) => {
953 promise.reject_error(error, can_gc);
954 return promise;
955 },
956 };
957
958 let trusted_subtle = Trusted::new(self);
964 let trusted_base_key = Trusted::new(base_key);
965 let trusted_promise = TrustedPromise::new(promise.clone());
966 self.global().task_manager().dom_manipulation_task_source().queue(
967 task!(derive_key: move || {
968 let subtle = trusted_subtle.root();
969 let base_key = trusted_base_key.root();
970 let promise = trusted_promise.root();
971
972 if normalized_algorithm.name() != base_key.algorithm().name() {
980 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
981 return;
982 }
983
984 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
987 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
988 return;
989 }
990
991 let length = match normalized_derived_key_algorithm_length.get_key_length() {
994 Ok(length) => length,
995 Err(error) => {
996 subtle.reject_promise_with_error(promise, error);
997 return;
998 }
999 };
1000
1001 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
1004 Ok(secret) => secret,
1005 Err(error) => {
1006 subtle.reject_promise_with_error(promise, error);
1007 return;
1008 }
1009 };
1010
1011 let result = match normalized_derived_key_algorithm_import.import_key(
1017 &subtle.global(),
1018 KeyFormat::Raw_secret,
1019 &secret,
1020 extractable,
1021 usages.clone(),
1022 CanGc::note(),
1023 ) {
1024 Ok(algorithm) => algorithm,
1025 Err(error) => {
1026 subtle.reject_promise_with_error(promise, error);
1027 return;
1028 },
1029 };
1030
1031 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1034 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1035 return;
1036 }
1037
1038 subtle.resolve_promise_with_key(promise, result);
1049 }),
1050 );
1051 promise
1052 }
1053
1054 fn DeriveBits(
1056 &self,
1057 cx: JSContext,
1058 algorithm: AlgorithmIdentifier,
1059 base_key: &CryptoKey,
1060 length: Option<u32>,
1061 comp: InRealm,
1062 can_gc: CanGc,
1063 ) -> Rc<Promise> {
1064 let promise = Promise::new_in_current_realm(comp, can_gc);
1072 let normalized_algorithm =
1073 match normalize_algorithm(cx, Operation::DeriveBits, &algorithm, can_gc) {
1074 Ok(normalized_algorithm) => normalized_algorithm,
1075 Err(error) => {
1076 promise.reject_error(error, can_gc);
1077 return promise;
1078 },
1079 };
1080
1081 let trsuted_subtle = Trusted::new(self);
1087 let trusted_base_key = Trusted::new(base_key);
1088 let trusted_promise = TrustedPromise::new(promise.clone());
1089 self.global()
1090 .task_manager()
1091 .dom_manipulation_task_source()
1092 .queue(task!(import_key: move || {
1093 let subtle = trsuted_subtle.root();
1094 let base_key = trusted_base_key.root();
1095 let promise = trusted_promise.root();
1096
1097 if normalized_algorithm.name() != base_key.algorithm().name() {
1105 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1106 return;
1107 }
1108
1109 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1112 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1113 return;
1114 }
1115
1116 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1119 Ok(bits) => bits,
1120 Err(error) => {
1121 subtle.reject_promise_with_error(promise, error);
1122 return;
1123 }
1124 };
1125
1126 subtle.resolve_promise_with_data(promise, bits);
1132 }));
1133 promise
1134 }
1135
1136 fn ImportKey(
1138 &self,
1139 cx: JSContext,
1140 format: KeyFormat,
1141 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1142 algorithm: AlgorithmIdentifier,
1143 extractable: bool,
1144 key_usages: Vec<KeyUsage>,
1145 comp: InRealm,
1146 can_gc: CanGc,
1147 ) -> Rc<Promise> {
1148 let promise = Promise::new_in_current_realm(comp, can_gc);
1154
1155 let key_data = match format {
1157 KeyFormat::Jwk => {
1159 match key_data {
1160 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1161 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1162 promise.reject_error(
1165 Error::Type(c"The keyData type does not match the format".to_owned()),
1166 can_gc,
1167 );
1168 return promise;
1169 },
1170
1171 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1172 match jwk.stringify(cx) {
1179 Ok(stringified) => stringified.as_bytes().to_vec(),
1180 Err(error) => {
1181 promise.reject_error(error, can_gc);
1182 return promise;
1183 },
1184 }
1185 },
1186 }
1187 },
1188 _ => {
1190 match key_data {
1191 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1194 promise.reject_error(
1195 Error::Type(c"The keyData type does not match the format".to_owned()),
1196 can_gc,
1197 );
1198 return promise;
1199 },
1200
1201 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1204 view.to_vec()
1205 },
1206 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1207 buffer.to_vec()
1208 },
1209 }
1210 },
1211 };
1212
1213 let normalized_algorithm =
1217 match normalize_algorithm(cx, Operation::ImportKey, &algorithm, can_gc) {
1218 Ok(algorithm) => algorithm,
1219 Err(error) => {
1220 promise.reject_error(error, can_gc);
1221 return promise;
1222 },
1223 };
1224
1225 let this = Trusted::new(self);
1227 let trusted_promise = TrustedPromise::new(promise.clone());
1228 self.global()
1229 .task_manager()
1230 .dom_manipulation_task_source()
1231 .queue(task!(import_key: move || {
1232 let subtle = this.root();
1233 let promise = trusted_promise.root();
1234
1235 let result = match normalized_algorithm.import_key(
1243 &subtle.global(),
1244 format,
1245 &key_data,
1246 extractable,
1247 key_usages.clone(),
1248 CanGc::note()
1249 ) {
1250 Ok(key) => key,
1251 Err(error) => {
1252 subtle.reject_promise_with_error(promise, error);
1253 return;
1254 },
1255 };
1256
1257 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1260 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1261 return;
1262 }
1263
1264 result.set_extractable(extractable);
1266
1267 result.set_usages(&key_usages);
1269
1270 subtle.resolve_promise_with_key(promise, result);
1276 }));
1277
1278 promise
1279 }
1280
1281 fn ExportKey(
1283 &self,
1284 format: KeyFormat,
1285 key: &CryptoKey,
1286 comp: InRealm,
1287 can_gc: CanGc,
1288 ) -> Rc<Promise> {
1289 let promise = Promise::new_in_current_realm(comp, can_gc);
1296
1297 let trusted_subtle = Trusted::new(self);
1299 let trusted_promise = TrustedPromise::new(promise.clone());
1300 let trusted_key = Trusted::new(key);
1301 self.global()
1302 .task_manager()
1303 .dom_manipulation_task_source()
1304 .queue(task!(export_key: move || {
1305 let subtle = trusted_subtle.root();
1306 let promise = trusted_promise.root();
1307 let key = trusted_key.root();
1308
1309 let registered_algorithm = match SupportedAlgorithm::try_from(key.algorithm().name()) {
1317 Ok(registered_algorithm) => registered_algorithm,
1318 Err(error) => {
1319 subtle.reject_promise_with_error(promise, error);
1320 return;
1321 },
1322 };
1323 if registered_algorithm.support(Operation::ExportKey).is_err() {
1324 subtle.reject_promise_with_error(promise, Error::NotSupported(None));
1325 return;
1326 }
1327
1328 if !key.Extractable() {
1331 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1332 return;
1333 }
1334
1335 let result = match perform_export_key_operation(format, &key) {
1338 Ok(exported_key) => exported_key,
1339 Err(error) => {
1340 subtle.reject_promise_with_error(promise, error);
1341 return;
1342 },
1343 };
1344
1345 match result {
1358 ExportedKey::Bytes(bytes) => {
1359 subtle.resolve_promise_with_data(promise, bytes);
1360 },
1361 ExportedKey::Jwk(jwk) => {
1362 subtle.resolve_promise_with_jwk(promise, jwk);
1363 },
1364 }
1365 }));
1366 promise
1367 }
1368
1369 fn WrapKey(
1371 &self,
1372 cx: JSContext,
1373 format: KeyFormat,
1374 key: &CryptoKey,
1375 wrapping_key: &CryptoKey,
1376 algorithm: AlgorithmIdentifier,
1377 comp: InRealm,
1378 can_gc: CanGc,
1379 ) -> Rc<Promise> {
1380 let mut normalized_algorithm_result =
1387 normalize_algorithm(cx, Operation::WrapKey, &algorithm, can_gc);
1388
1389 if normalized_algorithm_result.is_err() {
1392 normalized_algorithm_result =
1393 normalize_algorithm(cx, Operation::Encrypt, &algorithm, can_gc);
1394 }
1395
1396 let promise = Promise::new_in_current_realm(comp, can_gc);
1398 let normalized_algorithm = match normalized_algorithm_result {
1399 Ok(normalized_algorithm) => normalized_algorithm,
1400 Err(error) => {
1401 promise.reject_error(error, can_gc);
1402 return promise;
1403 },
1404 };
1405
1406 let trusted_subtle = Trusted::new(self);
1412 let trusted_key = Trusted::new(key);
1413 let trusted_wrapping_key = Trusted::new(wrapping_key);
1414 let trusted_promise = TrustedPromise::new(promise.clone());
1415 self.global()
1416 .task_manager()
1417 .dom_manipulation_task_source()
1418 .queue(task!(wrap_key: move || {
1419 let subtle = trusted_subtle.root();
1420 let key = trusted_key.root();
1421 let wrapping_key = trusted_wrapping_key.root();
1422 let promise = trusted_promise.root();
1423
1424 if normalized_algorithm.name() != wrapping_key.algorithm().name() {
1432 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1433 return;
1434 }
1435
1436 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1439 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1440 return;
1441 }
1442
1443 let registered_algorithm = match SupportedAlgorithm::try_from(key.algorithm().name()) {
1446 Ok(registered_algorithm) => registered_algorithm,
1447 Err(error) => {
1448 subtle.reject_promise_with_error(promise, error);
1449 return;
1450 },
1451 };
1452 if registered_algorithm.support(Operation::ExportKey).is_err() {
1453 subtle.reject_promise_with_error(promise, Error::NotSupported(None));
1454 return;
1455 }
1456
1457 if !key.Extractable() {
1460 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1461 return;
1462 }
1463
1464 let exported_key = match perform_export_key_operation(format, &key) {
1467 Ok(exported_key) => exported_key,
1468 Err(error) => {
1469 subtle.reject_promise_with_error(promise, error);
1470 return;
1471 },
1472 };
1473
1474 let cx = GlobalScope::get_cx();
1486 let bytes = match exported_key {
1487 ExportedKey::Bytes(bytes) => bytes,
1488 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1489 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1490 Err(error) => {
1491 subtle.reject_promise_with_error(promise, error);
1492 return;
1493 },
1494 },
1495 };
1496
1497 let mut result = normalized_algorithm.wrap_key(&wrapping_key, &bytes);
1509 if result.is_err() {
1510 result = normalized_algorithm.encrypt(&wrapping_key, &bytes);
1511 }
1512 let result = match result {
1513 Ok(result) => result,
1514 Err(error) => {
1515 subtle.reject_promise_with_error(promise, error);
1516 return;
1517 },
1518 };
1519
1520 subtle.resolve_promise_with_data(promise, result);
1526 }));
1527 promise
1528 }
1529
1530 fn UnwrapKey(
1532 &self,
1533 cx: JSContext,
1534 format: KeyFormat,
1535 wrapped_key: ArrayBufferViewOrArrayBuffer,
1536 unwrapping_key: &CryptoKey,
1537 algorithm: AlgorithmIdentifier,
1538 unwrapped_key_algorithm: AlgorithmIdentifier,
1539 extractable: bool,
1540 usages: Vec<KeyUsage>,
1541 comp: InRealm,
1542 can_gc: CanGc,
1543 ) -> Rc<Promise> {
1544 let wrapped_key = match wrapped_key {
1552 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1553 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1554 };
1555
1556 let mut normalized_algorithm =
1559 normalize_algorithm(cx, Operation::UnwrapKey, &algorithm, can_gc);
1560
1561 if normalized_algorithm.is_err() {
1564 normalized_algorithm = normalize_algorithm(cx, Operation::Decrypt, &algorithm, can_gc);
1565 }
1566
1567 let promise = Promise::new_in_current_realm(comp, can_gc);
1569 let normalized_algorithm = match normalized_algorithm {
1570 Ok(algorithm) => algorithm,
1571 Err(error) => {
1572 promise.reject_error(error, can_gc);
1573 return promise;
1574 },
1575 };
1576
1577 let normalized_key_algorithm =
1581 match normalize_algorithm(cx, Operation::ImportKey, &unwrapped_key_algorithm, can_gc) {
1582 Ok(algorithm) => algorithm,
1583 Err(error) => {
1584 promise.reject_error(error, can_gc);
1585 return promise;
1586 },
1587 };
1588
1589 let trusted_subtle = Trusted::new(self);
1595 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1596 let trusted_promise = TrustedPromise::new(promise.clone());
1597 self.global().task_manager().dom_manipulation_task_source().queue(
1598 task!(unwrap_key: move || {
1599 let subtle = trusted_subtle.root();
1600 let unwrapping_key = trusted_unwrapping_key.root();
1601 let promise = trusted_promise.root();
1602
1603 if normalized_algorithm.name() != unwrapping_key.algorithm().name() {
1611 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1612 return;
1613 }
1614
1615 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1618 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1619 return;
1620 }
1621
1622 let mut bytes = normalized_algorithm.unwrap_key(&unwrapping_key, &wrapped_key);
1634 if bytes.is_err() {
1635 bytes = normalized_algorithm.decrypt(&unwrapping_key, &wrapped_key);
1636 }
1637 let bytes = match bytes {
1638 Ok(bytes) => bytes,
1639 Err(error) => {
1640 subtle.reject_promise_with_error(promise, error);
1641 return;
1642 },
1643 };
1644
1645 let cx = GlobalScope::get_cx();
1656 if format == KeyFormat::Jwk {
1657 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1658 subtle.reject_promise_with_error(promise, error);
1659 return;
1660 }
1661 }
1662 let key = bytes;
1663
1664 let result = match normalized_key_algorithm.import_key(
1668 &subtle.global(),
1669 format,
1670 &key,
1671 extractable,
1672 usages.clone(),
1673 CanGc::note(),
1674 ) {
1675 Ok(result) => result,
1676 Err(error) => {
1677 subtle.reject_promise_with_error(promise, error);
1678 return;
1679 },
1680 };
1681
1682 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1685 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1686 return;
1687 }
1688
1689 subtle.resolve_promise_with_key(promise, result);
1700 }),
1701 );
1702 promise
1703 }
1704
1705 fn EncapsulateKey(
1707 &self,
1708 cx: JSContext,
1709 encapsulation_algorithm: AlgorithmIdentifier,
1710 encapsulation_key: &CryptoKey,
1711 shared_key_algorithm: AlgorithmIdentifier,
1712 extractable: bool,
1713 usages: Vec<KeyUsage>,
1714 comp: InRealm,
1715 can_gc: CanGc,
1716 ) -> Rc<Promise> {
1717 let promise = Promise::new_in_current_realm(comp, can_gc);
1727 let normalized_encapsulation_algorithm =
1728 match normalize_algorithm(cx, Operation::Encapsulate, &encapsulation_algorithm, can_gc)
1729 {
1730 Ok(algorithm) => algorithm,
1731 Err(error) => {
1732 promise.reject_error(error, can_gc);
1733 return promise;
1734 },
1735 };
1736
1737 let normalized_shared_key_algorithm =
1742 match normalize_algorithm(cx, Operation::ImportKey, &shared_key_algorithm, can_gc) {
1743 Ok(algorithm) => algorithm,
1744 Err(error) => {
1745 promise.reject_error(error, can_gc);
1746 return promise;
1747 },
1748 };
1749
1750 let trusted_subtle = Trusted::new(self);
1756 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1757 let trusted_promise = TrustedPromise::new(promise.clone());
1758 self.global().task_manager().dom_manipulation_task_source().queue(
1759 task!(encapsulate_keys: move || {
1760 let subtle = trusted_subtle.root();
1761 let encapsulation_key = trusted_encapsulated_key.root();
1762 let promise = trusted_promise.root();
1763
1764 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1772 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1773 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1774 normalizedEncapsulationAlgorithm".to_string(),
1775 )));
1776 return;
1777 }
1778
1779 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1782 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1783 "[[usages]] internal slot of encapsulationKey does not contain an \
1784 entry that is \"encapsulateBits\"".to_string(),
1785 )));
1786 return;
1787 }
1788
1789 let encapsulated_bits_result =
1795 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1796 let encapsulated_bits = match encapsulated_bits_result {
1797 Ok(encapsulated_bits) => encapsulated_bits,
1798 Err(error) => {
1799 subtle.reject_promise_with_error(promise, error);
1800 return;
1801 },
1802 };
1803
1804 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1812 Some(shared_key) => shared_key,
1813 None => {
1814 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1815 "Shared key is missing in the result of the encapsulate operation"
1816 .to_string())));
1817 return;
1818 },
1819 };
1820 let shared_key_result = normalized_shared_key_algorithm.import_key(
1821 &subtle.global(),
1822 KeyFormat::Raw_secret,
1823 encapsulated_shared_key,
1824 extractable,
1825 usages.clone(),
1826 CanGc::note(),
1827 );
1828 let shared_key = match shared_key_result {
1829 Ok(shared_key) => shared_key,
1830 Err(error) => {
1831 subtle.reject_promise_with_error(promise, error);
1832 return;
1833 },
1834 };
1835
1836 let encapsulated_key = SubtleEncapsulatedKey {
1839 shared_key: Some(Trusted::new(&shared_key)),
1840 ciphertext:encapsulated_bits.ciphertext,
1841 };
1842
1843 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1849 })
1850 );
1851 promise
1852 }
1853
1854 fn EncapsulateBits(
1856 &self,
1857 cx: JSContext,
1858 encapsulation_algorithm: AlgorithmIdentifier,
1859 encapsulation_key: &CryptoKey,
1860 comp: InRealm,
1861 can_gc: CanGc,
1862 ) -> Rc<Promise> {
1863 let promise = Promise::new_in_current_realm(comp, can_gc);
1871 let normalized_encapsulation_algorithm =
1872 match normalize_algorithm(cx, Operation::Encapsulate, &encapsulation_algorithm, can_gc)
1873 {
1874 Ok(algorithm) => algorithm,
1875 Err(error) => {
1876 promise.reject_error(error, can_gc);
1877 return promise;
1878 },
1879 };
1880
1881 let trusted_subtle = Trusted::new(self);
1887 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1888 let trusted_promise = TrustedPromise::new(promise.clone());
1889 self.global().task_manager().dom_manipulation_task_source().queue(
1890 task!(derive_key: move || {
1891 let subtle = trusted_subtle.root();
1892 let encapsulation_key = trusted_encapsulation_key.root();
1893 let promise = trusted_promise.root();
1894
1895 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1903 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1904 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1905 normalizedEncapsulationAlgorithm".to_string(),
1906 )));
1907 return;
1908 }
1909
1910 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1913 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1914 "[[usages]] internal slot of encapsulationKey does not contain an \
1915 entry that is \"encapsulateBits\"".to_string(),
1916 )));
1917 return;
1918 }
1919
1920 let encapsulated_bits = match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1926 Ok(encapsulated_bits) => encapsulated_bits,
1927 Err(error) => {
1928 subtle.reject_promise_with_error(promise, error);
1929 return;
1930 },
1931 };
1932
1933 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1939 }),
1940 );
1941 promise
1942 }
1943
1944 fn DecapsulateKey(
1946 &self,
1947 cx: JSContext,
1948 decapsulation_algorithm: AlgorithmIdentifier,
1949 decapsulation_key: &CryptoKey,
1950 ciphertext: ArrayBufferViewOrArrayBuffer,
1951 shared_key_algorithm: AlgorithmIdentifier,
1952 extractable: bool,
1953 usages: Vec<KeyUsage>,
1954 comp: InRealm,
1955 can_gc: CanGc,
1956 ) -> Rc<Promise> {
1957 let ciphertext = match ciphertext {
1965 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1966 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1967 };
1968
1969 let promise = Promise::new_in_current_realm(comp, can_gc);
1974 let normalized_decapsulation_algorithm =
1975 match normalize_algorithm(cx, Operation::Decapsulate, &decapsulation_algorithm, can_gc)
1976 {
1977 Ok(normalized_algorithm) => normalized_algorithm,
1978 Err(error) => {
1979 promise.reject_error(error, can_gc);
1980 return promise;
1981 },
1982 };
1983
1984 let normalized_shared_key_algorithm =
1989 match normalize_algorithm(cx, Operation::ImportKey, &shared_key_algorithm, can_gc) {
1990 Ok(normalized_algorithm) => normalized_algorithm,
1991 Err(error) => {
1992 promise.reject_error(error, can_gc);
1993 return promise;
1994 },
1995 };
1996
1997 let trusted_subtle = Trusted::new(self);
2003 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2004 let trusted_promise = TrustedPromise::new(promise.clone());
2005 self.global()
2006 .task_manager()
2007 .dom_manipulation_task_source()
2008 .queue(task!(decapsulate_key: move || {
2009 let subtle = trusted_subtle.root();
2010 let promise = trusted_promise.root();
2011 let decapsulation_key = trusted_decapsulation_key.root();
2012
2013 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2021 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2022 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2023 normalizedDecapsulationAlgorithm".to_string()
2024 )));
2025 return;
2026 }
2027
2028 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2031 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2032 "[[usages]] internal slot of decapsulationKey does not contain an \
2033 entry that is \"decapsulateBits\"".to_string(),
2034 )));
2035 return;
2036 }
2037
2038 let decapsulated_bits_result =
2044 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2045 let decapsulated_bits = match decapsulated_bits_result {
2046 Ok(decapsulated_bits) => decapsulated_bits,
2047 Err(error) => {
2048 subtle.reject_promise_with_error(promise, error);
2049 return;
2050 },
2051 };
2052
2053
2054 let shared_key_result = normalized_shared_key_algorithm.import_key(
2062 &subtle.global(),
2063 KeyFormat::Raw_secret,
2064 &decapsulated_bits,
2065 extractable,
2066 usages.clone(),
2067 CanGc::note(),
2068 );
2069 let shared_key = match shared_key_result {
2070 Ok(shared_key) => shared_key,
2071 Err(error) => {
2072 subtle.reject_promise_with_error(promise, error);
2073 return;
2074 },
2075 };
2076
2077
2078 subtle.resolve_promise_with_key(promise, shared_key);
2084 }));
2085 promise
2086 }
2087
2088 fn DecapsulateBits(
2090 &self,
2091 cx: JSContext,
2092 decapsulation_algorithm: AlgorithmIdentifier,
2093 decapsulation_key: &CryptoKey,
2094 ciphertext: ArrayBufferViewOrArrayBuffer,
2095 comp: InRealm,
2096 can_gc: CanGc,
2097 ) -> Rc<Promise> {
2098 let ciphertext = match ciphertext {
2104 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2105 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2106 };
2107
2108 let promise = Promise::new_in_current_realm(comp, can_gc);
2113 let normalized_decapsulation_algorithm =
2114 match normalize_algorithm(cx, Operation::Decapsulate, &decapsulation_algorithm, can_gc)
2115 {
2116 Ok(normalized_algorithm) => normalized_algorithm,
2117 Err(error) => {
2118 promise.reject_error(error, can_gc);
2119 return promise;
2120 },
2121 };
2122
2123 let trusted_subtle = Trusted::new(self);
2129 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2130 let trusted_promise = TrustedPromise::new(promise.clone());
2131 self.global()
2132 .task_manager()
2133 .dom_manipulation_task_source()
2134 .queue(task!(decapsulate_bits: move || {
2135 let subtle = trusted_subtle.root();
2136 let promise = trusted_promise.root();
2137 let decapsulation_key = trusted_decapsulation_key.root();
2138
2139 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2147 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2148 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2149 normalizedDecapsulationAlgorithm".to_string()
2150 )));
2151 return;
2152 }
2153
2154 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2157 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2158 "[[usages]] internal slot of decapsulationKey does not contain an \
2159 entry that is \"decapsulateBits\"".to_string(),
2160 )));
2161 return;
2162 }
2163
2164 let decapsulated_bits_result =
2170 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2171 let decapsulated_bits = match decapsulated_bits_result {
2172 Ok(decapsulated_bits) => decapsulated_bits,
2173 Err(error) => {
2174 subtle.reject_promise_with_error(promise, error);
2175 return;
2176 },
2177 };
2178
2179 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2185 }));
2186 promise
2187 }
2188}
2189
2190#[derive(Clone, Debug, MallocSizeOf)]
2195struct SubtleAlgorithm {
2196 name: String,
2198}
2199
2200impl From<Algorithm> for SubtleAlgorithm {
2201 fn from(params: Algorithm) -> Self {
2202 SubtleAlgorithm {
2203 name: params.name.to_string(),
2204 }
2205 }
2206}
2207
2208#[derive(Clone, Debug, MallocSizeOf)]
2210pub(crate) struct SubtleKeyAlgorithm {
2211 name: String,
2213}
2214
2215impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2216 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2217 let dictionary = KeyAlgorithm {
2218 name: self.name.clone().into(),
2219 };
2220 dictionary.safe_to_jsval(cx, rval, can_gc);
2221 }
2222}
2223
2224#[derive(Clone, MallocSizeOf)]
2226pub(crate) struct SubtleRsaHashedKeyGenParams {
2227 name: String,
2229
2230 modulus_length: u32,
2232
2233 public_exponent: Vec<u8>,
2235
2236 hash: Box<NormalizedAlgorithm>,
2238}
2239
2240impl TryFrom<RootedTraceableBox<RsaHashedKeyGenParams>> for SubtleRsaHashedKeyGenParams {
2241 type Error = Error;
2242
2243 fn try_from(value: RootedTraceableBox<RsaHashedKeyGenParams>) -> Result<Self, Self::Error> {
2244 let cx = GlobalScope::get_cx();
2245 Ok(SubtleRsaHashedKeyGenParams {
2246 name: value.parent.parent.name.to_string(),
2247 modulus_length: value.parent.modulusLength,
2248 public_exponent: value.parent.publicExponent.to_vec(),
2249 hash: Box::new(normalize_algorithm(
2250 cx,
2251 Operation::Digest,
2252 &value.hash,
2253 CanGc::note(),
2254 )?),
2255 })
2256 }
2257}
2258
2259#[derive(Clone, MallocSizeOf)]
2261pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2262 name: String,
2264
2265 modulus_length: u32,
2267
2268 public_exponent: Vec<u8>,
2270
2271 hash: Box<NormalizedAlgorithm>,
2273}
2274
2275impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2276 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2277 rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>());
2278 let public_exponent =
2279 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut(), can_gc)
2280 .expect("Fail to convert publicExponent to Uint8Array");
2281 let key_algorithm = KeyAlgorithm {
2282 name: self.name.clone().into(),
2283 };
2284 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2285 parent: key_algorithm,
2286 modulusLength: self.modulus_length,
2287 publicExponent: public_exponent,
2288 });
2289 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
2290 parent: rsa_key_algorithm,
2291 hash: KeyAlgorithm {
2292 name: self.hash.name().into(),
2293 },
2294 });
2295 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval, can_gc);
2296 }
2297}
2298
2299#[derive(Clone, MallocSizeOf)]
2301struct SubtleRsaHashedImportParams {
2302 name: String,
2304
2305 hash: Box<NormalizedAlgorithm>,
2307}
2308
2309impl TryFrom<RootedTraceableBox<RsaHashedImportParams>> for SubtleRsaHashedImportParams {
2310 type Error = Error;
2311
2312 fn try_from(value: RootedTraceableBox<RsaHashedImportParams>) -> Result<Self, Self::Error> {
2313 let cx = GlobalScope::get_cx();
2314 Ok(SubtleRsaHashedImportParams {
2315 name: value.parent.name.to_string(),
2316 hash: Box::new(normalize_algorithm(
2317 cx,
2318 Operation::Digest,
2319 &value.hash,
2320 CanGc::note(),
2321 )?),
2322 })
2323 }
2324}
2325
2326#[derive(Clone, Debug, MallocSizeOf)]
2328struct SubtleRsaPssParams {
2329 name: String,
2331
2332 salt_length: u32,
2334}
2335
2336impl From<RsaPssParams> for SubtleRsaPssParams {
2337 fn from(value: RsaPssParams) -> Self {
2338 SubtleRsaPssParams {
2339 name: value.parent.name.to_string(),
2340 salt_length: value.saltLength,
2341 }
2342 }
2343}
2344
2345#[derive(Clone, Debug, MallocSizeOf)]
2347struct SubtleRsaOaepParams {
2348 name: String,
2350 label: Option<Vec<u8>>,
2352}
2353
2354impl From<RootedTraceableBox<RsaOaepParams>> for SubtleRsaOaepParams {
2355 fn from(value: RootedTraceableBox<RsaOaepParams>) -> Self {
2356 let label = value.label.as_ref().map(|label| match label {
2357 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2358 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2359 });
2360 SubtleRsaOaepParams {
2361 name: value.parent.name.to_string(),
2362 label,
2363 }
2364 }
2365}
2366
2367#[derive(Clone, MallocSizeOf)]
2369struct SubtleEcdsaParams {
2370 name: String,
2372
2373 hash: Box<NormalizedAlgorithm>,
2375}
2376
2377impl TryFrom<RootedTraceableBox<EcdsaParams>> for SubtleEcdsaParams {
2378 type Error = Error;
2379
2380 fn try_from(value: RootedTraceableBox<EcdsaParams>) -> Result<Self, Error> {
2381 let cx = GlobalScope::get_cx();
2382 let hash = normalize_algorithm(cx, Operation::Digest, &value.hash, CanGc::note())?;
2383 Ok(SubtleEcdsaParams {
2384 name: value.parent.name.to_string(),
2385 hash: Box::new(hash),
2386 })
2387 }
2388}
2389
2390#[derive(Clone, Debug, MallocSizeOf)]
2392struct SubtleEcKeyGenParams {
2393 name: String,
2395
2396 named_curve: String,
2398}
2399
2400impl From<EcKeyGenParams> for SubtleEcKeyGenParams {
2401 fn from(value: EcKeyGenParams) -> Self {
2402 SubtleEcKeyGenParams {
2403 name: value.parent.name.to_string(),
2404 named_curve: value.namedCurve.to_string(),
2405 }
2406 }
2407}
2408
2409#[derive(Clone, Debug, MallocSizeOf)]
2411pub(crate) struct SubtleEcKeyAlgorithm {
2412 name: String,
2414
2415 named_curve: String,
2417}
2418
2419impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
2420 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2421 let parent = KeyAlgorithm {
2422 name: self.name.clone().into(),
2423 };
2424 let dictionary = EcKeyAlgorithm {
2425 parent,
2426 namedCurve: self.named_curve.clone().into(),
2427 };
2428 dictionary.safe_to_jsval(cx, rval, can_gc);
2429 }
2430}
2431
2432#[derive(Clone, Debug, MallocSizeOf)]
2434struct SubtleEcKeyImportParams {
2435 name: String,
2437
2438 named_curve: String,
2440}
2441
2442impl From<EcKeyImportParams> for SubtleEcKeyImportParams {
2443 fn from(value: EcKeyImportParams) -> Self {
2444 SubtleEcKeyImportParams {
2445 name: value.parent.name.to_string(),
2446 named_curve: value.namedCurve.to_string(),
2447 }
2448 }
2449}
2450
2451#[derive(Clone, MallocSizeOf)]
2453struct SubtleEcdhKeyDeriveParams {
2454 name: String,
2456
2457 public: Trusted<CryptoKey>,
2459}
2460
2461impl From<EcdhKeyDeriveParams> for SubtleEcdhKeyDeriveParams {
2462 fn from(value: EcdhKeyDeriveParams) -> Self {
2463 SubtleEcdhKeyDeriveParams {
2464 name: value.parent.name.to_string(),
2465 public: Trusted::new(&value.public),
2466 }
2467 }
2468}
2469
2470#[derive(Clone, Debug, MallocSizeOf)]
2472struct SubtleAesCtrParams {
2473 name: String,
2475
2476 counter: Vec<u8>,
2478
2479 length: u8,
2481}
2482
2483impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
2484 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
2485 let counter = match ¶ms.counter {
2486 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2487 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2488 };
2489 SubtleAesCtrParams {
2490 name: params.parent.name.to_string(),
2491 counter,
2492 length: params.length,
2493 }
2494 }
2495}
2496
2497#[derive(Clone, Debug, MallocSizeOf)]
2499pub(crate) struct SubtleAesKeyAlgorithm {
2500 name: String,
2502
2503 length: u16,
2505}
2506
2507impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
2508 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2509 let parent = KeyAlgorithm {
2510 name: self.name.clone().into(),
2511 };
2512 let dictionary = AesKeyAlgorithm {
2513 parent,
2514 length: self.length,
2515 };
2516 dictionary.safe_to_jsval(cx, rval, can_gc);
2517 }
2518}
2519
2520#[derive(Clone, Debug, MallocSizeOf)]
2522struct SubtleAesKeyGenParams {
2523 name: String,
2525
2526 length: u16,
2528}
2529
2530impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
2531 fn from(params: AesKeyGenParams) -> Self {
2532 SubtleAesKeyGenParams {
2533 name: params.parent.name.to_string(),
2534 length: params.length,
2535 }
2536 }
2537}
2538
2539#[derive(Clone, Debug, MallocSizeOf)]
2541struct SubtleAesDerivedKeyParams {
2542 name: String,
2544
2545 length: u16,
2547}
2548
2549impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
2550 fn from(params: AesDerivedKeyParams) -> Self {
2551 SubtleAesDerivedKeyParams {
2552 name: params.parent.name.to_string(),
2553 length: params.length,
2554 }
2555 }
2556}
2557
2558#[derive(Clone, Debug, MallocSizeOf)]
2560struct SubtleAesCbcParams {
2561 name: String,
2563
2564 iv: Vec<u8>,
2566}
2567
2568impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
2569 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
2570 let iv = match ¶ms.iv {
2571 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2572 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2573 };
2574 SubtleAesCbcParams {
2575 name: params.parent.name.to_string(),
2576 iv,
2577 }
2578 }
2579}
2580
2581#[derive(Clone, Debug, MallocSizeOf)]
2583struct SubtleAesGcmParams {
2584 name: String,
2586
2587 iv: Vec<u8>,
2589
2590 additional_data: Option<Vec<u8>>,
2592
2593 tag_length: Option<u8>,
2595}
2596
2597impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
2598 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
2599 let iv = match ¶ms.iv {
2600 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2601 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2602 };
2603 let additional_data = params.additionalData.as_ref().map(|data| match data {
2604 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2605 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2606 });
2607
2608 SubtleAesGcmParams {
2609 name: params.parent.name.to_string(),
2610 iv,
2611 additional_data,
2612 tag_length: params.tagLength,
2613 }
2614 }
2615}
2616
2617#[derive(Clone, MallocSizeOf)]
2619struct SubtleHmacImportParams {
2620 name: String,
2622
2623 hash: Box<NormalizedAlgorithm>,
2625
2626 length: Option<u32>,
2628}
2629
2630impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
2631 type Error = Error;
2632
2633 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
2634 let cx = GlobalScope::get_cx();
2635 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2636 Ok(SubtleHmacImportParams {
2637 name: params.parent.name.to_string(),
2638 hash: Box::new(hash),
2639 length: params.length,
2640 })
2641 }
2642}
2643
2644#[derive(Clone, Debug, MallocSizeOf)]
2646pub(crate) struct SubtleHmacKeyAlgorithm {
2647 name: String,
2649
2650 hash: SubtleKeyAlgorithm,
2652
2653 length: u32,
2655}
2656
2657impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
2658 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2659 let parent = KeyAlgorithm {
2660 name: self.name.clone().into(),
2661 };
2662 let hash = KeyAlgorithm {
2663 name: self.hash.name.clone().into(),
2664 };
2665 let dictionary = HmacKeyAlgorithm {
2666 parent,
2667 hash,
2668 length: self.length,
2669 };
2670 dictionary.safe_to_jsval(cx, rval, can_gc);
2671 }
2672}
2673
2674#[derive(Clone, MallocSizeOf)]
2676struct SubtleHmacKeyGenParams {
2677 name: String,
2679
2680 hash: Box<NormalizedAlgorithm>,
2682
2683 length: Option<u32>,
2685}
2686
2687impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
2688 type Error = Error;
2689
2690 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
2691 let cx = GlobalScope::get_cx();
2692 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2693 Ok(SubtleHmacKeyGenParams {
2694 name: params.parent.name.to_string(),
2695 hash: Box::new(hash),
2696 length: params.length,
2697 })
2698 }
2699}
2700
2701#[derive(Clone, MallocSizeOf)]
2703pub(crate) struct SubtleHkdfParams {
2704 name: String,
2706
2707 hash: Box<NormalizedAlgorithm>,
2709
2710 salt: Vec<u8>,
2712
2713 info: Vec<u8>,
2715}
2716
2717impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
2718 type Error = Error;
2719
2720 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
2721 let cx = GlobalScope::get_cx();
2722 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2723 let salt = match ¶ms.salt {
2724 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2725 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2726 };
2727 let info = match ¶ms.info {
2728 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2729 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2730 };
2731 Ok(SubtleHkdfParams {
2732 name: params.parent.name.to_string(),
2733 hash: Box::new(hash),
2734 salt,
2735 info,
2736 })
2737 }
2738}
2739
2740#[derive(Clone, MallocSizeOf)]
2742pub(crate) struct SubtlePbkdf2Params {
2743 name: String,
2745
2746 salt: Vec<u8>,
2748
2749 iterations: u32,
2751
2752 hash: Box<NormalizedAlgorithm>,
2754}
2755
2756impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
2757 type Error = Error;
2758
2759 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
2760 let cx = GlobalScope::get_cx();
2761 let salt = match ¶ms.salt {
2762 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2763 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2764 };
2765 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2766 Ok(SubtlePbkdf2Params {
2767 name: params.parent.name.to_string(),
2768 salt,
2769 iterations: params.iterations,
2770 hash: Box::new(hash),
2771 })
2772 }
2773}
2774
2775#[derive(Clone, Debug, MallocSizeOf)]
2777struct SubtleContextParams {
2778 name: String,
2780
2781 context: Option<Vec<u8>>,
2783}
2784
2785impl From<RootedTraceableBox<ContextParams>> for SubtleContextParams {
2786 fn from(value: RootedTraceableBox<ContextParams>) -> Self {
2787 let context = value.context.as_ref().map(|context| match context {
2788 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2789 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2790 });
2791 SubtleContextParams {
2792 name: value.parent.name.to_string(),
2793 context,
2794 }
2795 }
2796}
2797
2798#[derive(Clone, Debug, MallocSizeOf)]
2800struct SubtleAeadParams {
2801 name: String,
2803
2804 iv: Vec<u8>,
2806
2807 additional_data: Option<Vec<u8>>,
2809
2810 tag_length: Option<u8>,
2812}
2813
2814impl From<RootedTraceableBox<AeadParams>> for SubtleAeadParams {
2815 fn from(value: RootedTraceableBox<AeadParams>) -> Self {
2816 let iv = match &value.iv {
2817 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2818 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2819 };
2820 let additional_data = value.additionalData.as_ref().map(|data| match data {
2821 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2822 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2823 });
2824
2825 SubtleAeadParams {
2826 name: value.parent.name.to_string(),
2827 iv,
2828 additional_data,
2829 tag_length: value.tagLength,
2830 }
2831 }
2832}
2833
2834#[derive(Clone, Debug, MallocSizeOf)]
2836struct SubtleCShakeParams {
2837 name: String,
2839
2840 length: u32,
2842
2843 function_name: Option<Vec<u8>>,
2845
2846 customization: Option<Vec<u8>>,
2848}
2849
2850impl From<RootedTraceableBox<CShakeParams>> for SubtleCShakeParams {
2851 fn from(value: RootedTraceableBox<CShakeParams>) -> Self {
2852 let function_name = value
2853 .functionName
2854 .as_ref()
2855 .map(|function_name| match function_name {
2856 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2857 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2858 });
2859 let customization = value
2860 .customization
2861 .as_ref()
2862 .map(|customization| match customization {
2863 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2864 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2865 });
2866 SubtleCShakeParams {
2867 name: value.parent.name.to_string(),
2868 length: value.length,
2869 function_name,
2870 customization,
2871 }
2872 }
2873}
2874
2875#[derive(Clone, Debug, MallocSizeOf)]
2877struct SubtleArgon2Params {
2878 name: String,
2880
2881 nonce: Vec<u8>,
2883
2884 parallelism: u32,
2886
2887 memory: u32,
2889
2890 passes: u32,
2892
2893 version: Option<u8>,
2895
2896 secret_value: Option<Vec<u8>>,
2898
2899 associated_data: Option<Vec<u8>>,
2901}
2902
2903impl From<RootedTraceableBox<Argon2Params>> for SubtleArgon2Params {
2904 fn from(value: RootedTraceableBox<Argon2Params>) -> Self {
2905 let nonce = match &value.nonce {
2906 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2907 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2908 };
2909 let secret_value = value
2910 .secretValue
2911 .as_ref()
2912 .map(|secret_value| match secret_value {
2913 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2914 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2915 });
2916 let associated_data =
2917 value
2918 .associatedData
2919 .as_ref()
2920 .map(|associated_data| match associated_data {
2921 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2922 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2923 });
2924 SubtleArgon2Params {
2925 name: value.parent.name.to_string(),
2926 nonce,
2927 parallelism: value.parallelism,
2928 memory: value.memory,
2929 passes: value.passes,
2930 version: value.version,
2931 secret_value,
2932 associated_data,
2933 }
2934 }
2935}
2936
2937struct SubtleEncapsulatedKey {
2939 shared_key: Option<Trusted<CryptoKey>>,
2941
2942 ciphertext: Option<Vec<u8>>,
2944}
2945
2946impl SafeToJSValConvertible for SubtleEncapsulatedKey {
2947 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2948 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
2949 let ciphertext = self.ciphertext.as_ref().map(|data| {
2950 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
2951 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
2952 .expect("Failed to convert ciphertext to ArrayBufferU8")
2953 });
2954 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
2955 sharedKey: shared_key,
2956 ciphertext,
2957 });
2958 encapsulated_key.safe_to_jsval(cx, rval, can_gc);
2959 }
2960}
2961
2962struct SubtleEncapsulatedBits {
2964 shared_key: Option<Vec<u8>>,
2966
2967 ciphertext: Option<Vec<u8>>,
2969}
2970
2971impl SafeToJSValConvertible for SubtleEncapsulatedBits {
2972 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2973 let shared_key = self.shared_key.as_ref().map(|data| {
2974 rooted!(in(*cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
2975 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut(), can_gc)
2976 .expect("Failed to convert shared key to ArrayBufferU8")
2977 });
2978 let ciphertext = self.ciphertext.as_ref().map(|data| {
2979 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
2980 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
2981 .expect("Failed to convert ciphertext to ArrayBufferU8")
2982 });
2983 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
2984 sharedKey: shared_key,
2985 ciphertext,
2986 });
2987 encapsulated_bits.safe_to_jsval(cx, rval, can_gc);
2988 }
2989}
2990
2991fn dictionary_from_jsval<T>(cx: JSContext, value: HandleValue, can_gc: CanGc) -> Fallible<T>
2993where
2994 T: SafeFromJSValConvertible<Config = ()>,
2995{
2996 let conversion = T::safe_from_jsval(cx, value, (), can_gc).map_err(|_| Error::JSFailed)?;
2997 match conversion {
2998 ConversionResult::Success(dictionary) => Ok(dictionary),
2999 ConversionResult::Failure(error) => Err(Error::Type(error.into_owned())),
3000 }
3001}
3002
3003enum ExportedKey {
3007 Bytes(Vec<u8>),
3008 Jwk(Box<JsonWebKey>),
3009}
3010
3011#[derive(Clone, MallocSizeOf)]
3015#[expect(clippy::enum_variant_names)]
3016pub(crate) enum KeyAlgorithmAndDerivatives {
3017 KeyAlgorithm(SubtleKeyAlgorithm),
3018 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
3019 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
3020 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
3021 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
3022}
3023
3024impl KeyAlgorithmAndDerivatives {
3025 fn name(&self) -> &str {
3026 match self {
3027 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
3028 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => &algo.name,
3029 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => &algo.name,
3030 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
3031 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
3032 }
3033 }
3034}
3035
3036impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
3037 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3038 match self {
3039 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
3040 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => {
3041 algo.safe_to_jsval(cx, rval, can_gc)
3042 },
3043 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
3044 algo.safe_to_jsval(cx, rval, can_gc)
3045 },
3046 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
3047 algo.safe_to_jsval(cx, rval, can_gc)
3048 },
3049 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
3050 algo.safe_to_jsval(cx, rval, can_gc)
3051 },
3052 }
3053 }
3054}
3055
3056#[derive(Clone, Copy)]
3057enum JwkStringField {
3058 X,
3059 Y,
3060 D,
3061 N,
3062 E,
3063 P,
3064 Q,
3065 DP,
3066 DQ,
3067 QI,
3068 K,
3069 Priv,
3070 Pub,
3071}
3072
3073impl Display for JwkStringField {
3074 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3075 let field_name = match self {
3076 JwkStringField::X => "x",
3077 JwkStringField::Y => "y",
3078 JwkStringField::D => "d",
3079 JwkStringField::N => "n",
3080 JwkStringField::E => "e",
3081 JwkStringField::P => "q",
3082 JwkStringField::Q => "q",
3083 JwkStringField::DP => "dp",
3084 JwkStringField::DQ => "dq",
3085 JwkStringField::QI => "qi",
3086 JwkStringField::K => "k",
3087 JwkStringField::Priv => "priv",
3088 JwkStringField::Pub => "pub",
3089 };
3090 write!(f, "{}", field_name)
3091 }
3092}
3093
3094trait JsonWebKeyExt {
3095 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
3096 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
3097 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
3098 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
3099 fn set_key_ops(&mut self, usages: Vec<KeyUsage>);
3100 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
3101 fn decode_optional_string_field(&self, field: JwkStringField)
3102 -> Result<Option<Vec<u8>>, Error>;
3103 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error>;
3104 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error>;
3105}
3106
3107impl JsonWebKeyExt for JsonWebKey {
3108 #[expect(unsafe_code)]
3110 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
3111 let json = String::from_utf8_lossy(data);
3116
3117 let json: Vec<_> = json.encode_utf16().collect();
3119
3120 rooted!(in(*cx) let mut result = UndefinedValue());
3124 unsafe {
3125 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
3126 return Err(Error::JSFailed);
3127 }
3128 }
3129
3130 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
3132 Ok(ConversionResult::Success(key)) => key,
3133 Ok(ConversionResult::Failure(error)) => {
3134 return Err(Error::Type(error.into_owned()));
3135 },
3136 Err(()) => {
3137 return Err(Error::JSFailed);
3138 },
3139 };
3140
3141 if key.kty.is_none() {
3143 return Err(Error::Data(None));
3144 }
3145
3146 Ok(key)
3148 }
3149
3150 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
3156 rooted!(in(*cx) let mut data = UndefinedValue());
3157 self.safe_to_jsval(cx, data.handle_mut(), CanGc::note());
3158 serialize_jsval_to_json_utf8(cx, data.handle())
3159 }
3160
3161 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
3162 let mut usages = vec![];
3163 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
3164 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
3165 }
3166 Ok(usages)
3167 }
3168
3169 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
3173 if let Some(ref key_ops) = self.key_ops {
3175 if key_ops
3178 .iter()
3179 .collect::<std::collections::HashSet<_>>()
3180 .len() <
3181 key_ops.len()
3182 {
3183 return Err(Error::Data(None));
3184 }
3185 if let Some(ref use_) = self.use_ {
3188 if key_ops.iter().any(|op| op != use_) {
3189 return Err(Error::Data(None));
3190 }
3191 }
3192
3193 let key_ops_as_usages = self.get_usages_from_key_ops()?;
3195 if !specified_usages
3196 .iter()
3197 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
3198 {
3199 return Err(Error::Data(None));
3200 }
3201 }
3202
3203 Ok(())
3204 }
3205
3206 fn set_key_ops(&mut self, usages: Vec<KeyUsage>) {
3208 self.key_ops = Some(
3209 usages
3210 .into_iter()
3211 .map(|usage| DOMString::from(usage.as_str()))
3212 .collect(),
3213 );
3214 }
3215
3216 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
3219 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
3220 match field {
3221 JwkStringField::X => self.x = Some(encoded_data),
3222 JwkStringField::Y => self.y = Some(encoded_data),
3223 JwkStringField::D => self.d = Some(encoded_data),
3224 JwkStringField::N => self.n = Some(encoded_data),
3225 JwkStringField::E => self.e = Some(encoded_data),
3226 JwkStringField::P => self.p = Some(encoded_data),
3227 JwkStringField::Q => self.q = Some(encoded_data),
3228 JwkStringField::DP => self.dp = Some(encoded_data),
3229 JwkStringField::DQ => self.dq = Some(encoded_data),
3230 JwkStringField::QI => self.qi = Some(encoded_data),
3231 JwkStringField::K => self.k = Some(encoded_data),
3232 JwkStringField::Priv => self.priv_ = Some(encoded_data),
3233 JwkStringField::Pub => self.pub_ = Some(encoded_data),
3234 }
3235 }
3236
3237 fn decode_optional_string_field(
3240 &self,
3241 field: JwkStringField,
3242 ) -> Result<Option<Vec<u8>>, Error> {
3243 let field_string = match field {
3244 JwkStringField::X => &self.x,
3245 JwkStringField::Y => &self.y,
3246 JwkStringField::D => &self.d,
3247 JwkStringField::N => &self.n,
3248 JwkStringField::E => &self.e,
3249 JwkStringField::P => &self.p,
3250 JwkStringField::Q => &self.q,
3251 JwkStringField::DP => &self.dp,
3252 JwkStringField::DQ => &self.dq,
3253 JwkStringField::QI => &self.qi,
3254 JwkStringField::K => &self.k,
3255 JwkStringField::Priv => &self.priv_,
3256 JwkStringField::Pub => &self.pub_,
3257 };
3258
3259 field_string
3260 .as_ref()
3261 .map(|field_string| Base64UrlUnpadded::decode_vec(&field_string.str()))
3262 .transpose()
3263 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
3264 }
3265
3266 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error> {
3269 self.decode_optional_string_field(field)?
3270 .ok_or(Error::Data(Some(format!(
3271 "The {} field is not present in jwk",
3272 field
3273 ))))
3274 }
3275
3276 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error> {
3285 if self.oth.is_some() &&
3286 (self.p.is_none() ||
3287 self.q.is_none() ||
3288 self.dp.is_none() ||
3289 self.dq.is_none() ||
3290 self.qi.is_none())
3291 {
3292 return Err(Error::Data(Some(
3293 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
3294 )));
3295 }
3296
3297 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
3298 let r = Base64UrlUnpadded::decode_vec(
3299 &rsa_other_prime_info
3300 .r
3301 .as_ref()
3302 .ok_or(Error::Data(Some(
3303 "The r field is not present in one of the entry of oth field in jwk"
3304 .to_string(),
3305 )))?
3306 .str(),
3307 )
3308 .map_err(|_| {
3309 Error::Data(Some(
3310 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
3311 ))
3312 })?;
3313 primes.push(r);
3314
3315 let _d = Base64UrlUnpadded::decode_vec(
3316 &rsa_other_prime_info
3317 .d
3318 .as_ref()
3319 .ok_or(Error::Data(Some(
3320 "The d field is not present in one of the entry of oth field in jwk"
3321 .to_string(),
3322 )))?
3323 .str(),
3324 )
3325 .map_err(|_| {
3326 Error::Data(Some(
3327 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
3328 ))
3329 })?;
3330
3331 let _t = Base64UrlUnpadded::decode_vec(
3332 &rsa_other_prime_info
3333 .t
3334 .as_ref()
3335 .ok_or(Error::Data(Some(
3336 "The t field is not present in one of the entry of oth field in jwk"
3337 .to_string(),
3338 )))?
3339 .str(),
3340 )
3341 .map_err(|_| {
3342 Error::Data(Some(
3343 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
3344 ))
3345 })?;
3346 }
3347
3348 Ok(())
3349 }
3350}
3351
3352enum ShaAlgorithm {
3354 Sha1,
3355 Sha256,
3356 Sha384,
3357 Sha512,
3358}
3359
3360impl ShaAlgorithm {
3361 fn as_str(&self) -> &'static str {
3362 match self {
3363 ShaAlgorithm::Sha1 => ALG_SHA1,
3364 ShaAlgorithm::Sha256 => ALG_SHA256,
3365 ShaAlgorithm::Sha384 => ALG_SHA384,
3366 ShaAlgorithm::Sha512 => ALG_SHA512,
3367 }
3368 }
3369}
3370
3371enum MlKemAlgorithm {
3373 MlKem512,
3374 MlKem768,
3375 MlKem1024,
3376}
3377
3378impl MlKemAlgorithm {
3379 fn as_str(&self) -> &'static str {
3380 match self {
3381 MlKemAlgorithm::MlKem512 => ALG_ML_KEM_512,
3382 MlKemAlgorithm::MlKem768 => ALG_ML_KEM_768,
3383 MlKemAlgorithm::MlKem1024 => ALG_ML_KEM_1024,
3384 }
3385 }
3386}
3387
3388enum MlDsaAlgorithm {
3390 MlDsa44,
3391 MlDsa65,
3392 MlDsa87,
3393}
3394
3395impl MlDsaAlgorithm {
3396 fn as_str(&self) -> &'static str {
3397 match self {
3398 MlDsaAlgorithm::MlDsa44 => ALG_ML_DSA_44,
3399 MlDsaAlgorithm::MlDsa65 => ALG_ML_DSA_65,
3400 MlDsaAlgorithm::MlDsa87 => ALG_ML_DSA_87,
3401 }
3402 }
3403}
3404
3405enum Sha3Algorithm {
3407 Sha3_256,
3408 Sha3_384,
3409 Sha3_512,
3410}
3411
3412impl Sha3Algorithm {
3413 fn as_str(&self) -> &'static str {
3414 match self {
3415 Sha3Algorithm::Sha3_256 => ALG_SHA3_256,
3416 Sha3Algorithm::Sha3_384 => ALG_SHA3_384,
3417 Sha3Algorithm::Sha3_512 => ALG_SHA3_512,
3418 }
3419 }
3420}
3421
3422enum CShakeAlgorithm {
3424 CShake128,
3425 CShake256,
3426}
3427
3428impl CShakeAlgorithm {
3429 fn as_str(&self) -> &'static str {
3430 match self {
3431 CShakeAlgorithm::CShake128 => ALG_CSHAKE_128,
3432 CShakeAlgorithm::CShake256 => ALG_CSHAKE_256,
3433 }
3434 }
3435}
3436
3437enum Argon2Algorithm {
3439 Argon2D,
3440 Argon2I,
3441 Argon2ID,
3442}
3443
3444impl Argon2Algorithm {
3445 fn as_str(&self) -> &'static str {
3446 match self {
3447 Argon2Algorithm::Argon2D => ALG_ARGON2D,
3448 Argon2Algorithm::Argon2I => ALG_ARGON2I,
3449 Argon2Algorithm::Argon2ID => ALG_ARGON2ID,
3450 }
3451 }
3452}
3453
3454enum SupportedAlgorithm {
3456 RsassaPkcs1V1_5,
3457 RsaPss,
3458 RsaOaep,
3459 Ecdsa,
3460 Ecdh,
3461 Ed25519,
3462 X25519,
3463 AesCtr,
3464 AesCbc,
3465 AesGcm,
3466 AesKw,
3467 Hmac,
3468 Sha(ShaAlgorithm),
3469 Hkdf,
3470 Pbkdf2,
3471 MlKem(MlKemAlgorithm),
3472 MlDsa(MlDsaAlgorithm),
3473 AesOcb,
3474 ChaCha20Poly1305,
3475 Sha3(Sha3Algorithm),
3476 CShake(CShakeAlgorithm),
3477 Argon2(Argon2Algorithm),
3478}
3479
3480impl SupportedAlgorithm {
3481 fn as_str(&self) -> &'static str {
3482 match self {
3483 SupportedAlgorithm::RsassaPkcs1V1_5 => ALG_RSASSA_PKCS1_V1_5,
3484 SupportedAlgorithm::RsaPss => ALG_RSA_PSS,
3485 SupportedAlgorithm::RsaOaep => ALG_RSA_OAEP,
3486 SupportedAlgorithm::Ecdsa => ALG_ECDSA,
3487 SupportedAlgorithm::Ecdh => ALG_ECDH,
3488 SupportedAlgorithm::Ed25519 => ALG_ED25519,
3489 SupportedAlgorithm::X25519 => ALG_X25519,
3490 SupportedAlgorithm::AesCtr => ALG_AES_CTR,
3491 SupportedAlgorithm::AesCbc => ALG_AES_CBC,
3492 SupportedAlgorithm::AesGcm => ALG_AES_GCM,
3493 SupportedAlgorithm::AesKw => ALG_AES_KW,
3494 SupportedAlgorithm::Hmac => ALG_HMAC,
3495 SupportedAlgorithm::Sha(sha_algorithm) => sha_algorithm.as_str(),
3496 SupportedAlgorithm::Hkdf => ALG_HKDF,
3497 SupportedAlgorithm::Pbkdf2 => ALG_PBKDF2,
3498 SupportedAlgorithm::MlKem(ml_kem_algorithm) => ml_kem_algorithm.as_str(),
3499 SupportedAlgorithm::MlDsa(ml_dsa_algorithm) => ml_dsa_algorithm.as_str(),
3500 SupportedAlgorithm::AesOcb => ALG_AES_OCB,
3501 SupportedAlgorithm::ChaCha20Poly1305 => ALG_CHACHA20_POLY1305,
3502 SupportedAlgorithm::Sha3(sha3_algorithm) => sha3_algorithm.as_str(),
3503 SupportedAlgorithm::CShake(cshake_algorithm) => cshake_algorithm.as_str(),
3504 SupportedAlgorithm::Argon2(argon2_algorithm) => argon2_algorithm.as_str(),
3505 }
3506 }
3507
3508 fn from_ignore_case(alg_name: &str) -> Result<SupportedAlgorithm, Error> {
3509 let Some(&alg_name) = SUPPORTED_ALGORITHMS
3510 .iter()
3511 .find(|supported_algorithm| supported_algorithm.eq_ignore_ascii_case(alg_name))
3512 else {
3513 return Err(Error::NotSupported(Some(format!(
3514 "Unsupported algorithm: {}",
3515 alg_name
3516 ))));
3517 };
3518 SupportedAlgorithm::try_from(alg_name)
3519 }
3520
3521 fn support(&self, op: Operation) -> Result<ParameterType, Error> {
3529 let desired_type = match (self, &op) {
3530 (Self::RsassaPkcs1V1_5, Operation::Sign) => ParameterType::None,
3532 (Self::RsassaPkcs1V1_5, Operation::Verify) => ParameterType::None,
3533 (Self::RsassaPkcs1V1_5, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3534 (Self::RsassaPkcs1V1_5, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3535 (Self::RsassaPkcs1V1_5, Operation::ExportKey) => ParameterType::None,
3536
3537 (Self::RsaPss, Operation::Sign) => ParameterType::RsaPssParams,
3539 (Self::RsaPss, Operation::Verify) => ParameterType::RsaPssParams,
3540 (Self::RsaPss, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3541 (Self::RsaPss, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3542 (Self::RsaPss, Operation::ExportKey) => ParameterType::None,
3543
3544 (Self::RsaOaep, Operation::Encrypt) => ParameterType::RsaOaepParams,
3546 (Self::RsaOaep, Operation::Decrypt) => ParameterType::RsaOaepParams,
3547 (Self::RsaOaep, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3548 (Self::RsaOaep, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3549 (Self::RsaOaep, Operation::ExportKey) => ParameterType::None,
3550
3551 (Self::Ecdsa, Operation::Sign) => ParameterType::EcdsaParams,
3553 (Self::Ecdsa, Operation::Verify) => ParameterType::EcdsaParams,
3554 (Self::Ecdsa, Operation::GenerateKey) => ParameterType::EcKeyGenParams,
3555 (Self::Ecdsa, Operation::ImportKey) => ParameterType::EcKeyImportParams,
3556 (Self::Ecdsa, Operation::ExportKey) => ParameterType::None,
3557
3558 (Self::Ecdh, Operation::GenerateKey) => ParameterType::EcKeyGenParams,
3560 (Self::Ecdh, Operation::DeriveBits) => ParameterType::EcdhKeyDeriveParams,
3561 (Self::Ecdh, Operation::ImportKey) => ParameterType::EcKeyImportParams,
3562 (Self::Ecdh, Operation::ExportKey) => ParameterType::None,
3563
3564 (Self::Ed25519, Operation::Sign) => ParameterType::None,
3566 (Self::Ed25519, Operation::Verify) => ParameterType::None,
3567 (Self::Ed25519, Operation::GenerateKey) => ParameterType::None,
3568 (Self::Ed25519, Operation::ImportKey) => ParameterType::None,
3569 (Self::Ed25519, Operation::ExportKey) => ParameterType::None,
3570
3571 (Self::X25519, Operation::DeriveBits) => ParameterType::EcdhKeyDeriveParams,
3573 (Self::X25519, Operation::GenerateKey) => ParameterType::None,
3574 (Self::X25519, Operation::ImportKey) => ParameterType::None,
3575 (Self::X25519, Operation::ExportKey) => ParameterType::None,
3576
3577 (Self::AesCtr, Operation::Encrypt) => ParameterType::AesCtrParams,
3579 (Self::AesCtr, Operation::Decrypt) => ParameterType::AesCtrParams,
3580 (Self::AesCtr, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3581 (Self::AesCtr, Operation::ImportKey) => ParameterType::None,
3582 (Self::AesCtr, Operation::ExportKey) => ParameterType::None,
3583 (Self::AesCtr, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3584
3585 (Self::AesCbc, Operation::Encrypt) => ParameterType::AesCbcParams,
3587 (Self::AesCbc, Operation::Decrypt) => ParameterType::AesCbcParams,
3588 (Self::AesCbc, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3589 (Self::AesCbc, Operation::ImportKey) => ParameterType::None,
3590 (Self::AesCbc, Operation::ExportKey) => ParameterType::None,
3591 (Self::AesCbc, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3592
3593 (Self::AesGcm, Operation::Encrypt) => ParameterType::AesGcmParams,
3595 (Self::AesGcm, Operation::Decrypt) => ParameterType::AesGcmParams,
3596 (Self::AesGcm, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3597 (Self::AesGcm, Operation::ImportKey) => ParameterType::None,
3598 (Self::AesGcm, Operation::ExportKey) => ParameterType::None,
3599 (Self::AesGcm, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3600
3601 (Self::AesKw, Operation::WrapKey) => ParameterType::None,
3603 (Self::AesKw, Operation::UnwrapKey) => ParameterType::None,
3604 (Self::AesKw, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3605 (Self::AesKw, Operation::ImportKey) => ParameterType::None,
3606 (Self::AesKw, Operation::ExportKey) => ParameterType::None,
3607 (Self::AesKw, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3608
3609 (Self::Hmac, Operation::Sign) => ParameterType::None,
3611 (Self::Hmac, Operation::Verify) => ParameterType::None,
3612 (Self::Hmac, Operation::GenerateKey) => ParameterType::HmacKeyGenParams,
3613 (Self::Hmac, Operation::ImportKey) => ParameterType::HmacImportParams,
3614 (Self::Hmac, Operation::ExportKey) => ParameterType::None,
3615 (Self::Hmac, Operation::GetKeyLength) => ParameterType::HmacImportParams,
3616
3617 (Self::Sha(_), Operation::Digest) => ParameterType::None,
3619
3620 (Self::Hkdf, Operation::DeriveBits) => ParameterType::HkdfParams,
3622 (Self::Hkdf, Operation::ImportKey) => ParameterType::None,
3623 (Self::Hkdf, Operation::GetKeyLength) => ParameterType::None,
3624
3625 (Self::Pbkdf2, Operation::DeriveBits) => ParameterType::Pbkdf2Params,
3627 (Self::Pbkdf2, Operation::ImportKey) => ParameterType::None,
3628 (Self::Pbkdf2, Operation::GetKeyLength) => ParameterType::None,
3629
3630 (Self::MlKem(_), Operation::Encapsulate) => ParameterType::None,
3632 (Self::MlKem(_), Operation::Decapsulate) => ParameterType::None,
3633 (Self::MlKem(_), Operation::GenerateKey) => ParameterType::None,
3634 (Self::MlKem(_), Operation::ImportKey) => ParameterType::None,
3635 (Self::MlKem(_), Operation::ExportKey) => ParameterType::None,
3636
3637 (Self::MlDsa(_), Operation::Sign) => ParameterType::ContextParams,
3639 (Self::MlDsa(_), Operation::Verify) => ParameterType::ContextParams,
3640 (Self::MlDsa(_), Operation::GenerateKey) => ParameterType::None,
3641 (Self::MlDsa(_), Operation::ImportKey) => ParameterType::None,
3642 (Self::MlDsa(_), Operation::ExportKey) => ParameterType::None,
3643
3644 (Self::AesOcb, Operation::Encrypt) => ParameterType::AeadParams,
3646 (Self::AesOcb, Operation::Decrypt) => ParameterType::AeadParams,
3647 (Self::AesOcb, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3648 (Self::AesOcb, Operation::ImportKey) => ParameterType::None,
3649 (Self::AesOcb, Operation::ExportKey) => ParameterType::None,
3650 (Self::AesOcb, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3651
3652 (Self::ChaCha20Poly1305, Operation::Encrypt) => ParameterType::AeadParams,
3654 (Self::ChaCha20Poly1305, Operation::Decrypt) => ParameterType::AeadParams,
3655 (Self::ChaCha20Poly1305, Operation::GenerateKey) => ParameterType::None,
3656 (Self::ChaCha20Poly1305, Operation::ImportKey) => ParameterType::None,
3657 (Self::ChaCha20Poly1305, Operation::ExportKey) => ParameterType::None,
3658 (Self::ChaCha20Poly1305, Operation::GetKeyLength) => ParameterType::None,
3659
3660 (Self::Sha3(_), Operation::Digest) => ParameterType::None,
3662
3663 (Self::CShake(_), Operation::Digest) => ParameterType::CShakeParams,
3665
3666 (Self::Argon2(_), Operation::DeriveBits) => ParameterType::Argon2Params,
3668 (Self::Argon2(_), Operation::ImportKey) => ParameterType::None,
3669 (Self::Argon2(_), Operation::GetKeyLength) => ParameterType::None,
3670
3671 _ => {
3672 return Err(Error::NotSupported(Some(format!(
3673 "{} does not support {} operation",
3674 self.as_str(),
3675 op.as_str()
3676 ))));
3677 },
3678 };
3679
3680 Ok(desired_type)
3681 }
3682}
3683
3684impl TryFrom<&str> for SupportedAlgorithm {
3685 type Error = Error;
3686
3687 fn try_from(value: &str) -> Result<Self, Self::Error> {
3688 match value {
3689 ALG_RSASSA_PKCS1_V1_5 => Ok(SupportedAlgorithm::RsassaPkcs1V1_5),
3690 ALG_RSA_PSS => Ok(SupportedAlgorithm::RsaPss),
3691 ALG_RSA_OAEP => Ok(SupportedAlgorithm::RsaOaep),
3692 ALG_ECDSA => Ok(SupportedAlgorithm::Ecdsa),
3693 ALG_ECDH => Ok(SupportedAlgorithm::Ecdh),
3694 ALG_ED25519 => Ok(SupportedAlgorithm::Ed25519),
3695 ALG_X25519 => Ok(SupportedAlgorithm::X25519),
3696 ALG_AES_CTR => Ok(SupportedAlgorithm::AesCtr),
3697 ALG_AES_CBC => Ok(SupportedAlgorithm::AesCbc),
3698 ALG_AES_GCM => Ok(SupportedAlgorithm::AesGcm),
3699 ALG_AES_KW => Ok(SupportedAlgorithm::AesKw),
3700 ALG_HMAC => Ok(SupportedAlgorithm::Hmac),
3701 ALG_SHA1 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha1)),
3702 ALG_SHA256 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha256)),
3703 ALG_SHA384 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha384)),
3704 ALG_SHA512 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha512)),
3705 ALG_HKDF => Ok(SupportedAlgorithm::Hkdf),
3706 ALG_PBKDF2 => Ok(SupportedAlgorithm::Pbkdf2),
3707 ALG_ML_KEM_512 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem512)),
3708 ALG_ML_KEM_768 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem768)),
3709 ALG_ML_KEM_1024 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem1024)),
3710 ALG_ML_DSA_44 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa44)),
3711 ALG_ML_DSA_65 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa65)),
3712 ALG_ML_DSA_87 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa87)),
3713 ALG_AES_OCB => Ok(SupportedAlgorithm::AesOcb),
3714 ALG_CHACHA20_POLY1305 => Ok(SupportedAlgorithm::ChaCha20Poly1305),
3715 ALG_SHA3_256 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_256)),
3716 ALG_SHA3_384 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_384)),
3717 ALG_SHA3_512 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_512)),
3718 ALG_CSHAKE_128 => Ok(SupportedAlgorithm::CShake(CShakeAlgorithm::CShake128)),
3719 ALG_CSHAKE_256 => Ok(SupportedAlgorithm::CShake(CShakeAlgorithm::CShake256)),
3720 ALG_ARGON2D => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2D)),
3721 ALG_ARGON2I => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2I)),
3722 ALG_ARGON2ID => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2ID)),
3723 _ => Err(Error::NotSupported(Some(format!(
3724 "Unsupported algorithm: {}",
3725 value
3726 )))),
3727 }
3728 }
3729}
3730
3731enum ParameterType {
3732 None,
3733 RsaHashedKeyGenParams,
3734 RsaHashedImportParams,
3735 RsaPssParams,
3736 RsaOaepParams,
3737 EcdsaParams,
3738 EcKeyGenParams,
3739 EcKeyImportParams,
3740 EcdhKeyDeriveParams,
3741 AesCtrParams,
3742 AesKeyGenParams,
3743 AesDerivedKeyParams,
3744 AesCbcParams,
3745 AesGcmParams,
3746 HmacImportParams,
3747 HmacKeyGenParams,
3748 HkdfParams,
3749 Pbkdf2Params,
3750 ContextParams,
3751 AeadParams,
3752 CShakeParams,
3753 Argon2Params,
3754}
3755
3756#[derive(Clone, MallocSizeOf)]
3761enum NormalizedAlgorithm {
3762 Algorithm(SubtleAlgorithm),
3763 RsaHashedKeyGenParams(SubtleRsaHashedKeyGenParams),
3764 RsaHashedImportParams(SubtleRsaHashedImportParams),
3765 RsaPssParams(SubtleRsaPssParams),
3766 RsaOaepParams(SubtleRsaOaepParams),
3767 EcdsaParams(SubtleEcdsaParams),
3768 EcKeyGenParams(SubtleEcKeyGenParams),
3769 EcKeyImportParams(SubtleEcKeyImportParams),
3770 EcdhKeyDeriveParams(SubtleEcdhKeyDeriveParams),
3771 AesCtrParams(SubtleAesCtrParams),
3772 AesKeyGenParams(SubtleAesKeyGenParams),
3773 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
3774 AesCbcParams(SubtleAesCbcParams),
3775 AesGcmParams(SubtleAesGcmParams),
3776 HmacImportParams(SubtleHmacImportParams),
3777 HmacKeyGenParams(SubtleHmacKeyGenParams),
3778 HkdfParams(SubtleHkdfParams),
3779 Pbkdf2Params(SubtlePbkdf2Params),
3780 ContextParams(SubtleContextParams),
3781 AeadParams(SubtleAeadParams),
3782 CShakeParams(SubtleCShakeParams),
3783 Argon2Params(SubtleArgon2Params),
3784}
3785
3786fn normalize_algorithm(
3788 cx: JSContext,
3789 op: Operation,
3790 alg: &AlgorithmIdentifier,
3791 can_gc: CanGc,
3792) -> Result<NormalizedAlgorithm, Error> {
3793 match alg {
3794 ObjectOrString::String(name) => {
3796 let alg = Algorithm {
3800 name: name.to_owned(),
3801 };
3802 rooted!(in(*cx) let mut alg_value = UndefinedValue());
3803 alg.safe_to_jsval(cx, alg_value.handle_mut(), CanGc::note());
3804 let alg_obj = RootedTraceableBox::new(Heap::default());
3805 alg_obj.set(alg_value.to_object());
3806 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj), can_gc)
3807 },
3808 ObjectOrString::Object(obj) => {
3810 rooted!(in(*cx) let value = ObjectValue(obj.get()));
3819 let initial_alg = dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3820
3821 let alg_name = SupportedAlgorithm::from_ignore_case(&initial_alg.name.str())?;
3831 let desired_type = alg_name.support(op)?;
3832
3833 rooted!(in(*cx) let mut alg_name_ptr = UndefinedValue());
3863 alg_name
3864 .as_str()
3865 .safe_to_jsval(cx, alg_name_ptr.handle_mut(), can_gc);
3866 set_dictionary_property(cx, obj.handle(), c"name", alg_name_ptr.handle())
3867 .map_err(|_| Error::JSFailed)?;
3868 let normalized_algorithm =
3869 NormalizedAlgorithm::from_object_value(cx, value.handle(), desired_type, can_gc)?;
3870
3871 Ok(normalized_algorithm)
3873 },
3874 }
3875}
3876
3877impl NormalizedAlgorithm {
3878 fn from_object_value(
3888 cx: JSContext,
3889 value: HandleValue,
3890 desired_type: ParameterType,
3891 can_gc: CanGc,
3892 ) -> Result<NormalizedAlgorithm, Error> {
3893 let normalized_algorithm = match desired_type {
3894 ParameterType::None => NormalizedAlgorithm::Algorithm(
3895 dictionary_from_jsval::<Algorithm>(cx, value, can_gc)?.into(),
3896 ),
3897 ParameterType::RsaHashedKeyGenParams => NormalizedAlgorithm::RsaHashedKeyGenParams(
3898 dictionary_from_jsval::<RootedTraceableBox<RsaHashedKeyGenParams>>(
3899 cx, value, can_gc,
3900 )?
3901 .try_into()?,
3902 ),
3903 ParameterType::RsaHashedImportParams => NormalizedAlgorithm::RsaHashedImportParams(
3904 dictionary_from_jsval::<RootedTraceableBox<RsaHashedImportParams>>(
3905 cx, value, can_gc,
3906 )?
3907 .try_into()?,
3908 ),
3909 ParameterType::RsaPssParams => NormalizedAlgorithm::RsaPssParams(
3910 dictionary_from_jsval::<RsaPssParams>(cx, value, can_gc)?.into(),
3911 ),
3912 ParameterType::RsaOaepParams => NormalizedAlgorithm::RsaOaepParams(
3913 dictionary_from_jsval::<RootedTraceableBox<RsaOaepParams>>(cx, value, can_gc)?
3914 .into(),
3915 ),
3916 ParameterType::EcdsaParams => NormalizedAlgorithm::EcdsaParams(
3917 dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(cx, value, can_gc)?
3918 .try_into()?,
3919 ),
3920 ParameterType::EcKeyGenParams => NormalizedAlgorithm::EcKeyGenParams(
3921 dictionary_from_jsval::<EcKeyGenParams>(cx, value, can_gc)?.into(),
3922 ),
3923 ParameterType::EcKeyImportParams => NormalizedAlgorithm::EcKeyImportParams(
3924 dictionary_from_jsval::<EcKeyImportParams>(cx, value, can_gc)?.into(),
3925 ),
3926 ParameterType::EcdhKeyDeriveParams => NormalizedAlgorithm::EcdhKeyDeriveParams(
3927 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value, can_gc)?.into(),
3928 ),
3929 ParameterType::AesCtrParams => NormalizedAlgorithm::AesCtrParams(
3930 dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(cx, value, can_gc)?
3931 .into(),
3932 ),
3933 ParameterType::AesKeyGenParams => NormalizedAlgorithm::AesKeyGenParams(
3934 dictionary_from_jsval::<AesKeyGenParams>(cx, value, can_gc)?.into(),
3935 ),
3936 ParameterType::AesDerivedKeyParams => NormalizedAlgorithm::AesDerivedKeyParams(
3937 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value, can_gc)?.into(),
3938 ),
3939 ParameterType::AesCbcParams => NormalizedAlgorithm::AesCbcParams(
3940 dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(cx, value, can_gc)?
3941 .into(),
3942 ),
3943 ParameterType::AesGcmParams => NormalizedAlgorithm::AesGcmParams(
3944 dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(cx, value, can_gc)?
3945 .into(),
3946 ),
3947 ParameterType::HmacImportParams => NormalizedAlgorithm::HmacImportParams(
3948 dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(cx, value, can_gc)?
3949 .try_into()?,
3950 ),
3951 ParameterType::HmacKeyGenParams => NormalizedAlgorithm::HmacKeyGenParams(
3952 dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(cx, value, can_gc)?
3953 .try_into()?,
3954 ),
3955 ParameterType::HkdfParams => NormalizedAlgorithm::HkdfParams(
3956 dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(cx, value, can_gc)?
3957 .try_into()?,
3958 ),
3959 ParameterType::Pbkdf2Params => NormalizedAlgorithm::Pbkdf2Params(
3960 dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(cx, value, can_gc)?
3961 .try_into()?,
3962 ),
3963 ParameterType::ContextParams => NormalizedAlgorithm::ContextParams(
3964 dictionary_from_jsval::<RootedTraceableBox<ContextParams>>(cx, value, can_gc)?
3965 .into(),
3966 ),
3967 ParameterType::AeadParams => NormalizedAlgorithm::AeadParams(
3968 dictionary_from_jsval::<RootedTraceableBox<AeadParams>>(cx, value, can_gc)?.into(),
3969 ),
3970 ParameterType::CShakeParams => NormalizedAlgorithm::CShakeParams(
3971 dictionary_from_jsval::<RootedTraceableBox<CShakeParams>>(cx, value, can_gc)?
3972 .into(),
3973 ),
3974 ParameterType::Argon2Params => NormalizedAlgorithm::Argon2Params(
3975 dictionary_from_jsval::<RootedTraceableBox<Argon2Params>>(cx, value, can_gc)?
3976 .into(),
3977 ),
3978 };
3979
3980 Ok(normalized_algorithm)
3981 }
3982
3983 fn name(&self) -> &str {
3985 match self {
3986 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
3987 NormalizedAlgorithm::RsaHashedKeyGenParams(algo) => &algo.name,
3988 NormalizedAlgorithm::RsaHashedImportParams(algo) => &algo.name,
3989 NormalizedAlgorithm::RsaPssParams(algo) => &algo.name,
3990 NormalizedAlgorithm::RsaOaepParams(algo) => &algo.name,
3991 NormalizedAlgorithm::EcdsaParams(algo) => &algo.name,
3992 NormalizedAlgorithm::EcKeyGenParams(algo) => &algo.name,
3993 NormalizedAlgorithm::EcKeyImportParams(algo) => &algo.name,
3994 NormalizedAlgorithm::EcdhKeyDeriveParams(algo) => &algo.name,
3995 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
3996 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
3997 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
3998 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
3999 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
4000 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
4001 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
4002 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
4003 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
4004 NormalizedAlgorithm::ContextParams(algo) => &algo.name,
4005 NormalizedAlgorithm::AeadParams(algo) => &algo.name,
4006 NormalizedAlgorithm::CShakeParams(algo) => &algo.name,
4007 NormalizedAlgorithm::Argon2Params(algo) => &algo.name,
4008 }
4009 }
4010
4011 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4012 match (self.name(), self) {
4013 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaOaepParams(algo)) => {
4014 rsa_oaep_operation::encrypt(algo, key, plaintext)
4015 },
4016 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
4017 aes_ctr_operation::encrypt(algo, key, plaintext)
4018 },
4019 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
4020 aes_cbc_operation::encrypt(algo, key, plaintext)
4021 },
4022 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
4023 aes_gcm_operation::encrypt(algo, key, plaintext)
4024 },
4025 (ALG_AES_OCB, NormalizedAlgorithm::AeadParams(algo)) => {
4026 aes_ocb_operation::encrypt(algo, key, plaintext)
4027 },
4028 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
4029 chacha20_poly1305_operation::encrypt(algo, key, plaintext)
4030 },
4031 _ => Err(Error::NotSupported(None)),
4032 }
4033 }
4034
4035 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4036 match (self.name(), self) {
4037 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaOaepParams(algo)) => {
4038 rsa_oaep_operation::decrypt(algo, key, ciphertext)
4039 },
4040 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
4041 aes_ctr_operation::decrypt(algo, key, ciphertext)
4042 },
4043 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
4044 aes_cbc_operation::decrypt(algo, key, ciphertext)
4045 },
4046 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
4047 aes_gcm_operation::decrypt(algo, key, ciphertext)
4048 },
4049 (ALG_AES_OCB, NormalizedAlgorithm::AeadParams(algo)) => {
4050 aes_ocb_operation::decrypt(algo, key, ciphertext)
4051 },
4052 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
4053 chacha20_poly1305_operation::decrypt(algo, key, ciphertext)
4054 },
4055 _ => Err(Error::NotSupported(None)),
4056 }
4057 }
4058
4059 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
4060 match (self.name(), self) {
4061 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::Algorithm(_algo)) => {
4062 rsassa_pkcs1_v1_5_operation::sign(key, message)
4063 },
4064 (ALG_RSA_PSS, NormalizedAlgorithm::RsaPssParams(algo)) => {
4065 rsa_pss_operation::sign(algo, key, message)
4066 },
4067 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
4068 ecdsa_operation::sign(algo, key, message)
4069 },
4070 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4071 ed25519_operation::sign(key, message)
4072 },
4073 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => hmac_operation::sign(key, message),
4074 (
4075 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4076 NormalizedAlgorithm::ContextParams(algo),
4077 ) => ml_dsa_operation::sign(algo, key, message),
4078 _ => Err(Error::NotSupported(None)),
4079 }
4080 }
4081
4082 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4083 match (self.name(), self) {
4084 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::Algorithm(_algo)) => {
4085 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4086 },
4087 (ALG_RSA_PSS, NormalizedAlgorithm::RsaPssParams(algo)) => {
4088 rsa_pss_operation::verify(algo, key, message, signature)
4089 },
4090 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
4091 ecdsa_operation::verify(algo, key, message, signature)
4092 },
4093 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4094 ed25519_operation::verify(key, message, signature)
4095 },
4096 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => {
4097 hmac_operation::verify(key, message, signature)
4098 },
4099 (
4100 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4101 NormalizedAlgorithm::ContextParams(algo),
4102 ) => ml_dsa_operation::verify(algo, key, message, signature),
4103 _ => Err(Error::NotSupported(None)),
4104 }
4105 }
4106
4107 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
4108 match (self.name(), self) {
4109 (ALG_SHA1, NormalizedAlgorithm::Algorithm(algo)) => {
4110 sha_operation::digest(algo, message)
4111 },
4112 (ALG_SHA256, NormalizedAlgorithm::Algorithm(algo)) => {
4113 sha_operation::digest(algo, message)
4114 },
4115 (ALG_SHA384, NormalizedAlgorithm::Algorithm(algo)) => {
4116 sha_operation::digest(algo, message)
4117 },
4118 (ALG_SHA512, NormalizedAlgorithm::Algorithm(algo)) => {
4119 sha_operation::digest(algo, message)
4120 },
4121 (ALG_SHA3_256, NormalizedAlgorithm::Algorithm(algo)) => {
4122 sha3_operation::digest(algo, message)
4123 },
4124 (ALG_SHA3_384, NormalizedAlgorithm::Algorithm(algo)) => {
4125 sha3_operation::digest(algo, message)
4126 },
4127 (ALG_SHA3_512, NormalizedAlgorithm::Algorithm(algo)) => {
4128 sha3_operation::digest(algo, message)
4129 },
4130 (ALG_CSHAKE_128, NormalizedAlgorithm::CShakeParams(algo)) => {
4131 cshake_operation::digest(algo, message)
4132 },
4133 (ALG_CSHAKE_256, NormalizedAlgorithm::CShakeParams(algo)) => {
4134 cshake_operation::digest(algo, message)
4135 },
4136 _ => Err(Error::NotSupported(None)),
4137 }
4138 }
4139
4140 fn generate_key(
4141 &self,
4142 global: &GlobalScope,
4143 extractable: bool,
4144 usages: Vec<KeyUsage>,
4145 can_gc: CanGc,
4146 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
4147 match (self.name(), self) {
4148 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4149 rsassa_pkcs1_v1_5_operation::generate_key(global, algo, extractable, usages, can_gc)
4150 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4151 },
4152 (ALG_RSA_PSS, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4153 rsa_pss_operation::generate_key(global, algo, extractable, usages, can_gc)
4154 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4155 },
4156 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4157 rsa_oaep_operation::generate_key(global, algo, extractable, usages, can_gc)
4158 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4159 },
4160 (ALG_ECDSA, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
4161 ecdsa_operation::generate_key(global, algo, extractable, usages, can_gc)
4162 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4163 },
4164 (ALG_ECDH, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
4165 ecdh_operation::generate_key(global, algo, extractable, usages, can_gc)
4166 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4167 },
4168 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4169 ed25519_operation::generate_key(global, extractable, usages, can_gc)
4170 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4171 },
4172 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4173 x25519_operation::generate_key(global, extractable, usages, can_gc)
4174 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4175 },
4176 (ALG_AES_CTR, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4177 aes_ctr_operation::generate_key(global, algo, extractable, usages, can_gc)
4178 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4179 },
4180 (ALG_AES_CBC, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4181 aes_cbc_operation::generate_key(global, algo, extractable, usages, can_gc)
4182 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4183 },
4184 (ALG_AES_GCM, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4185 aes_gcm_operation::generate_key(global, algo, extractable, usages, can_gc)
4186 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4187 },
4188 (ALG_AES_KW, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4189 aes_kw_operation::generate_key(global, algo, extractable, usages, can_gc)
4190 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4191 },
4192 (ALG_HMAC, NormalizedAlgorithm::HmacKeyGenParams(algo)) => {
4193 hmac_operation::generate_key(global, algo, extractable, usages, can_gc)
4194 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4195 },
4196 (
4197 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4198 NormalizedAlgorithm::Algorithm(algo),
4199 ) => ml_kem_operation::generate_key(global, algo, extractable, usages, can_gc)
4200 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
4201 (
4202 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4203 NormalizedAlgorithm::Algorithm(algo),
4204 ) => ml_dsa_operation::generate_key(global, algo, extractable, usages, can_gc)
4205 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
4206 (ALG_AES_OCB, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4207 aes_ocb_operation::generate_key(global, algo, extractable, usages, can_gc)
4208 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4209 },
4210 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4211 chacha20_poly1305_operation::generate_key(global, extractable, usages, can_gc)
4212 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4213 },
4214 _ => Err(Error::NotSupported(None)),
4215 }
4216 }
4217
4218 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
4219 match (self.name(), self) {
4220 (ALG_ECDH, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
4221 ecdh_operation::derive_bits(algo, key, length)
4222 },
4223 (ALG_X25519, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
4224 x25519_operation::derive_bits(algo, key, length)
4225 },
4226 (ALG_HKDF, NormalizedAlgorithm::HkdfParams(algo)) => {
4227 hkdf_operation::derive_bits(algo, key, length)
4228 },
4229 (ALG_PBKDF2, NormalizedAlgorithm::Pbkdf2Params(algo)) => {
4230 pbkdf2_operation::derive_bits(algo, key, length)
4231 },
4232 (ALG_ARGON2D, NormalizedAlgorithm::Argon2Params(algo)) => {
4233 argon2_operation::derive_bits(algo, key, length)
4234 },
4235 (ALG_ARGON2I, NormalizedAlgorithm::Argon2Params(algo)) => {
4236 argon2_operation::derive_bits(algo, key, length)
4237 },
4238 (ALG_ARGON2ID, NormalizedAlgorithm::Argon2Params(algo)) => {
4239 argon2_operation::derive_bits(algo, key, length)
4240 },
4241 _ => Err(Error::NotSupported(None)),
4242 }
4243 }
4244
4245 fn import_key(
4246 &self,
4247 global: &GlobalScope,
4248 format: KeyFormat,
4249 key_data: &[u8],
4250 extractable: bool,
4251 usages: Vec<KeyUsage>,
4252 can_gc: CanGc,
4253 ) -> Result<DomRoot<CryptoKey>, Error> {
4254 match (self.name(), self) {
4255 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4256 rsassa_pkcs1_v1_5_operation::import_key(
4257 global,
4258 algo,
4259 format,
4260 key_data,
4261 extractable,
4262 usages,
4263 can_gc,
4264 )
4265 },
4266 (ALG_RSA_PSS, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4267 rsa_pss_operation::import_key(
4268 global,
4269 algo,
4270 format,
4271 key_data,
4272 extractable,
4273 usages,
4274 can_gc,
4275 )
4276 },
4277 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4278 rsa_oaep_operation::import_key(
4279 global,
4280 algo,
4281 format,
4282 key_data,
4283 extractable,
4284 usages,
4285 can_gc,
4286 )
4287 },
4288 (ALG_ECDSA, NormalizedAlgorithm::EcKeyImportParams(algo)) => {
4289 ecdsa_operation::import_key(
4290 global,
4291 algo,
4292 format,
4293 key_data,
4294 extractable,
4295 usages,
4296 can_gc,
4297 )
4298 },
4299 (ALG_ECDH, NormalizedAlgorithm::EcKeyImportParams(algo)) => ecdh_operation::import_key(
4300 global,
4301 algo,
4302 format,
4303 key_data,
4304 extractable,
4305 usages,
4306 can_gc,
4307 ),
4308 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4309 ed25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4310 },
4311 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4312 x25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4313 },
4314 (ALG_AES_CTR, NormalizedAlgorithm::Algorithm(_algo)) => {
4315 aes_ctr_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4316 },
4317 (ALG_AES_CBC, NormalizedAlgorithm::Algorithm(_algo)) => {
4318 aes_cbc_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4319 },
4320 (ALG_AES_GCM, NormalizedAlgorithm::Algorithm(_algo)) => {
4321 aes_gcm_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4322 },
4323 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4324 aes_kw_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4325 },
4326 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => hmac_operation::import_key(
4327 global,
4328 algo,
4329 format,
4330 key_data,
4331 extractable,
4332 usages,
4333 can_gc,
4334 ),
4335 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => {
4336 hkdf_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4337 },
4338 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
4339 pbkdf2_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4340 },
4341 (
4342 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4343 NormalizedAlgorithm::Algorithm(algo),
4344 ) => ml_kem_operation::import_key(
4345 global,
4346 algo,
4347 format,
4348 key_data,
4349 extractable,
4350 usages,
4351 can_gc,
4352 ),
4353 (
4354 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4355 NormalizedAlgorithm::Algorithm(algo),
4356 ) => ml_dsa_operation::import_key(
4357 global,
4358 algo,
4359 format,
4360 key_data,
4361 extractable,
4362 usages,
4363 can_gc,
4364 ),
4365 (ALG_AES_OCB, NormalizedAlgorithm::Algorithm(_algo)) => {
4366 aes_ocb_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4367 },
4368 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4369 chacha20_poly1305_operation::import_key(
4370 global,
4371 format,
4372 key_data,
4373 extractable,
4374 usages,
4375 can_gc,
4376 )
4377 },
4378 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4379 global,
4380 algo,
4381 format,
4382 key_data,
4383 extractable,
4384 usages,
4385 can_gc,
4386 ),
4387 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4388 global,
4389 algo,
4390 format,
4391 key_data,
4392 extractable,
4393 usages,
4394 can_gc,
4395 ),
4396 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4397 global,
4398 algo,
4399 format,
4400 key_data,
4401 extractable,
4402 usages,
4403 can_gc,
4404 ),
4405 _ => Err(Error::NotSupported(None)),
4406 }
4407 }
4408
4409 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4410 match (self.name(), self) {
4411 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4412 aes_kw_operation::wrap_key(key, plaintext)
4413 },
4414 _ => Err(Error::NotSupported(None)),
4415 }
4416 }
4417
4418 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4419 match (self.name(), self) {
4420 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4421 aes_kw_operation::unwrap_key(key, ciphertext)
4422 },
4423 _ => Err(Error::NotSupported(None)),
4424 }
4425 }
4426
4427 fn get_key_length(&self) -> Result<Option<u32>, Error> {
4428 match (self.name(), self) {
4429 (ALG_AES_CTR, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4430 aes_ctr_operation::get_key_length(algo)
4431 },
4432 (ALG_AES_CBC, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4433 aes_cbc_operation::get_key_length(algo)
4434 },
4435 (ALG_AES_GCM, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4436 aes_gcm_operation::get_key_length(algo)
4437 },
4438 (ALG_AES_KW, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4439 aes_kw_operation::get_key_length(algo)
4440 },
4441 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => {
4442 hmac_operation::get_key_length(algo)
4443 },
4444 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => hkdf_operation::get_key_length(),
4445 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
4446 pbkdf2_operation::get_key_length()
4447 },
4448 (ALG_AES_OCB, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4449 aes_ocb_operation::get_key_length(algo)
4450 },
4451 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4452 chacha20_poly1305_operation::get_key_length()
4453 },
4454 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(_algo)) => {
4455 argon2_operation::get_key_length()
4456 },
4457 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(_algo)) => {
4458 argon2_operation::get_key_length()
4459 },
4460 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(_algo)) => {
4461 argon2_operation::get_key_length()
4462 },
4463 _ => Err(Error::NotSupported(None)),
4464 }
4465 }
4466
4467 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
4468 match (self.name(), self) {
4469 (
4470 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4471 NormalizedAlgorithm::Algorithm(algo),
4472 ) => ml_kem_operation::encapsulate(algo, key),
4473 _ => Err(Error::NotSupported(None)),
4474 }
4475 }
4476
4477 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4478 match (self.name(), self) {
4479 (
4480 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4481 NormalizedAlgorithm::Algorithm(algo),
4482 ) => ml_kem_operation::decapsulate(algo, key, ciphertext),
4483 _ => Err(Error::NotSupported(None)),
4484 }
4485 }
4486}
4487
4488fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
4495 match key.algorithm().name() {
4496 ALG_RSASSA_PKCS1_V1_5 => rsassa_pkcs1_v1_5_operation::export_key(format, key),
4497 ALG_RSA_PSS => rsa_pss_operation::export_key(format, key),
4498 ALG_RSA_OAEP => rsa_oaep_operation::export_key(format, key),
4499 ALG_ECDSA => ecdsa_operation::export_key(format, key),
4500 ALG_ECDH => ecdh_operation::export_key(format, key),
4501 ALG_ED25519 => ed25519_operation::export_key(format, key),
4502 ALG_X25519 => x25519_operation::export_key(format, key),
4503 ALG_AES_CTR => aes_ctr_operation::export_key(format, key),
4504 ALG_AES_CBC => aes_cbc_operation::export_key(format, key),
4505 ALG_AES_GCM => aes_gcm_operation::export_key(format, key),
4506 ALG_AES_KW => aes_kw_operation::export_key(format, key),
4507 ALG_HMAC => hmac_operation::export_key(format, key),
4508 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024 => {
4509 ml_kem_operation::export_key(format, key)
4510 },
4511 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87 => ml_dsa_operation::export_key(format, key),
4512 ALG_AES_OCB => aes_ocb_operation::export_key(format, key),
4513 ALG_CHACHA20_POLY1305 => chacha20_poly1305_operation::export_key(format, key),
4514 _ => Err(Error::NotSupported(None)),
4515 }
4516}