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("The keyData type does not match the format".to_string()),
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("The keyData type does not match the format".to_string()),
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 From<NormalizedAlgorithm> for SubtleKeyAlgorithm {
2216 fn from(value: NormalizedAlgorithm) -> Self {
2217 SubtleKeyAlgorithm {
2218 name: value.name().to_string(),
2219 }
2220 }
2221}
2222
2223impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2224 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2225 let dictionary = KeyAlgorithm {
2226 name: self.name.clone().into(),
2227 };
2228 dictionary.safe_to_jsval(cx, rval, can_gc);
2229 }
2230}
2231
2232#[derive(Clone, MallocSizeOf)]
2234pub(crate) struct SubtleRsaHashedKeyGenParams {
2235 name: String,
2237
2238 modulus_length: u32,
2240
2241 public_exponent: Vec<u8>,
2243
2244 hash: Box<NormalizedAlgorithm>,
2246}
2247
2248impl TryFrom<RootedTraceableBox<RsaHashedKeyGenParams>> for SubtleRsaHashedKeyGenParams {
2249 type Error = Error;
2250
2251 fn try_from(value: RootedTraceableBox<RsaHashedKeyGenParams>) -> Result<Self, Self::Error> {
2252 let cx = GlobalScope::get_cx();
2253 Ok(SubtleRsaHashedKeyGenParams {
2254 name: value.parent.parent.name.to_string(),
2255 modulus_length: value.parent.modulusLength,
2256 public_exponent: value.parent.publicExponent.to_vec(),
2257 hash: Box::new(normalize_algorithm(
2258 cx,
2259 Operation::Digest,
2260 &value.hash,
2261 CanGc::note(),
2262 )?),
2263 })
2264 }
2265}
2266
2267#[derive(Clone, MallocSizeOf)]
2269pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2270 name: String,
2272
2273 modulus_length: u32,
2275
2276 public_exponent: Vec<u8>,
2278
2279 hash: Box<NormalizedAlgorithm>,
2281}
2282
2283impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2284 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2285 rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>());
2286 let public_exponent =
2287 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut(), can_gc)
2288 .expect("Fail to convert publicExponent to Uint8Array");
2289 let key_algorithm = KeyAlgorithm {
2290 name: self.name.clone().into(),
2291 };
2292 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2293 parent: key_algorithm,
2294 modulusLength: self.modulus_length,
2295 publicExponent: public_exponent,
2296 });
2297 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
2298 parent: rsa_key_algorithm,
2299 hash: KeyAlgorithm {
2300 name: self.hash.name().into(),
2301 },
2302 });
2303 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval, can_gc);
2304 }
2305}
2306
2307#[derive(Clone, MallocSizeOf)]
2309struct SubtleRsaHashedImportParams {
2310 name: String,
2312
2313 hash: Box<NormalizedAlgorithm>,
2315}
2316
2317impl TryFrom<RootedTraceableBox<RsaHashedImportParams>> for SubtleRsaHashedImportParams {
2318 type Error = Error;
2319
2320 fn try_from(value: RootedTraceableBox<RsaHashedImportParams>) -> Result<Self, Self::Error> {
2321 let cx = GlobalScope::get_cx();
2322 Ok(SubtleRsaHashedImportParams {
2323 name: value.parent.name.to_string(),
2324 hash: Box::new(normalize_algorithm(
2325 cx,
2326 Operation::Digest,
2327 &value.hash,
2328 CanGc::note(),
2329 )?),
2330 })
2331 }
2332}
2333
2334#[derive(Clone, Debug, MallocSizeOf)]
2336struct SubtleRsaPssParams {
2337 name: String,
2339
2340 salt_length: u32,
2342}
2343
2344impl From<RsaPssParams> for SubtleRsaPssParams {
2345 fn from(value: RsaPssParams) -> Self {
2346 SubtleRsaPssParams {
2347 name: value.parent.name.to_string(),
2348 salt_length: value.saltLength,
2349 }
2350 }
2351}
2352
2353#[derive(Clone, Debug, MallocSizeOf)]
2355struct SubtleRsaOaepParams {
2356 name: String,
2358 label: Option<Vec<u8>>,
2360}
2361
2362impl From<RootedTraceableBox<RsaOaepParams>> for SubtleRsaOaepParams {
2363 fn from(value: RootedTraceableBox<RsaOaepParams>) -> Self {
2364 let label = value.label.as_ref().map(|label| match label {
2365 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2366 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2367 });
2368 SubtleRsaOaepParams {
2369 name: value.parent.name.to_string(),
2370 label,
2371 }
2372 }
2373}
2374
2375#[derive(Clone, MallocSizeOf)]
2377struct SubtleEcdsaParams {
2378 name: String,
2380
2381 hash: Box<NormalizedAlgorithm>,
2383}
2384
2385impl TryFrom<RootedTraceableBox<EcdsaParams>> for SubtleEcdsaParams {
2386 type Error = Error;
2387
2388 fn try_from(value: RootedTraceableBox<EcdsaParams>) -> Result<Self, Error> {
2389 let cx = GlobalScope::get_cx();
2390 let hash = normalize_algorithm(cx, Operation::Digest, &value.hash, CanGc::note())?;
2391 Ok(SubtleEcdsaParams {
2392 name: value.parent.name.to_string(),
2393 hash: Box::new(hash),
2394 })
2395 }
2396}
2397
2398#[derive(Clone, Debug, MallocSizeOf)]
2400struct SubtleEcKeyGenParams {
2401 name: String,
2403
2404 named_curve: String,
2406}
2407
2408impl From<EcKeyGenParams> for SubtleEcKeyGenParams {
2409 fn from(value: EcKeyGenParams) -> Self {
2410 SubtleEcKeyGenParams {
2411 name: value.parent.name.to_string(),
2412 named_curve: value.namedCurve.to_string(),
2413 }
2414 }
2415}
2416
2417#[derive(Clone, Debug, MallocSizeOf)]
2419pub(crate) struct SubtleEcKeyAlgorithm {
2420 name: String,
2422
2423 named_curve: String,
2425}
2426
2427impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
2428 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2429 let parent = KeyAlgorithm {
2430 name: self.name.clone().into(),
2431 };
2432 let dictionary = EcKeyAlgorithm {
2433 parent,
2434 namedCurve: self.named_curve.clone().into(),
2435 };
2436 dictionary.safe_to_jsval(cx, rval, can_gc);
2437 }
2438}
2439
2440#[derive(Clone, Debug, MallocSizeOf)]
2442struct SubtleEcKeyImportParams {
2443 name: String,
2445
2446 named_curve: String,
2448}
2449
2450impl From<EcKeyImportParams> for SubtleEcKeyImportParams {
2451 fn from(value: EcKeyImportParams) -> Self {
2452 SubtleEcKeyImportParams {
2453 name: value.parent.name.to_string(),
2454 named_curve: value.namedCurve.to_string(),
2455 }
2456 }
2457}
2458
2459#[derive(Clone, MallocSizeOf)]
2461struct SubtleEcdhKeyDeriveParams {
2462 name: String,
2464
2465 public: Trusted<CryptoKey>,
2467}
2468
2469impl From<EcdhKeyDeriveParams> for SubtleEcdhKeyDeriveParams {
2470 fn from(value: EcdhKeyDeriveParams) -> Self {
2471 SubtleEcdhKeyDeriveParams {
2472 name: value.parent.name.to_string(),
2473 public: Trusted::new(&value.public),
2474 }
2475 }
2476}
2477
2478#[derive(Clone, Debug, MallocSizeOf)]
2480struct SubtleAesCtrParams {
2481 name: String,
2483
2484 counter: Vec<u8>,
2486
2487 length: u8,
2489}
2490
2491impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
2492 fn from(params: RootedTraceableBox<AesCtrParams>) -> Self {
2493 let counter = match ¶ms.counter {
2494 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2495 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2496 };
2497 SubtleAesCtrParams {
2498 name: params.parent.name.to_string(),
2499 counter,
2500 length: params.length,
2501 }
2502 }
2503}
2504
2505#[derive(Clone, Debug, MallocSizeOf)]
2507pub(crate) struct SubtleAesKeyAlgorithm {
2508 name: String,
2510
2511 length: u16,
2513}
2514
2515impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
2516 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2517 let parent = KeyAlgorithm {
2518 name: self.name.clone().into(),
2519 };
2520 let dictionary = AesKeyAlgorithm {
2521 parent,
2522 length: self.length,
2523 };
2524 dictionary.safe_to_jsval(cx, rval, can_gc);
2525 }
2526}
2527
2528#[derive(Clone, Debug, MallocSizeOf)]
2530struct SubtleAesKeyGenParams {
2531 name: String,
2533
2534 length: u16,
2536}
2537
2538impl From<AesKeyGenParams> for SubtleAesKeyGenParams {
2539 fn from(params: AesKeyGenParams) -> Self {
2540 SubtleAesKeyGenParams {
2541 name: params.parent.name.to_string(),
2542 length: params.length,
2543 }
2544 }
2545}
2546
2547#[derive(Clone, Debug, MallocSizeOf)]
2549struct SubtleAesDerivedKeyParams {
2550 name: String,
2552
2553 length: u16,
2555}
2556
2557impl From<AesDerivedKeyParams> for SubtleAesDerivedKeyParams {
2558 fn from(params: AesDerivedKeyParams) -> Self {
2559 SubtleAesDerivedKeyParams {
2560 name: params.parent.name.to_string(),
2561 length: params.length,
2562 }
2563 }
2564}
2565
2566#[derive(Clone, Debug, MallocSizeOf)]
2568struct SubtleAesCbcParams {
2569 name: String,
2571
2572 iv: Vec<u8>,
2574}
2575
2576impl From<RootedTraceableBox<AesCbcParams>> for SubtleAesCbcParams {
2577 fn from(params: RootedTraceableBox<AesCbcParams>) -> Self {
2578 let iv = match ¶ms.iv {
2579 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2580 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2581 };
2582 SubtleAesCbcParams {
2583 name: params.parent.name.to_string(),
2584 iv,
2585 }
2586 }
2587}
2588
2589#[derive(Clone, Debug, MallocSizeOf)]
2591struct SubtleAesGcmParams {
2592 name: String,
2594
2595 iv: Vec<u8>,
2597
2598 additional_data: Option<Vec<u8>>,
2600
2601 tag_length: Option<u8>,
2603}
2604
2605impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
2606 fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
2607 let iv = match ¶ms.iv {
2608 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2609 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2610 };
2611 let additional_data = params.additionalData.as_ref().map(|data| match data {
2612 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2613 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2614 });
2615
2616 SubtleAesGcmParams {
2617 name: params.parent.name.to_string(),
2618 iv,
2619 additional_data,
2620 tag_length: params.tagLength,
2621 }
2622 }
2623}
2624
2625#[derive(Clone, MallocSizeOf)]
2627struct SubtleHmacImportParams {
2628 name: String,
2630
2631 hash: Box<NormalizedAlgorithm>,
2633
2634 length: Option<u32>,
2636}
2637
2638impl TryFrom<RootedTraceableBox<HmacImportParams>> for SubtleHmacImportParams {
2639 type Error = Error;
2640
2641 fn try_from(params: RootedTraceableBox<HmacImportParams>) -> Result<Self, Error> {
2642 let cx = GlobalScope::get_cx();
2643 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2644 Ok(SubtleHmacImportParams {
2645 name: params.parent.name.to_string(),
2646 hash: Box::new(hash),
2647 length: params.length,
2648 })
2649 }
2650}
2651
2652#[derive(Clone, Debug, MallocSizeOf)]
2654pub(crate) struct SubtleHmacKeyAlgorithm {
2655 name: String,
2657
2658 hash: SubtleKeyAlgorithm,
2660
2661 length: u32,
2663}
2664
2665impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
2666 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2667 let parent = KeyAlgorithm {
2668 name: self.name.clone().into(),
2669 };
2670 let hash = KeyAlgorithm {
2671 name: self.hash.name.clone().into(),
2672 };
2673 let dictionary = HmacKeyAlgorithm {
2674 parent,
2675 hash,
2676 length: self.length,
2677 };
2678 dictionary.safe_to_jsval(cx, rval, can_gc);
2679 }
2680}
2681
2682#[derive(Clone, MallocSizeOf)]
2684struct SubtleHmacKeyGenParams {
2685 name: String,
2687
2688 hash: Box<NormalizedAlgorithm>,
2690
2691 length: Option<u32>,
2693}
2694
2695impl TryFrom<RootedTraceableBox<HmacKeyGenParams>> for SubtleHmacKeyGenParams {
2696 type Error = Error;
2697
2698 fn try_from(params: RootedTraceableBox<HmacKeyGenParams>) -> Result<Self, Error> {
2699 let cx = GlobalScope::get_cx();
2700 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2701 Ok(SubtleHmacKeyGenParams {
2702 name: params.parent.name.to_string(),
2703 hash: Box::new(hash),
2704 length: params.length,
2705 })
2706 }
2707}
2708
2709#[derive(Clone, MallocSizeOf)]
2711pub(crate) struct SubtleHkdfParams {
2712 name: String,
2714
2715 hash: Box<NormalizedAlgorithm>,
2717
2718 salt: Vec<u8>,
2720
2721 info: Vec<u8>,
2723}
2724
2725impl TryFrom<RootedTraceableBox<HkdfParams>> for SubtleHkdfParams {
2726 type Error = Error;
2727
2728 fn try_from(params: RootedTraceableBox<HkdfParams>) -> Result<Self, Error> {
2729 let cx = GlobalScope::get_cx();
2730 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2731 let salt = match ¶ms.salt {
2732 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2733 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2734 };
2735 let info = match ¶ms.info {
2736 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2737 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2738 };
2739 Ok(SubtleHkdfParams {
2740 name: params.parent.name.to_string(),
2741 hash: Box::new(hash),
2742 salt,
2743 info,
2744 })
2745 }
2746}
2747
2748#[derive(Clone, MallocSizeOf)]
2750pub(crate) struct SubtlePbkdf2Params {
2751 name: String,
2753
2754 salt: Vec<u8>,
2756
2757 iterations: u32,
2759
2760 hash: Box<NormalizedAlgorithm>,
2762}
2763
2764impl TryFrom<RootedTraceableBox<Pbkdf2Params>> for SubtlePbkdf2Params {
2765 type Error = Error;
2766
2767 fn try_from(params: RootedTraceableBox<Pbkdf2Params>) -> Result<Self, Error> {
2768 let cx = GlobalScope::get_cx();
2769 let salt = match ¶ms.salt {
2770 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2771 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2772 };
2773 let hash = normalize_algorithm(cx, Operation::Digest, ¶ms.hash, CanGc::note())?;
2774 Ok(SubtlePbkdf2Params {
2775 name: params.parent.name.to_string(),
2776 salt,
2777 iterations: params.iterations,
2778 hash: Box::new(hash),
2779 })
2780 }
2781}
2782
2783#[derive(Clone, Debug, MallocSizeOf)]
2785struct SubtleContextParams {
2786 name: String,
2788
2789 context: Option<Vec<u8>>,
2791}
2792
2793impl From<RootedTraceableBox<ContextParams>> for SubtleContextParams {
2794 fn from(value: RootedTraceableBox<ContextParams>) -> Self {
2795 let context = value.context.as_ref().map(|context| match context {
2796 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2797 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2798 });
2799 SubtleContextParams {
2800 name: value.parent.name.to_string(),
2801 context,
2802 }
2803 }
2804}
2805
2806#[derive(Clone, Debug, MallocSizeOf)]
2808struct SubtleAeadParams {
2809 name: String,
2811
2812 iv: Vec<u8>,
2814
2815 additional_data: Option<Vec<u8>>,
2817
2818 tag_length: Option<u8>,
2820}
2821
2822impl From<RootedTraceableBox<AeadParams>> for SubtleAeadParams {
2823 fn from(value: RootedTraceableBox<AeadParams>) -> Self {
2824 let iv = match &value.iv {
2825 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2826 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2827 };
2828 let additional_data = value.additionalData.as_ref().map(|data| match data {
2829 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2830 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2831 });
2832
2833 SubtleAeadParams {
2834 name: value.parent.name.to_string(),
2835 iv,
2836 additional_data,
2837 tag_length: value.tagLength,
2838 }
2839 }
2840}
2841
2842#[derive(Clone, Debug, MallocSizeOf)]
2844struct SubtleCShakeParams {
2845 name: String,
2847
2848 length: u32,
2850
2851 function_name: Option<Vec<u8>>,
2853
2854 customization: Option<Vec<u8>>,
2856}
2857
2858impl From<RootedTraceableBox<CShakeParams>> for SubtleCShakeParams {
2859 fn from(value: RootedTraceableBox<CShakeParams>) -> Self {
2860 let function_name = value
2861 .functionName
2862 .as_ref()
2863 .map(|function_name| match function_name {
2864 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2865 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2866 });
2867 let customization = value
2868 .customization
2869 .as_ref()
2870 .map(|customization| match customization {
2871 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2872 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2873 });
2874 SubtleCShakeParams {
2875 name: value.parent.name.to_string(),
2876 length: value.length,
2877 function_name,
2878 customization,
2879 }
2880 }
2881}
2882
2883#[derive(Clone, Debug, MallocSizeOf)]
2885struct SubtleArgon2Params {
2886 name: String,
2888
2889 nonce: Vec<u8>,
2891
2892 parallelism: u32,
2894
2895 memory: u32,
2897
2898 passes: u32,
2900
2901 version: Option<u8>,
2903
2904 secret_value: Option<Vec<u8>>,
2906
2907 associated_data: Option<Vec<u8>>,
2909}
2910
2911impl From<RootedTraceableBox<Argon2Params>> for SubtleArgon2Params {
2912 fn from(value: RootedTraceableBox<Argon2Params>) -> Self {
2913 let nonce = match &value.nonce {
2914 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2915 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2916 };
2917 let secret_value = value
2918 .secretValue
2919 .as_ref()
2920 .map(|secret_value| match secret_value {
2921 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2922 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2923 });
2924 let associated_data =
2925 value
2926 .associatedData
2927 .as_ref()
2928 .map(|associated_data| match associated_data {
2929 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2930 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2931 });
2932 SubtleArgon2Params {
2933 name: value.parent.name.to_string(),
2934 nonce,
2935 parallelism: value.parallelism,
2936 memory: value.memory,
2937 passes: value.passes,
2938 version: value.version,
2939 secret_value,
2940 associated_data,
2941 }
2942 }
2943}
2944
2945struct SubtleEncapsulatedKey {
2947 shared_key: Option<Trusted<CryptoKey>>,
2949
2950 ciphertext: Option<Vec<u8>>,
2952}
2953
2954impl SafeToJSValConvertible for SubtleEncapsulatedKey {
2955 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2956 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
2957 let ciphertext = self.ciphertext.as_ref().map(|data| {
2958 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
2959 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
2960 .expect("Failed to convert ciphertext to ArrayBufferU8")
2961 });
2962 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
2963 sharedKey: shared_key,
2964 ciphertext,
2965 });
2966 encapsulated_key.safe_to_jsval(cx, rval, can_gc);
2967 }
2968}
2969
2970struct SubtleEncapsulatedBits {
2972 shared_key: Option<Vec<u8>>,
2974
2975 ciphertext: Option<Vec<u8>>,
2977}
2978
2979impl SafeToJSValConvertible for SubtleEncapsulatedBits {
2980 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2981 let shared_key = self.shared_key.as_ref().map(|data| {
2982 rooted!(in(*cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
2983 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut(), can_gc)
2984 .expect("Failed to convert shared key to ArrayBufferU8")
2985 });
2986 let ciphertext = self.ciphertext.as_ref().map(|data| {
2987 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
2988 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
2989 .expect("Failed to convert ciphertext to ArrayBufferU8")
2990 });
2991 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
2992 sharedKey: shared_key,
2993 ciphertext,
2994 });
2995 encapsulated_bits.safe_to_jsval(cx, rval, can_gc);
2996 }
2997}
2998
2999fn dictionary_from_jsval<T>(cx: JSContext, value: HandleValue, can_gc: CanGc) -> Fallible<T>
3001where
3002 T: SafeFromJSValConvertible<Config = ()>,
3003{
3004 let conversion = T::safe_from_jsval(cx, value, (), can_gc).map_err(|_| Error::JSFailed)?;
3005 match conversion {
3006 ConversionResult::Success(dictionary) => Ok(dictionary),
3007 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
3008 }
3009}
3010
3011enum ExportedKey {
3015 Bytes(Vec<u8>),
3016 Jwk(Box<JsonWebKey>),
3017}
3018
3019#[derive(Clone, MallocSizeOf)]
3023#[expect(clippy::enum_variant_names)]
3024pub(crate) enum KeyAlgorithmAndDerivatives {
3025 KeyAlgorithm(SubtleKeyAlgorithm),
3026 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
3027 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
3028 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
3029 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
3030}
3031
3032impl KeyAlgorithmAndDerivatives {
3033 fn name(&self) -> &str {
3034 match self {
3035 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => &algo.name,
3036 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => &algo.name,
3037 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => &algo.name,
3038 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => &algo.name,
3039 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => &algo.name,
3040 }
3041 }
3042}
3043
3044impl From<NormalizedAlgorithm> for KeyAlgorithmAndDerivatives {
3045 fn from(value: NormalizedAlgorithm) -> Self {
3046 KeyAlgorithmAndDerivatives::KeyAlgorithm(SubtleKeyAlgorithm {
3047 name: value.name().to_string(),
3048 })
3049 }
3050}
3051
3052impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
3053 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3054 match self {
3055 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
3056 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => {
3057 algo.safe_to_jsval(cx, rval, can_gc)
3058 },
3059 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
3060 algo.safe_to_jsval(cx, rval, can_gc)
3061 },
3062 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
3063 algo.safe_to_jsval(cx, rval, can_gc)
3064 },
3065 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
3066 algo.safe_to_jsval(cx, rval, can_gc)
3067 },
3068 }
3069 }
3070}
3071
3072#[derive(Clone, Copy)]
3073enum JwkStringField {
3074 X,
3075 Y,
3076 D,
3077 N,
3078 E,
3079 P,
3080 Q,
3081 DP,
3082 DQ,
3083 QI,
3084 K,
3085 Priv,
3086 Pub,
3087}
3088
3089impl Display for JwkStringField {
3090 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3091 let field_name = match self {
3092 JwkStringField::X => "x",
3093 JwkStringField::Y => "y",
3094 JwkStringField::D => "d",
3095 JwkStringField::N => "n",
3096 JwkStringField::E => "e",
3097 JwkStringField::P => "q",
3098 JwkStringField::Q => "q",
3099 JwkStringField::DP => "dp",
3100 JwkStringField::DQ => "dq",
3101 JwkStringField::QI => "qi",
3102 JwkStringField::K => "k",
3103 JwkStringField::Priv => "priv",
3104 JwkStringField::Pub => "pub",
3105 };
3106 write!(f, "{}", field_name)
3107 }
3108}
3109
3110trait JsonWebKeyExt {
3111 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
3112 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error>;
3113 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
3114 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
3115 fn set_key_ops(&mut self, usages: Vec<KeyUsage>);
3116 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
3117 fn decode_optional_string_field(&self, field: JwkStringField)
3118 -> Result<Option<Vec<u8>>, Error>;
3119 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error>;
3120 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error>;
3121}
3122
3123impl JsonWebKeyExt for JsonWebKey {
3124 #[expect(unsafe_code)]
3126 fn parse(cx: JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
3127 let json = String::from_utf8_lossy(data);
3132
3133 let json: Vec<_> = json.encode_utf16().collect();
3135
3136 rooted!(in(*cx) let mut result = UndefinedValue());
3140 unsafe {
3141 if !JS_ParseJSON(*cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
3142 return Err(Error::JSFailed);
3143 }
3144 }
3145
3146 let key = match JsonWebKey::new(cx, result.handle(), CanGc::note()) {
3148 Ok(ConversionResult::Success(key)) => key,
3149 Ok(ConversionResult::Failure(error)) => {
3150 return Err(Error::Type(error.to_string()));
3151 },
3152 Err(()) => {
3153 return Err(Error::JSFailed);
3154 },
3155 };
3156
3157 if key.kty.is_none() {
3159 return Err(Error::Data(None));
3160 }
3161
3162 Ok(key)
3164 }
3165
3166 fn stringify(&self, cx: JSContext) -> Result<DOMString, Error> {
3172 rooted!(in(*cx) let mut data = UndefinedValue());
3173 self.safe_to_jsval(cx, data.handle_mut(), CanGc::note());
3174 serialize_jsval_to_json_utf8(cx, data.handle())
3175 }
3176
3177 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
3178 let mut usages = vec![];
3179 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
3180 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
3181 }
3182 Ok(usages)
3183 }
3184
3185 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
3189 if let Some(ref key_ops) = self.key_ops {
3191 if key_ops
3194 .iter()
3195 .collect::<std::collections::HashSet<_>>()
3196 .len() <
3197 key_ops.len()
3198 {
3199 return Err(Error::Data(None));
3200 }
3201 if let Some(ref use_) = self.use_ {
3204 if key_ops.iter().any(|op| op != use_) {
3205 return Err(Error::Data(None));
3206 }
3207 }
3208
3209 let key_ops_as_usages = self.get_usages_from_key_ops()?;
3211 if !specified_usages
3212 .iter()
3213 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
3214 {
3215 return Err(Error::Data(None));
3216 }
3217 }
3218
3219 Ok(())
3220 }
3221
3222 fn set_key_ops(&mut self, usages: Vec<KeyUsage>) {
3224 self.key_ops = Some(
3225 usages
3226 .into_iter()
3227 .map(|usage| DOMString::from(usage.as_str()))
3228 .collect(),
3229 );
3230 }
3231
3232 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
3235 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
3236 match field {
3237 JwkStringField::X => self.x = Some(encoded_data),
3238 JwkStringField::Y => self.y = Some(encoded_data),
3239 JwkStringField::D => self.d = Some(encoded_data),
3240 JwkStringField::N => self.n = Some(encoded_data),
3241 JwkStringField::E => self.e = Some(encoded_data),
3242 JwkStringField::P => self.p = Some(encoded_data),
3243 JwkStringField::Q => self.q = Some(encoded_data),
3244 JwkStringField::DP => self.dp = Some(encoded_data),
3245 JwkStringField::DQ => self.dq = Some(encoded_data),
3246 JwkStringField::QI => self.qi = Some(encoded_data),
3247 JwkStringField::K => self.k = Some(encoded_data),
3248 JwkStringField::Priv => self.priv_ = Some(encoded_data),
3249 JwkStringField::Pub => self.pub_ = Some(encoded_data),
3250 }
3251 }
3252
3253 fn decode_optional_string_field(
3256 &self,
3257 field: JwkStringField,
3258 ) -> Result<Option<Vec<u8>>, Error> {
3259 let field_string = match field {
3260 JwkStringField::X => &self.x,
3261 JwkStringField::Y => &self.y,
3262 JwkStringField::D => &self.d,
3263 JwkStringField::N => &self.n,
3264 JwkStringField::E => &self.e,
3265 JwkStringField::P => &self.p,
3266 JwkStringField::Q => &self.q,
3267 JwkStringField::DP => &self.dp,
3268 JwkStringField::DQ => &self.dq,
3269 JwkStringField::QI => &self.qi,
3270 JwkStringField::K => &self.k,
3271 JwkStringField::Priv => &self.priv_,
3272 JwkStringField::Pub => &self.pub_,
3273 };
3274
3275 field_string
3276 .as_ref()
3277 .map(|field_string| Base64UrlUnpadded::decode_vec(&field_string.str()))
3278 .transpose()
3279 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
3280 }
3281
3282 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error> {
3285 self.decode_optional_string_field(field)?
3286 .ok_or(Error::Data(Some(format!(
3287 "The {} field is not present in jwk",
3288 field
3289 ))))
3290 }
3291
3292 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error> {
3301 if self.oth.is_some() &&
3302 (self.p.is_none() ||
3303 self.q.is_none() ||
3304 self.dp.is_none() ||
3305 self.dq.is_none() ||
3306 self.qi.is_none())
3307 {
3308 return Err(Error::Data(Some(
3309 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
3310 )));
3311 }
3312
3313 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
3314 let r = Base64UrlUnpadded::decode_vec(
3315 &rsa_other_prime_info
3316 .r
3317 .as_ref()
3318 .ok_or(Error::Data(Some(
3319 "The r field is not present in one of the entry of oth field in jwk"
3320 .to_string(),
3321 )))?
3322 .str(),
3323 )
3324 .map_err(|_| {
3325 Error::Data(Some(
3326 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
3327 ))
3328 })?;
3329 primes.push(r);
3330
3331 let _d = Base64UrlUnpadded::decode_vec(
3332 &rsa_other_prime_info
3333 .d
3334 .as_ref()
3335 .ok_or(Error::Data(Some(
3336 "The d 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 d field in one of the entry of oth field in jwk".to_string(),
3344 ))
3345 })?;
3346
3347 let _t = Base64UrlUnpadded::decode_vec(
3348 &rsa_other_prime_info
3349 .t
3350 .as_ref()
3351 .ok_or(Error::Data(Some(
3352 "The t field is not present in one of the entry of oth field in jwk"
3353 .to_string(),
3354 )))?
3355 .str(),
3356 )
3357 .map_err(|_| {
3358 Error::Data(Some(
3359 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
3360 ))
3361 })?;
3362 }
3363
3364 Ok(())
3365 }
3366}
3367
3368enum ShaAlgorithm {
3370 Sha1,
3371 Sha256,
3372 Sha384,
3373 Sha512,
3374}
3375
3376impl ShaAlgorithm {
3377 fn as_str(&self) -> &'static str {
3378 match self {
3379 ShaAlgorithm::Sha1 => ALG_SHA1,
3380 ShaAlgorithm::Sha256 => ALG_SHA256,
3381 ShaAlgorithm::Sha384 => ALG_SHA384,
3382 ShaAlgorithm::Sha512 => ALG_SHA512,
3383 }
3384 }
3385}
3386
3387enum MlKemAlgorithm {
3389 MlKem512,
3390 MlKem768,
3391 MlKem1024,
3392}
3393
3394impl MlKemAlgorithm {
3395 fn as_str(&self) -> &'static str {
3396 match self {
3397 MlKemAlgorithm::MlKem512 => ALG_ML_KEM_512,
3398 MlKemAlgorithm::MlKem768 => ALG_ML_KEM_768,
3399 MlKemAlgorithm::MlKem1024 => ALG_ML_KEM_1024,
3400 }
3401 }
3402}
3403
3404enum MlDsaAlgorithm {
3406 MlDsa44,
3407 MlDsa65,
3408 MlDsa87,
3409}
3410
3411impl MlDsaAlgorithm {
3412 fn as_str(&self) -> &'static str {
3413 match self {
3414 MlDsaAlgorithm::MlDsa44 => ALG_ML_DSA_44,
3415 MlDsaAlgorithm::MlDsa65 => ALG_ML_DSA_65,
3416 MlDsaAlgorithm::MlDsa87 => ALG_ML_DSA_87,
3417 }
3418 }
3419}
3420
3421enum Sha3Algorithm {
3423 Sha3_256,
3424 Sha3_384,
3425 Sha3_512,
3426}
3427
3428impl Sha3Algorithm {
3429 fn as_str(&self) -> &'static str {
3430 match self {
3431 Sha3Algorithm::Sha3_256 => ALG_SHA3_256,
3432 Sha3Algorithm::Sha3_384 => ALG_SHA3_384,
3433 Sha3Algorithm::Sha3_512 => ALG_SHA3_512,
3434 }
3435 }
3436}
3437
3438enum CShakeAlgorithm {
3440 CShake128,
3441 CShake256,
3442}
3443
3444impl CShakeAlgorithm {
3445 fn as_str(&self) -> &'static str {
3446 match self {
3447 CShakeAlgorithm::CShake128 => ALG_CSHAKE_128,
3448 CShakeAlgorithm::CShake256 => ALG_CSHAKE_256,
3449 }
3450 }
3451}
3452
3453enum Argon2Algorithm {
3455 Argon2D,
3456 Argon2I,
3457 Argon2ID,
3458}
3459
3460impl Argon2Algorithm {
3461 fn as_str(&self) -> &'static str {
3462 match self {
3463 Argon2Algorithm::Argon2D => ALG_ARGON2D,
3464 Argon2Algorithm::Argon2I => ALG_ARGON2I,
3465 Argon2Algorithm::Argon2ID => ALG_ARGON2ID,
3466 }
3467 }
3468}
3469
3470enum SupportedAlgorithm {
3472 RsassaPkcs1V1_5,
3473 RsaPss,
3474 RsaOaep,
3475 Ecdsa,
3476 Ecdh,
3477 Ed25519,
3478 X25519,
3479 AesCtr,
3480 AesCbc,
3481 AesGcm,
3482 AesKw,
3483 Hmac,
3484 Sha(ShaAlgorithm),
3485 Hkdf,
3486 Pbkdf2,
3487 MlKem(MlKemAlgorithm),
3488 MlDsa(MlDsaAlgorithm),
3489 AesOcb,
3490 ChaCha20Poly1305,
3491 Sha3(Sha3Algorithm),
3492 CShake(CShakeAlgorithm),
3493 Argon2(Argon2Algorithm),
3494}
3495
3496impl SupportedAlgorithm {
3497 fn as_str(&self) -> &'static str {
3498 match self {
3499 SupportedAlgorithm::RsassaPkcs1V1_5 => ALG_RSASSA_PKCS1_V1_5,
3500 SupportedAlgorithm::RsaPss => ALG_RSA_PSS,
3501 SupportedAlgorithm::RsaOaep => ALG_RSA_OAEP,
3502 SupportedAlgorithm::Ecdsa => ALG_ECDSA,
3503 SupportedAlgorithm::Ecdh => ALG_ECDH,
3504 SupportedAlgorithm::Ed25519 => ALG_ED25519,
3505 SupportedAlgorithm::X25519 => ALG_X25519,
3506 SupportedAlgorithm::AesCtr => ALG_AES_CTR,
3507 SupportedAlgorithm::AesCbc => ALG_AES_CBC,
3508 SupportedAlgorithm::AesGcm => ALG_AES_GCM,
3509 SupportedAlgorithm::AesKw => ALG_AES_KW,
3510 SupportedAlgorithm::Hmac => ALG_HMAC,
3511 SupportedAlgorithm::Sha(sha_algorithm) => sha_algorithm.as_str(),
3512 SupportedAlgorithm::Hkdf => ALG_HKDF,
3513 SupportedAlgorithm::Pbkdf2 => ALG_PBKDF2,
3514 SupportedAlgorithm::MlKem(ml_kem_algorithm) => ml_kem_algorithm.as_str(),
3515 SupportedAlgorithm::MlDsa(ml_dsa_algorithm) => ml_dsa_algorithm.as_str(),
3516 SupportedAlgorithm::AesOcb => ALG_AES_OCB,
3517 SupportedAlgorithm::ChaCha20Poly1305 => ALG_CHACHA20_POLY1305,
3518 SupportedAlgorithm::Sha3(sha3_algorithm) => sha3_algorithm.as_str(),
3519 SupportedAlgorithm::CShake(cshake_algorithm) => cshake_algorithm.as_str(),
3520 SupportedAlgorithm::Argon2(argon2_algorithm) => argon2_algorithm.as_str(),
3521 }
3522 }
3523
3524 fn from_ignore_case(alg_name: &str) -> Result<SupportedAlgorithm, Error> {
3525 let Some(&alg_name) = SUPPORTED_ALGORITHMS
3526 .iter()
3527 .find(|supported_algorithm| supported_algorithm.eq_ignore_ascii_case(alg_name))
3528 else {
3529 return Err(Error::NotSupported(Some(format!(
3530 "Unsupported algorithm: {}",
3531 alg_name
3532 ))));
3533 };
3534 SupportedAlgorithm::try_from(alg_name)
3535 }
3536
3537 fn support(&self, op: Operation) -> Result<ParameterType, Error> {
3545 let desired_type = match (self, &op) {
3546 (Self::RsassaPkcs1V1_5, Operation::Sign) => ParameterType::None,
3548 (Self::RsassaPkcs1V1_5, Operation::Verify) => ParameterType::None,
3549 (Self::RsassaPkcs1V1_5, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3550 (Self::RsassaPkcs1V1_5, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3551 (Self::RsassaPkcs1V1_5, Operation::ExportKey) => ParameterType::None,
3552
3553 (Self::RsaPss, Operation::Sign) => ParameterType::RsaPssParams,
3555 (Self::RsaPss, Operation::Verify) => ParameterType::RsaPssParams,
3556 (Self::RsaPss, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3557 (Self::RsaPss, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3558 (Self::RsaPss, Operation::ExportKey) => ParameterType::None,
3559
3560 (Self::RsaOaep, Operation::Encrypt) => ParameterType::RsaOaepParams,
3562 (Self::RsaOaep, Operation::Decrypt) => ParameterType::RsaOaepParams,
3563 (Self::RsaOaep, Operation::GenerateKey) => ParameterType::RsaHashedKeyGenParams,
3564 (Self::RsaOaep, Operation::ImportKey) => ParameterType::RsaHashedImportParams,
3565 (Self::RsaOaep, Operation::ExportKey) => ParameterType::None,
3566
3567 (Self::Ecdsa, Operation::Sign) => ParameterType::EcdsaParams,
3569 (Self::Ecdsa, Operation::Verify) => ParameterType::EcdsaParams,
3570 (Self::Ecdsa, Operation::GenerateKey) => ParameterType::EcKeyGenParams,
3571 (Self::Ecdsa, Operation::ImportKey) => ParameterType::EcKeyImportParams,
3572 (Self::Ecdsa, Operation::ExportKey) => ParameterType::None,
3573
3574 (Self::Ecdh, Operation::GenerateKey) => ParameterType::EcKeyGenParams,
3576 (Self::Ecdh, Operation::DeriveBits) => ParameterType::EcdhKeyDeriveParams,
3577 (Self::Ecdh, Operation::ImportKey) => ParameterType::EcKeyImportParams,
3578 (Self::Ecdh, Operation::ExportKey) => ParameterType::None,
3579
3580 (Self::Ed25519, Operation::Sign) => ParameterType::None,
3582 (Self::Ed25519, Operation::Verify) => ParameterType::None,
3583 (Self::Ed25519, Operation::GenerateKey) => ParameterType::None,
3584 (Self::Ed25519, Operation::ImportKey) => ParameterType::None,
3585 (Self::Ed25519, Operation::ExportKey) => ParameterType::None,
3586
3587 (Self::X25519, Operation::DeriveBits) => ParameterType::EcdhKeyDeriveParams,
3589 (Self::X25519, Operation::GenerateKey) => ParameterType::None,
3590 (Self::X25519, Operation::ImportKey) => ParameterType::None,
3591 (Self::X25519, Operation::ExportKey) => ParameterType::None,
3592
3593 (Self::AesCtr, Operation::Encrypt) => ParameterType::AesCtrParams,
3595 (Self::AesCtr, Operation::Decrypt) => ParameterType::AesCtrParams,
3596 (Self::AesCtr, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3597 (Self::AesCtr, Operation::ImportKey) => ParameterType::None,
3598 (Self::AesCtr, Operation::ExportKey) => ParameterType::None,
3599 (Self::AesCtr, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3600
3601 (Self::AesCbc, Operation::Encrypt) => ParameterType::AesCbcParams,
3603 (Self::AesCbc, Operation::Decrypt) => ParameterType::AesCbcParams,
3604 (Self::AesCbc, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3605 (Self::AesCbc, Operation::ImportKey) => ParameterType::None,
3606 (Self::AesCbc, Operation::ExportKey) => ParameterType::None,
3607 (Self::AesCbc, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3608
3609 (Self::AesGcm, Operation::Encrypt) => ParameterType::AesGcmParams,
3611 (Self::AesGcm, Operation::Decrypt) => ParameterType::AesGcmParams,
3612 (Self::AesGcm, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3613 (Self::AesGcm, Operation::ImportKey) => ParameterType::None,
3614 (Self::AesGcm, Operation::ExportKey) => ParameterType::None,
3615 (Self::AesGcm, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3616
3617 (Self::AesKw, Operation::WrapKey) => ParameterType::None,
3619 (Self::AesKw, Operation::UnwrapKey) => ParameterType::None,
3620 (Self::AesKw, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3621 (Self::AesKw, Operation::ImportKey) => ParameterType::None,
3622 (Self::AesKw, Operation::ExportKey) => ParameterType::None,
3623 (Self::AesKw, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3624
3625 (Self::Hmac, Operation::Sign) => ParameterType::None,
3627 (Self::Hmac, Operation::Verify) => ParameterType::None,
3628 (Self::Hmac, Operation::GenerateKey) => ParameterType::HmacKeyGenParams,
3629 (Self::Hmac, Operation::ImportKey) => ParameterType::HmacImportParams,
3630 (Self::Hmac, Operation::ExportKey) => ParameterType::None,
3631 (Self::Hmac, Operation::GetKeyLength) => ParameterType::HmacImportParams,
3632
3633 (Self::Sha(_), Operation::Digest) => ParameterType::None,
3635
3636 (Self::Hkdf, Operation::DeriveBits) => ParameterType::HkdfParams,
3638 (Self::Hkdf, Operation::ImportKey) => ParameterType::None,
3639 (Self::Hkdf, Operation::GetKeyLength) => ParameterType::None,
3640
3641 (Self::Pbkdf2, Operation::DeriveBits) => ParameterType::Pbkdf2Params,
3643 (Self::Pbkdf2, Operation::ImportKey) => ParameterType::None,
3644 (Self::Pbkdf2, Operation::GetKeyLength) => ParameterType::None,
3645
3646 (Self::MlKem(_), Operation::Encapsulate) => ParameterType::None,
3648 (Self::MlKem(_), Operation::Decapsulate) => ParameterType::None,
3649 (Self::MlKem(_), Operation::GenerateKey) => ParameterType::None,
3650 (Self::MlKem(_), Operation::ImportKey) => ParameterType::None,
3651 (Self::MlKem(_), Operation::ExportKey) => ParameterType::None,
3652
3653 (Self::MlDsa(_), Operation::Sign) => ParameterType::ContextParams,
3655 (Self::MlDsa(_), Operation::Verify) => ParameterType::ContextParams,
3656 (Self::MlDsa(_), Operation::GenerateKey) => ParameterType::None,
3657 (Self::MlDsa(_), Operation::ImportKey) => ParameterType::None,
3658 (Self::MlDsa(_), Operation::ExportKey) => ParameterType::None,
3659
3660 (Self::AesOcb, Operation::Encrypt) => ParameterType::AeadParams,
3662 (Self::AesOcb, Operation::Decrypt) => ParameterType::AeadParams,
3663 (Self::AesOcb, Operation::GenerateKey) => ParameterType::AesKeyGenParams,
3664 (Self::AesOcb, Operation::ImportKey) => ParameterType::None,
3665 (Self::AesOcb, Operation::ExportKey) => ParameterType::None,
3666 (Self::AesOcb, Operation::GetKeyLength) => ParameterType::AesDerivedKeyParams,
3667
3668 (Self::ChaCha20Poly1305, Operation::Encrypt) => ParameterType::AeadParams,
3670 (Self::ChaCha20Poly1305, Operation::Decrypt) => ParameterType::AeadParams,
3671 (Self::ChaCha20Poly1305, Operation::GenerateKey) => ParameterType::None,
3672 (Self::ChaCha20Poly1305, Operation::ImportKey) => ParameterType::None,
3673 (Self::ChaCha20Poly1305, Operation::ExportKey) => ParameterType::None,
3674 (Self::ChaCha20Poly1305, Operation::GetKeyLength) => ParameterType::None,
3675
3676 (Self::Sha3(_), Operation::Digest) => ParameterType::None,
3678
3679 (Self::CShake(_), Operation::Digest) => ParameterType::CShakeParams,
3681
3682 (Self::Argon2(_), Operation::DeriveBits) => ParameterType::Argon2Params,
3684 (Self::Argon2(_), Operation::ImportKey) => ParameterType::None,
3685 (Self::Argon2(_), Operation::GetKeyLength) => ParameterType::None,
3686
3687 _ => {
3688 return Err(Error::NotSupported(Some(format!(
3689 "{} does not support {} operation",
3690 self.as_str(),
3691 op.as_str()
3692 ))));
3693 },
3694 };
3695
3696 Ok(desired_type)
3697 }
3698}
3699
3700impl TryFrom<&str> for SupportedAlgorithm {
3701 type Error = Error;
3702
3703 fn try_from(value: &str) -> Result<Self, Self::Error> {
3704 match value {
3705 ALG_RSASSA_PKCS1_V1_5 => Ok(SupportedAlgorithm::RsassaPkcs1V1_5),
3706 ALG_RSA_PSS => Ok(SupportedAlgorithm::RsaPss),
3707 ALG_RSA_OAEP => Ok(SupportedAlgorithm::RsaOaep),
3708 ALG_ECDSA => Ok(SupportedAlgorithm::Ecdsa),
3709 ALG_ECDH => Ok(SupportedAlgorithm::Ecdh),
3710 ALG_ED25519 => Ok(SupportedAlgorithm::Ed25519),
3711 ALG_X25519 => Ok(SupportedAlgorithm::X25519),
3712 ALG_AES_CTR => Ok(SupportedAlgorithm::AesCtr),
3713 ALG_AES_CBC => Ok(SupportedAlgorithm::AesCbc),
3714 ALG_AES_GCM => Ok(SupportedAlgorithm::AesGcm),
3715 ALG_AES_KW => Ok(SupportedAlgorithm::AesKw),
3716 ALG_HMAC => Ok(SupportedAlgorithm::Hmac),
3717 ALG_SHA1 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha1)),
3718 ALG_SHA256 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha256)),
3719 ALG_SHA384 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha384)),
3720 ALG_SHA512 => Ok(SupportedAlgorithm::Sha(ShaAlgorithm::Sha512)),
3721 ALG_HKDF => Ok(SupportedAlgorithm::Hkdf),
3722 ALG_PBKDF2 => Ok(SupportedAlgorithm::Pbkdf2),
3723 ALG_ML_KEM_512 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem512)),
3724 ALG_ML_KEM_768 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem768)),
3725 ALG_ML_KEM_1024 => Ok(SupportedAlgorithm::MlKem(MlKemAlgorithm::MlKem1024)),
3726 ALG_ML_DSA_44 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa44)),
3727 ALG_ML_DSA_65 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa65)),
3728 ALG_ML_DSA_87 => Ok(SupportedAlgorithm::MlDsa(MlDsaAlgorithm::MlDsa87)),
3729 ALG_AES_OCB => Ok(SupportedAlgorithm::AesOcb),
3730 ALG_CHACHA20_POLY1305 => Ok(SupportedAlgorithm::ChaCha20Poly1305),
3731 ALG_SHA3_256 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_256)),
3732 ALG_SHA3_384 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_384)),
3733 ALG_SHA3_512 => Ok(SupportedAlgorithm::Sha3(Sha3Algorithm::Sha3_512)),
3734 ALG_CSHAKE_128 => Ok(SupportedAlgorithm::CShake(CShakeAlgorithm::CShake128)),
3735 ALG_CSHAKE_256 => Ok(SupportedAlgorithm::CShake(CShakeAlgorithm::CShake256)),
3736 ALG_ARGON2D => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2D)),
3737 ALG_ARGON2I => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2I)),
3738 ALG_ARGON2ID => Ok(SupportedAlgorithm::Argon2(Argon2Algorithm::Argon2ID)),
3739 _ => Err(Error::NotSupported(Some(format!(
3740 "Unsupported algorithm: {}",
3741 value
3742 )))),
3743 }
3744 }
3745}
3746
3747enum ParameterType {
3748 None,
3749 RsaHashedKeyGenParams,
3750 RsaHashedImportParams,
3751 RsaPssParams,
3752 RsaOaepParams,
3753 EcdsaParams,
3754 EcKeyGenParams,
3755 EcKeyImportParams,
3756 EcdhKeyDeriveParams,
3757 AesCtrParams,
3758 AesKeyGenParams,
3759 AesDerivedKeyParams,
3760 AesCbcParams,
3761 AesGcmParams,
3762 HmacImportParams,
3763 HmacKeyGenParams,
3764 HkdfParams,
3765 Pbkdf2Params,
3766 ContextParams,
3767 AeadParams,
3768 CShakeParams,
3769 Argon2Params,
3770}
3771
3772#[derive(Clone, MallocSizeOf)]
3777enum NormalizedAlgorithm {
3778 Algorithm(SubtleAlgorithm),
3779 RsaHashedKeyGenParams(SubtleRsaHashedKeyGenParams),
3780 RsaHashedImportParams(SubtleRsaHashedImportParams),
3781 RsaPssParams(SubtleRsaPssParams),
3782 RsaOaepParams(SubtleRsaOaepParams),
3783 EcdsaParams(SubtleEcdsaParams),
3784 EcKeyGenParams(SubtleEcKeyGenParams),
3785 EcKeyImportParams(SubtleEcKeyImportParams),
3786 EcdhKeyDeriveParams(SubtleEcdhKeyDeriveParams),
3787 AesCtrParams(SubtleAesCtrParams),
3788 AesKeyGenParams(SubtleAesKeyGenParams),
3789 AesDerivedKeyParams(SubtleAesDerivedKeyParams),
3790 AesCbcParams(SubtleAesCbcParams),
3791 AesGcmParams(SubtleAesGcmParams),
3792 HmacImportParams(SubtleHmacImportParams),
3793 HmacKeyGenParams(SubtleHmacKeyGenParams),
3794 HkdfParams(SubtleHkdfParams),
3795 Pbkdf2Params(SubtlePbkdf2Params),
3796 ContextParams(SubtleContextParams),
3797 AeadParams(SubtleAeadParams),
3798 CShakeParams(SubtleCShakeParams),
3799 Argon2Params(SubtleArgon2Params),
3800}
3801
3802fn normalize_algorithm(
3804 cx: JSContext,
3805 op: Operation,
3806 alg: &AlgorithmIdentifier,
3807 can_gc: CanGc,
3808) -> Result<NormalizedAlgorithm, Error> {
3809 match alg {
3810 ObjectOrString::String(name) => {
3812 let alg = Algorithm {
3816 name: name.to_owned(),
3817 };
3818 rooted!(in(*cx) let mut alg_value = UndefinedValue());
3819 alg.safe_to_jsval(cx, alg_value.handle_mut(), CanGc::note());
3820 let alg_obj = RootedTraceableBox::new(Heap::default());
3821 alg_obj.set(alg_value.to_object());
3822 normalize_algorithm(cx, op, &ObjectOrString::Object(alg_obj), can_gc)
3823 },
3824 ObjectOrString::Object(obj) => {
3826 rooted!(in(*cx) let value = ObjectValue(obj.get()));
3835 let initial_alg = dictionary_from_jsval::<Algorithm>(cx, value.handle(), can_gc)?;
3836
3837 let alg_name = SupportedAlgorithm::from_ignore_case(&initial_alg.name.str())?;
3847 let desired_type = alg_name.support(op)?;
3848
3849 rooted!(in(*cx) let mut alg_name_ptr = UndefinedValue());
3879 alg_name
3880 .as_str()
3881 .safe_to_jsval(cx, alg_name_ptr.handle_mut(), can_gc);
3882 set_dictionary_property(cx, obj.handle(), c"name", alg_name_ptr.handle())
3883 .map_err(|_| Error::JSFailed)?;
3884 let normalized_algorithm =
3885 NormalizedAlgorithm::from_object_value(cx, value.handle(), desired_type, can_gc)?;
3886
3887 Ok(normalized_algorithm)
3889 },
3890 }
3891}
3892
3893impl NormalizedAlgorithm {
3894 fn from_object_value(
3904 cx: JSContext,
3905 value: HandleValue,
3906 desired_type: ParameterType,
3907 can_gc: CanGc,
3908 ) -> Result<NormalizedAlgorithm, Error> {
3909 let normalized_algorithm = match desired_type {
3910 ParameterType::None => NormalizedAlgorithm::Algorithm(
3911 dictionary_from_jsval::<Algorithm>(cx, value, can_gc)?.into(),
3912 ),
3913 ParameterType::RsaHashedKeyGenParams => NormalizedAlgorithm::RsaHashedKeyGenParams(
3914 dictionary_from_jsval::<RootedTraceableBox<RsaHashedKeyGenParams>>(
3915 cx, value, can_gc,
3916 )?
3917 .try_into()?,
3918 ),
3919 ParameterType::RsaHashedImportParams => NormalizedAlgorithm::RsaHashedImportParams(
3920 dictionary_from_jsval::<RootedTraceableBox<RsaHashedImportParams>>(
3921 cx, value, can_gc,
3922 )?
3923 .try_into()?,
3924 ),
3925 ParameterType::RsaPssParams => NormalizedAlgorithm::RsaPssParams(
3926 dictionary_from_jsval::<RsaPssParams>(cx, value, can_gc)?.into(),
3927 ),
3928 ParameterType::RsaOaepParams => NormalizedAlgorithm::RsaOaepParams(
3929 dictionary_from_jsval::<RootedTraceableBox<RsaOaepParams>>(cx, value, can_gc)?
3930 .into(),
3931 ),
3932 ParameterType::EcdsaParams => NormalizedAlgorithm::EcdsaParams(
3933 dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(cx, value, can_gc)?
3934 .try_into()?,
3935 ),
3936 ParameterType::EcKeyGenParams => NormalizedAlgorithm::EcKeyGenParams(
3937 dictionary_from_jsval::<EcKeyGenParams>(cx, value, can_gc)?.into(),
3938 ),
3939 ParameterType::EcKeyImportParams => NormalizedAlgorithm::EcKeyImportParams(
3940 dictionary_from_jsval::<EcKeyImportParams>(cx, value, can_gc)?.into(),
3941 ),
3942 ParameterType::EcdhKeyDeriveParams => NormalizedAlgorithm::EcdhKeyDeriveParams(
3943 dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value, can_gc)?.into(),
3944 ),
3945 ParameterType::AesCtrParams => NormalizedAlgorithm::AesCtrParams(
3946 dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(cx, value, can_gc)?
3947 .into(),
3948 ),
3949 ParameterType::AesKeyGenParams => NormalizedAlgorithm::AesKeyGenParams(
3950 dictionary_from_jsval::<AesKeyGenParams>(cx, value, can_gc)?.into(),
3951 ),
3952 ParameterType::AesDerivedKeyParams => NormalizedAlgorithm::AesDerivedKeyParams(
3953 dictionary_from_jsval::<AesDerivedKeyParams>(cx, value, can_gc)?.into(),
3954 ),
3955 ParameterType::AesCbcParams => NormalizedAlgorithm::AesCbcParams(
3956 dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(cx, value, can_gc)?
3957 .into(),
3958 ),
3959 ParameterType::AesGcmParams => NormalizedAlgorithm::AesGcmParams(
3960 dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(cx, value, can_gc)?
3961 .into(),
3962 ),
3963 ParameterType::HmacImportParams => NormalizedAlgorithm::HmacImportParams(
3964 dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(cx, value, can_gc)?
3965 .try_into()?,
3966 ),
3967 ParameterType::HmacKeyGenParams => NormalizedAlgorithm::HmacKeyGenParams(
3968 dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(cx, value, can_gc)?
3969 .try_into()?,
3970 ),
3971 ParameterType::HkdfParams => NormalizedAlgorithm::HkdfParams(
3972 dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(cx, value, can_gc)?
3973 .try_into()?,
3974 ),
3975 ParameterType::Pbkdf2Params => NormalizedAlgorithm::Pbkdf2Params(
3976 dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(cx, value, can_gc)?
3977 .try_into()?,
3978 ),
3979 ParameterType::ContextParams => NormalizedAlgorithm::ContextParams(
3980 dictionary_from_jsval::<RootedTraceableBox<ContextParams>>(cx, value, can_gc)?
3981 .into(),
3982 ),
3983 ParameterType::AeadParams => NormalizedAlgorithm::AeadParams(
3984 dictionary_from_jsval::<RootedTraceableBox<AeadParams>>(cx, value, can_gc)?.into(),
3985 ),
3986 ParameterType::CShakeParams => NormalizedAlgorithm::CShakeParams(
3987 dictionary_from_jsval::<RootedTraceableBox<CShakeParams>>(cx, value, can_gc)?
3988 .into(),
3989 ),
3990 ParameterType::Argon2Params => NormalizedAlgorithm::Argon2Params(
3991 dictionary_from_jsval::<RootedTraceableBox<Argon2Params>>(cx, value, can_gc)?
3992 .into(),
3993 ),
3994 };
3995
3996 Ok(normalized_algorithm)
3997 }
3998
3999 fn name(&self) -> &str {
4001 match self {
4002 NormalizedAlgorithm::Algorithm(algo) => &algo.name,
4003 NormalizedAlgorithm::RsaHashedKeyGenParams(algo) => &algo.name,
4004 NormalizedAlgorithm::RsaHashedImportParams(algo) => &algo.name,
4005 NormalizedAlgorithm::RsaPssParams(algo) => &algo.name,
4006 NormalizedAlgorithm::RsaOaepParams(algo) => &algo.name,
4007 NormalizedAlgorithm::EcdsaParams(algo) => &algo.name,
4008 NormalizedAlgorithm::EcKeyGenParams(algo) => &algo.name,
4009 NormalizedAlgorithm::EcKeyImportParams(algo) => &algo.name,
4010 NormalizedAlgorithm::EcdhKeyDeriveParams(algo) => &algo.name,
4011 NormalizedAlgorithm::AesCtrParams(algo) => &algo.name,
4012 NormalizedAlgorithm::AesKeyGenParams(algo) => &algo.name,
4013 NormalizedAlgorithm::AesDerivedKeyParams(algo) => &algo.name,
4014 NormalizedAlgorithm::AesCbcParams(algo) => &algo.name,
4015 NormalizedAlgorithm::AesGcmParams(algo) => &algo.name,
4016 NormalizedAlgorithm::HmacImportParams(algo) => &algo.name,
4017 NormalizedAlgorithm::HmacKeyGenParams(algo) => &algo.name,
4018 NormalizedAlgorithm::HkdfParams(algo) => &algo.name,
4019 NormalizedAlgorithm::Pbkdf2Params(algo) => &algo.name,
4020 NormalizedAlgorithm::ContextParams(algo) => &algo.name,
4021 NormalizedAlgorithm::AeadParams(algo) => &algo.name,
4022 NormalizedAlgorithm::CShakeParams(algo) => &algo.name,
4023 NormalizedAlgorithm::Argon2Params(algo) => &algo.name,
4024 }
4025 }
4026
4027 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4028 match (self.name(), self) {
4029 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaOaepParams(algo)) => {
4030 rsa_oaep_operation::encrypt(algo, key, plaintext)
4031 },
4032 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
4033 aes_ctr_operation::encrypt(algo, key, plaintext)
4034 },
4035 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
4036 aes_cbc_operation::encrypt(algo, key, plaintext)
4037 },
4038 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
4039 aes_gcm_operation::encrypt(algo, key, plaintext)
4040 },
4041 (ALG_AES_OCB, NormalizedAlgorithm::AeadParams(algo)) => {
4042 aes_ocb_operation::encrypt(algo, key, plaintext)
4043 },
4044 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
4045 chacha20_poly1305_operation::encrypt(algo, key, plaintext)
4046 },
4047 _ => Err(Error::NotSupported(None)),
4048 }
4049 }
4050
4051 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4052 match (self.name(), self) {
4053 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaOaepParams(algo)) => {
4054 rsa_oaep_operation::decrypt(algo, key, ciphertext)
4055 },
4056 (ALG_AES_CTR, NormalizedAlgorithm::AesCtrParams(algo)) => {
4057 aes_ctr_operation::decrypt(algo, key, ciphertext)
4058 },
4059 (ALG_AES_CBC, NormalizedAlgorithm::AesCbcParams(algo)) => {
4060 aes_cbc_operation::decrypt(algo, key, ciphertext)
4061 },
4062 (ALG_AES_GCM, NormalizedAlgorithm::AesGcmParams(algo)) => {
4063 aes_gcm_operation::decrypt(algo, key, ciphertext)
4064 },
4065 (ALG_AES_OCB, NormalizedAlgorithm::AeadParams(algo)) => {
4066 aes_ocb_operation::decrypt(algo, key, ciphertext)
4067 },
4068 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::AeadParams(algo)) => {
4069 chacha20_poly1305_operation::decrypt(algo, key, ciphertext)
4070 },
4071 _ => Err(Error::NotSupported(None)),
4072 }
4073 }
4074
4075 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
4076 match (self.name(), self) {
4077 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::Algorithm(_algo)) => {
4078 rsassa_pkcs1_v1_5_operation::sign(key, message)
4079 },
4080 (ALG_RSA_PSS, NormalizedAlgorithm::RsaPssParams(algo)) => {
4081 rsa_pss_operation::sign(algo, key, message)
4082 },
4083 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
4084 ecdsa_operation::sign(algo, key, message)
4085 },
4086 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4087 ed25519_operation::sign(key, message)
4088 },
4089 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => hmac_operation::sign(key, message),
4090 (
4091 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4092 NormalizedAlgorithm::ContextParams(algo),
4093 ) => ml_dsa_operation::sign(algo, key, message),
4094 _ => Err(Error::NotSupported(None)),
4095 }
4096 }
4097
4098 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4099 match (self.name(), self) {
4100 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::Algorithm(_algo)) => {
4101 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4102 },
4103 (ALG_RSA_PSS, NormalizedAlgorithm::RsaPssParams(algo)) => {
4104 rsa_pss_operation::verify(algo, key, message, signature)
4105 },
4106 (ALG_ECDSA, NormalizedAlgorithm::EcdsaParams(algo)) => {
4107 ecdsa_operation::verify(algo, key, message, signature)
4108 },
4109 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4110 ed25519_operation::verify(key, message, signature)
4111 },
4112 (ALG_HMAC, NormalizedAlgorithm::Algorithm(_algo)) => {
4113 hmac_operation::verify(key, message, signature)
4114 },
4115 (
4116 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4117 NormalizedAlgorithm::ContextParams(algo),
4118 ) => ml_dsa_operation::verify(algo, key, message, signature),
4119 _ => Err(Error::NotSupported(None)),
4120 }
4121 }
4122
4123 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
4124 match (self.name(), self) {
4125 (ALG_SHA1, NormalizedAlgorithm::Algorithm(algo)) => {
4126 sha_operation::digest(algo, message)
4127 },
4128 (ALG_SHA256, NormalizedAlgorithm::Algorithm(algo)) => {
4129 sha_operation::digest(algo, message)
4130 },
4131 (ALG_SHA384, NormalizedAlgorithm::Algorithm(algo)) => {
4132 sha_operation::digest(algo, message)
4133 },
4134 (ALG_SHA512, NormalizedAlgorithm::Algorithm(algo)) => {
4135 sha_operation::digest(algo, message)
4136 },
4137 (ALG_SHA3_256, NormalizedAlgorithm::Algorithm(algo)) => {
4138 sha3_operation::digest(algo, message)
4139 },
4140 (ALG_SHA3_384, NormalizedAlgorithm::Algorithm(algo)) => {
4141 sha3_operation::digest(algo, message)
4142 },
4143 (ALG_SHA3_512, NormalizedAlgorithm::Algorithm(algo)) => {
4144 sha3_operation::digest(algo, message)
4145 },
4146 (ALG_CSHAKE_128, NormalizedAlgorithm::CShakeParams(algo)) => {
4147 cshake_operation::digest(algo, message)
4148 },
4149 (ALG_CSHAKE_256, NormalizedAlgorithm::CShakeParams(algo)) => {
4150 cshake_operation::digest(algo, message)
4151 },
4152 _ => Err(Error::NotSupported(None)),
4153 }
4154 }
4155
4156 fn generate_key(
4157 &self,
4158 global: &GlobalScope,
4159 extractable: bool,
4160 usages: Vec<KeyUsage>,
4161 can_gc: CanGc,
4162 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
4163 match (self.name(), self) {
4164 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4165 rsassa_pkcs1_v1_5_operation::generate_key(global, algo, extractable, usages, can_gc)
4166 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4167 },
4168 (ALG_RSA_PSS, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4169 rsa_pss_operation::generate_key(global, algo, extractable, usages, can_gc)
4170 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4171 },
4172 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaHashedKeyGenParams(algo)) => {
4173 rsa_oaep_operation::generate_key(global, algo, extractable, usages, can_gc)
4174 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4175 },
4176 (ALG_ECDSA, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
4177 ecdsa_operation::generate_key(global, algo, extractable, usages, can_gc)
4178 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4179 },
4180 (ALG_ECDH, NormalizedAlgorithm::EcKeyGenParams(algo)) => {
4181 ecdh_operation::generate_key(global, algo, extractable, usages, can_gc)
4182 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4183 },
4184 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4185 ed25519_operation::generate_key(global, extractable, usages, can_gc)
4186 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4187 },
4188 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4189 x25519_operation::generate_key(global, extractable, usages, can_gc)
4190 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4191 },
4192 (ALG_AES_CTR, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4193 aes_ctr_operation::generate_key(global, algo, extractable, usages, can_gc)
4194 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4195 },
4196 (ALG_AES_CBC, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4197 aes_cbc_operation::generate_key(global, algo, extractable, usages, can_gc)
4198 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4199 },
4200 (ALG_AES_GCM, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4201 aes_gcm_operation::generate_key(global, algo, extractable, usages, can_gc)
4202 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4203 },
4204 (ALG_AES_KW, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4205 aes_kw_operation::generate_key(global, algo, extractable, usages, can_gc)
4206 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4207 },
4208 (ALG_HMAC, NormalizedAlgorithm::HmacKeyGenParams(algo)) => {
4209 hmac_operation::generate_key(global, algo, extractable, usages, can_gc)
4210 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4211 },
4212 (
4213 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4214 NormalizedAlgorithm::Algorithm(algo),
4215 ) => ml_kem_operation::generate_key(global, algo, extractable, usages, can_gc)
4216 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
4217 (
4218 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4219 NormalizedAlgorithm::Algorithm(algo),
4220 ) => ml_dsa_operation::generate_key(global, algo, extractable, usages, can_gc)
4221 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair),
4222 (ALG_AES_OCB, NormalizedAlgorithm::AesKeyGenParams(algo)) => {
4223 aes_ocb_operation::generate_key(global, algo, extractable, usages, can_gc)
4224 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4225 },
4226 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4227 chacha20_poly1305_operation::generate_key(global, extractable, usages, can_gc)
4228 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4229 },
4230 _ => Err(Error::NotSupported(None)),
4231 }
4232 }
4233
4234 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
4235 match (self.name(), self) {
4236 (ALG_ECDH, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
4237 ecdh_operation::derive_bits(algo, key, length)
4238 },
4239 (ALG_X25519, NormalizedAlgorithm::EcdhKeyDeriveParams(algo)) => {
4240 x25519_operation::derive_bits(algo, key, length)
4241 },
4242 (ALG_HKDF, NormalizedAlgorithm::HkdfParams(algo)) => {
4243 hkdf_operation::derive_bits(algo, key, length)
4244 },
4245 (ALG_PBKDF2, NormalizedAlgorithm::Pbkdf2Params(algo)) => {
4246 pbkdf2_operation::derive_bits(algo, key, length)
4247 },
4248 (ALG_ARGON2D, NormalizedAlgorithm::Argon2Params(algo)) => {
4249 argon2_operation::derive_bits(algo, key, length)
4250 },
4251 (ALG_ARGON2I, NormalizedAlgorithm::Argon2Params(algo)) => {
4252 argon2_operation::derive_bits(algo, key, length)
4253 },
4254 (ALG_ARGON2ID, NormalizedAlgorithm::Argon2Params(algo)) => {
4255 argon2_operation::derive_bits(algo, key, length)
4256 },
4257 _ => Err(Error::NotSupported(None)),
4258 }
4259 }
4260
4261 fn import_key(
4262 &self,
4263 global: &GlobalScope,
4264 format: KeyFormat,
4265 key_data: &[u8],
4266 extractable: bool,
4267 usages: Vec<KeyUsage>,
4268 can_gc: CanGc,
4269 ) -> Result<DomRoot<CryptoKey>, Error> {
4270 match (self.name(), self) {
4271 (ALG_RSASSA_PKCS1_V1_5, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4272 rsassa_pkcs1_v1_5_operation::import_key(
4273 global,
4274 algo,
4275 format,
4276 key_data,
4277 extractable,
4278 usages,
4279 can_gc,
4280 )
4281 },
4282 (ALG_RSA_PSS, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4283 rsa_pss_operation::import_key(
4284 global,
4285 algo,
4286 format,
4287 key_data,
4288 extractable,
4289 usages,
4290 can_gc,
4291 )
4292 },
4293 (ALG_RSA_OAEP, NormalizedAlgorithm::RsaHashedImportParams(algo)) => {
4294 rsa_oaep_operation::import_key(
4295 global,
4296 algo,
4297 format,
4298 key_data,
4299 extractable,
4300 usages,
4301 can_gc,
4302 )
4303 },
4304 (ALG_ECDSA, NormalizedAlgorithm::EcKeyImportParams(algo)) => {
4305 ecdsa_operation::import_key(
4306 global,
4307 algo,
4308 format,
4309 key_data,
4310 extractable,
4311 usages,
4312 can_gc,
4313 )
4314 },
4315 (ALG_ECDH, NormalizedAlgorithm::EcKeyImportParams(algo)) => ecdh_operation::import_key(
4316 global,
4317 algo,
4318 format,
4319 key_data,
4320 extractable,
4321 usages,
4322 can_gc,
4323 ),
4324 (ALG_ED25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4325 ed25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4326 },
4327 (ALG_X25519, NormalizedAlgorithm::Algorithm(_algo)) => {
4328 x25519_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4329 },
4330 (ALG_AES_CTR, NormalizedAlgorithm::Algorithm(_algo)) => {
4331 aes_ctr_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4332 },
4333 (ALG_AES_CBC, NormalizedAlgorithm::Algorithm(_algo)) => {
4334 aes_cbc_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4335 },
4336 (ALG_AES_GCM, NormalizedAlgorithm::Algorithm(_algo)) => {
4337 aes_gcm_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4338 },
4339 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4340 aes_kw_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4341 },
4342 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => hmac_operation::import_key(
4343 global,
4344 algo,
4345 format,
4346 key_data,
4347 extractable,
4348 usages,
4349 can_gc,
4350 ),
4351 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => {
4352 hkdf_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4353 },
4354 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
4355 pbkdf2_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4356 },
4357 (
4358 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4359 NormalizedAlgorithm::Algorithm(algo),
4360 ) => ml_kem_operation::import_key(
4361 global,
4362 algo,
4363 format,
4364 key_data,
4365 extractable,
4366 usages,
4367 can_gc,
4368 ),
4369 (
4370 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87,
4371 NormalizedAlgorithm::Algorithm(algo),
4372 ) => ml_dsa_operation::import_key(
4373 global,
4374 algo,
4375 format,
4376 key_data,
4377 extractable,
4378 usages,
4379 can_gc,
4380 ),
4381 (ALG_AES_OCB, NormalizedAlgorithm::Algorithm(_algo)) => {
4382 aes_ocb_operation::import_key(global, format, key_data, extractable, usages, can_gc)
4383 },
4384 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4385 chacha20_poly1305_operation::import_key(
4386 global,
4387 format,
4388 key_data,
4389 extractable,
4390 usages,
4391 can_gc,
4392 )
4393 },
4394 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4395 global,
4396 algo,
4397 format,
4398 key_data,
4399 extractable,
4400 usages,
4401 can_gc,
4402 ),
4403 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4404 global,
4405 algo,
4406 format,
4407 key_data,
4408 extractable,
4409 usages,
4410 can_gc,
4411 ),
4412 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(algo)) => argon2_operation::import_key(
4413 global,
4414 algo,
4415 format,
4416 key_data,
4417 extractable,
4418 usages,
4419 can_gc,
4420 ),
4421 _ => Err(Error::NotSupported(None)),
4422 }
4423 }
4424
4425 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4426 match (self.name(), self) {
4427 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4428 aes_kw_operation::wrap_key(key, plaintext)
4429 },
4430 _ => Err(Error::NotSupported(None)),
4431 }
4432 }
4433
4434 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4435 match (self.name(), self) {
4436 (ALG_AES_KW, NormalizedAlgorithm::Algorithm(_algo)) => {
4437 aes_kw_operation::unwrap_key(key, ciphertext)
4438 },
4439 _ => Err(Error::NotSupported(None)),
4440 }
4441 }
4442
4443 fn get_key_length(&self) -> Result<Option<u32>, Error> {
4444 match (self.name(), self) {
4445 (ALG_AES_CTR, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4446 aes_ctr_operation::get_key_length(algo)
4447 },
4448 (ALG_AES_CBC, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4449 aes_cbc_operation::get_key_length(algo)
4450 },
4451 (ALG_AES_GCM, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4452 aes_gcm_operation::get_key_length(algo)
4453 },
4454 (ALG_AES_KW, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4455 aes_kw_operation::get_key_length(algo)
4456 },
4457 (ALG_HMAC, NormalizedAlgorithm::HmacImportParams(algo)) => {
4458 hmac_operation::get_key_length(algo)
4459 },
4460 (ALG_HKDF, NormalizedAlgorithm::Algorithm(_algo)) => hkdf_operation::get_key_length(),
4461 (ALG_PBKDF2, NormalizedAlgorithm::Algorithm(_algo)) => {
4462 pbkdf2_operation::get_key_length()
4463 },
4464 (ALG_AES_OCB, NormalizedAlgorithm::AesDerivedKeyParams(algo)) => {
4465 aes_ocb_operation::get_key_length(algo)
4466 },
4467 (ALG_CHACHA20_POLY1305, NormalizedAlgorithm::Algorithm(_algo)) => {
4468 chacha20_poly1305_operation::get_key_length()
4469 },
4470 (ALG_ARGON2D, NormalizedAlgorithm::Algorithm(_algo)) => {
4471 argon2_operation::get_key_length()
4472 },
4473 (ALG_ARGON2I, NormalizedAlgorithm::Algorithm(_algo)) => {
4474 argon2_operation::get_key_length()
4475 },
4476 (ALG_ARGON2ID, NormalizedAlgorithm::Algorithm(_algo)) => {
4477 argon2_operation::get_key_length()
4478 },
4479 _ => Err(Error::NotSupported(None)),
4480 }
4481 }
4482
4483 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
4484 match (self.name(), self) {
4485 (
4486 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4487 NormalizedAlgorithm::Algorithm(algo),
4488 ) => ml_kem_operation::encapsulate(algo, key),
4489 _ => Err(Error::NotSupported(None)),
4490 }
4491 }
4492
4493 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4494 match (self.name(), self) {
4495 (
4496 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024,
4497 NormalizedAlgorithm::Algorithm(algo),
4498 ) => ml_kem_operation::decapsulate(algo, key, ciphertext),
4499 _ => Err(Error::NotSupported(None)),
4500 }
4501 }
4502}
4503
4504fn perform_export_key_operation(format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
4511 match key.algorithm().name() {
4512 ALG_RSASSA_PKCS1_V1_5 => rsassa_pkcs1_v1_5_operation::export_key(format, key),
4513 ALG_RSA_PSS => rsa_pss_operation::export_key(format, key),
4514 ALG_RSA_OAEP => rsa_oaep_operation::export_key(format, key),
4515 ALG_ECDSA => ecdsa_operation::export_key(format, key),
4516 ALG_ECDH => ecdh_operation::export_key(format, key),
4517 ALG_ED25519 => ed25519_operation::export_key(format, key),
4518 ALG_X25519 => x25519_operation::export_key(format, key),
4519 ALG_AES_CTR => aes_ctr_operation::export_key(format, key),
4520 ALG_AES_CBC => aes_cbc_operation::export_key(format, key),
4521 ALG_AES_GCM => aes_gcm_operation::export_key(format, key),
4522 ALG_AES_KW => aes_kw_operation::export_key(format, key),
4523 ALG_HMAC => hmac_operation::export_key(format, key),
4524 ALG_ML_KEM_512 | ALG_ML_KEM_768 | ALG_ML_KEM_1024 => {
4525 ml_kem_operation::export_key(format, key)
4526 },
4527 ALG_ML_DSA_44 | ALG_ML_DSA_65 | ALG_ML_DSA_87 => ml_dsa_operation::export_key(format, key),
4528 ALG_AES_OCB => aes_ocb_operation::export_key(format, key),
4529 ALG_CHACHA20_POLY1305 => chacha20_poly1305_operation::export_key(format, key),
4530 _ => Err(Error::NotSupported(None)),
4531 }
4532}