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 ec_common;
15mod ecdh_operation;
16mod ecdsa_operation;
17mod ed25519_operation;
18mod hkdf_operation;
19mod hmac_operation;
20mod ml_dsa_operation;
21mod ml_kem_operation;
22mod pbkdf2_operation;
23mod rsa_common;
24mod rsa_oaep_operation;
25mod rsa_pss_operation;
26mod rsassa_pkcs1_v1_5_operation;
27mod sha3_operation;
28mod sha_operation;
29mod turboshake_operation;
30mod x25519_operation;
31
32use std::fmt::Display;
33use std::ptr;
34use std::rc::Rc;
35use std::str::FromStr;
36
37use base64ct::{Base64UrlUnpadded, Encoding};
38use dom_struct::dom_struct;
39use js::conversions::{ConversionBehavior, ConversionResult};
40use js::jsapi::{Heap, JSObject};
41use js::jsval::UndefinedValue;
42use js::realm::CurrentRealm;
43use js::rust::wrappers2::JS_ParseJSON;
44use js::rust::{HandleObject, MutableHandleValue, Trace};
45use js::typedarray::{ArrayBufferU8, HeapUint8Array};
46use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
47use strum::{EnumString, IntoStaticStr, VariantArray};
48use zeroize::Zeroizing;
49
50use crate::dom::bindings::buffer_source::create_buffer_source;
51use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
52 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
53};
54use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
55 AesKeyAlgorithm, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EncapsulatedBits,
56 EncapsulatedKey, HmacKeyAlgorithm, JsonWebKey, KeyAlgorithm, KeyFormat, RsaHashedKeyAlgorithm,
57 RsaKeyAlgorithm, SubtleCryptoMethods,
58};
59use crate::dom::bindings::codegen::UnionTypes::{
60 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
61};
62use crate::dom::bindings::conversions::{
63 SafeFromJSValConvertible, SafeToJSValConvertible, StringificationBehavior,
64};
65use crate::dom::bindings::error::{Error, Fallible};
66use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
67use crate::dom::bindings::reflector::DomGlobal;
68use crate::dom::bindings::root::DomRoot;
69use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
70use crate::dom::bindings::trace::RootedTraceableBox;
71use crate::dom::bindings::utils::get_dictionary_property;
72use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
73use crate::dom::globalscope::GlobalScope;
74use crate::dom::promise::Promise;
75use crate::script_runtime::{CanGc, JSContext};
76
77const NAMED_CURVE_P256: &str = "P-256";
79const NAMED_CURVE_P384: &str = "P-384";
80const NAMED_CURVE_P521: &str = "P-521";
81
82static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
83
84#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
85enum CryptoAlgorithm {
86 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
87 RsassaPkcs1V1_5,
88 #[strum(serialize = "RSA-PSS")]
89 RsaPss,
90 #[strum(serialize = "RSA-OAEP")]
91 RsaOaep,
92 #[strum(serialize = "ECDSA")]
93 Ecdsa,
94 #[strum(serialize = "ECDH")]
95 Ecdh,
96 #[strum(serialize = "Ed25519")]
97 Ed25519,
98 #[strum(serialize = "X25519")]
99 X25519,
100 #[strum(serialize = "AES-CTR")]
101 AesCtr,
102 #[strum(serialize = "AES-CBC")]
103 AesCbc,
104 #[strum(serialize = "AES-GCM")]
105 AesGcm,
106 #[strum(serialize = "AES-KW")]
107 AesKw,
108 #[strum(serialize = "HMAC")]
109 Hmac,
110 #[strum(serialize = "SHA-1")]
111 Sha1,
112 #[strum(serialize = "SHA-256")]
113 Sha256,
114 #[strum(serialize = "SHA-384")]
115 Sha384,
116 #[strum(serialize = "SHA-512")]
117 Sha512,
118 #[strum(serialize = "HKDF")]
119 Hkdf,
120 #[strum(serialize = "PBKDF2")]
121 Pbkdf2,
122 #[strum(serialize = "ML-KEM-512")]
123 MlKem512,
124 #[strum(serialize = "ML-KEM-768")]
125 MlKem768,
126 #[strum(serialize = "ML-KEM-1024")]
127 MlKem1024,
128 #[strum(serialize = "ML-DSA-44")]
129 MlDsa44,
130 #[strum(serialize = "ML-DSA-65")]
131 MlDsa65,
132 #[strum(serialize = "ML-DSA-87")]
133 MlDsa87,
134 #[strum(serialize = "AES-OCB")]
135 AesOcb,
136 #[strum(serialize = "ChaCha20-Poly1305")]
137 ChaCha20Poly1305,
138 #[strum(serialize = "SHA3-256")]
139 Sha3_256,
140 #[strum(serialize = "SHA3-384")]
141 Sha3_384,
142 #[strum(serialize = "SHA3-512")]
143 Sha3_512,
144 #[strum(serialize = "cSHAKE128")]
145 CShake128,
146 #[strum(serialize = "cSHAKE256")]
147 CShake256,
148 #[strum(serialize = "TurboSHAKE128")]
149 TurboShake128,
150 #[strum(serialize = "TurboSHAKE256")]
151 TurboShake256,
152 #[strum(serialize = "Argon2d")]
153 Argon2D,
154 #[strum(serialize = "Argon2i")]
155 Argon2I,
156 #[strum(serialize = "Argon2id")]
157 Argon2ID,
158}
159
160impl CryptoAlgorithm {
161 fn as_str(&self) -> &'static str {
163 (*self).into()
164 }
165
166 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
167 Self::VARIANTS
168 .iter()
169 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
170 .cloned()
171 .ok_or(Error::NotSupported(Some(format!(
172 "Unsupported algorithm: {algorithm_name}"
173 ))))
174 }
175}
176
177#[dom_struct]
178pub(crate) struct SubtleCrypto {
179 reflector_: Reflector,
180}
181
182impl SubtleCrypto {
183 fn new_inherited() -> SubtleCrypto {
184 SubtleCrypto {
185 reflector_: Reflector::new(),
186 }
187 }
188
189 pub(crate) fn new(
190 cx: &mut js::context::JSContext,
191 global: &GlobalScope,
192 ) -> DomRoot<SubtleCrypto> {
193 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
194 }
195
196 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Zeroizing<Vec<u8>>) {
200 let trusted_promise = TrustedPromise::new(promise);
201 self.global()
202 .task_manager()
203 .crypto_task_source()
204 .queue(task!(resolve_data: move |cx| {
205 let promise = trusted_promise.root();
206
207 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
208 match create_buffer_source::<ArrayBufferU8>(
209 cx.into(),
210 &data,
211 array_buffer_ptr.handle_mut(),
212 CanGc::from_cx(cx),
213 ) {
214 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::from_cx(cx)),
215 Err(_) => promise.reject_error(Error::JSFailed, CanGc::from_cx(cx)),
216 }
217 }));
218 }
219
220 fn resolve_promise_with_jwk(
224 &self,
225 cx: &mut js::context::JSContext,
226 promise: Rc<Promise>,
227 jwk: Box<JsonWebKey>,
228 ) {
229 let stringified_jwk = match jwk.stringify(cx) {
232 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
233 Err(error) => {
234 self.reject_promise_with_error(promise, error);
235 return;
236 },
237 };
238
239 let trusted_subtle = Trusted::new(self);
240 let trusted_promise = TrustedPromise::new(promise);
241 self.global()
242 .task_manager()
243 .crypto_task_source()
244 .queue(task!(resolve_jwk: move |cx| {
245 let subtle = trusted_subtle.root();
246 let promise = trusted_promise.root();
247
248 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
249 Ok(jwk) => {
250 rooted!(&in(cx) let mut rval = UndefinedValue());
251 jwk.safe_to_jsval(cx.into(), rval.handle_mut(), CanGc::from_cx(cx));
252 rooted!(&in(cx) let mut object = rval.to_object());
253 promise.resolve_native(&*object, CanGc::from_cx(cx));
254 },
255 Err(error) => {
256 subtle.reject_promise_with_error(promise, error);
257 return;
258 },
259 }
260 }));
261 }
262
263 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
266 let trusted_key = Trusted::new(&*key);
267 let trusted_promise = TrustedPromise::new(promise);
268 self.global()
269 .task_manager()
270 .crypto_task_source()
271 .queue(task!(resolve_key: move |cx| {
272 let key = trusted_key.root();
273 let promise = trusted_promise.root();
274 promise.resolve_native(&key, CanGc::from_cx(cx));
275 }));
276 }
277
278 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
281 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
282 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
283 let trusted_promise = TrustedPromise::new(promise);
284 self.global()
285 .task_manager()
286 .crypto_task_source()
287 .queue(task!(resolve_key: move |cx| {
288 let key_pair = CryptoKeyPair {
289 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
290 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
291 };
292 let promise = trusted_promise.root();
293 promise.resolve_native(&key_pair, CanGc::from_cx(cx));
294 }));
295 }
296
297 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
300 let trusted_promise = TrustedPromise::new(promise);
301 self.global()
302 .task_manager()
303 .crypto_task_source()
304 .queue(task!(resolve_bool: move |cx| {
305 let promise = trusted_promise.root();
306 promise.resolve_native(&result, CanGc::from_cx(cx));
307 }));
308 }
309
310 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
313 let trusted_promise = TrustedPromise::new(promise);
314 self.global()
315 .task_manager()
316 .crypto_task_source()
317 .queue(task!(reject_error: move |cx| {
318 let promise = trusted_promise.root();
319 promise.reject_error(error, CanGc::from_cx(cx));
320 }));
321 }
322
323 fn resolve_promise_with_encapsulated_key(
327 &self,
328 promise: Rc<Promise>,
329 encapsulated_key: SubtleEncapsulatedKey,
330 ) {
331 let trusted_promise = TrustedPromise::new(promise);
332 self.global().task_manager().crypto_task_source().queue(
333 task!(resolve_encapsulated_key: move |cx| {
334 let promise = trusted_promise.root();
335 promise.resolve_native(&encapsulated_key, CanGc::from_cx(cx));
336 }),
337 );
338 }
339
340 fn resolve_promise_with_encapsulated_bits(
344 &self,
345 promise: Rc<Promise>,
346 encapsulated_bits: SubtleEncapsulatedBits,
347 ) {
348 let trusted_promise = TrustedPromise::new(promise);
349 self.global().task_manager().crypto_task_source().queue(
350 task!(resolve_encapsulated_bits: move |cx| {
351 let promise = trusted_promise.root();
352 promise.resolve_native(&encapsulated_bits, CanGc::from_cx(cx));
353 }),
354 );
355 }
356}
357
358impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
359 fn Encrypt(
361 &self,
362 cx: &mut CurrentRealm,
363 algorithm: AlgorithmIdentifier,
364 key: &CryptoKey,
365 data: ArrayBufferViewOrArrayBuffer,
366 ) -> Rc<Promise> {
367 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
375 Ok(normalized_algorithm) => normalized_algorithm,
376 Err(error) => {
377 let promise = Promise::new_in_realm(cx);
378 promise.reject_error(error, CanGc::from_cx(cx));
379 return promise;
380 },
381 };
382
383 let data = match data {
386 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => Zeroizing::new(view.to_vec()),
387 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => Zeroizing::new(buffer.to_vec()),
388 };
389
390 let promise = Promise::new_in_realm(cx);
393
394 let this = Trusted::new(self);
396 let trusted_promise = TrustedPromise::new(promise.clone());
397 let trusted_key = Trusted::new(key);
398 self.global()
399 .task_manager()
400 .dom_manipulation_task_source()
401 .queue(task!(encrypt: move || {
402 let subtle = this.root();
403 let promise = trusted_promise.root();
404 let key = trusted_key.root();
405
406 if normalized_algorithm.name() != key.algorithm().name() {
414 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
415 return;
416 }
417
418 if !key.usages().contains(&KeyUsage::Encrypt) {
421 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
422 return;
423 }
424
425 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
429 Ok(ciphertext) => ciphertext,
430 Err(error) => {
431 subtle.reject_promise_with_error(promise, error);
432 return;
433 },
434 };
435
436 subtle.resolve_promise_with_data(promise, ciphertext.into());
442 }));
443 promise
444 }
445
446 fn Decrypt(
448 &self,
449 cx: &mut CurrentRealm,
450 algorithm: AlgorithmIdentifier,
451 key: &CryptoKey,
452 data: ArrayBufferViewOrArrayBuffer,
453 ) -> Rc<Promise> {
454 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
462 Ok(normalized_algorithm) => normalized_algorithm,
463 Err(error) => {
464 let promise = Promise::new_in_realm(cx);
465 promise.reject_error(error, CanGc::from_cx(cx));
466 return promise;
467 },
468 };
469
470 let data = match data {
473 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
474 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
475 };
476
477 let promise = Promise::new_in_realm(cx);
480
481 let this = Trusted::new(self);
483 let trusted_promise = TrustedPromise::new(promise.clone());
484 let trusted_key = Trusted::new(key);
485 self.global()
486 .task_manager()
487 .dom_manipulation_task_source()
488 .queue(task!(decrypt: move || {
489 let subtle = this.root();
490 let promise = trusted_promise.root();
491 let key = trusted_key.root();
492
493 if normalized_algorithm.name() != key.algorithm().name() {
501 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
502 return;
503 }
504
505 if !key.usages().contains(&KeyUsage::Decrypt) {
508 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
509 return;
510 }
511
512 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
516 Ok(plaintext) => Zeroizing::new(plaintext),
517 Err(error) => {
518 subtle.reject_promise_with_error(promise, error);
519 return;
520 },
521 };
522
523 subtle.resolve_promise_with_data(promise, plaintext);
529 }));
530 promise
531 }
532
533 fn Sign(
535 &self,
536 cx: &mut CurrentRealm,
537 algorithm: AlgorithmIdentifier,
538 key: &CryptoKey,
539 data: ArrayBufferViewOrArrayBuffer,
540 ) -> Rc<Promise> {
541 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
549 Ok(normalized_algorithm) => normalized_algorithm,
550 Err(error) => {
551 let promise = Promise::new_in_realm(cx);
552 promise.reject_error(error, CanGc::from_cx(cx));
553 return promise;
554 },
555 };
556
557 let data = match &data {
560 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
561 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
562 };
563
564 let promise = Promise::new_in_realm(cx);
567
568 let this = Trusted::new(self);
570 let trusted_promise = TrustedPromise::new(promise.clone());
571 let trusted_key = Trusted::new(key);
572 self.global()
573 .task_manager()
574 .dom_manipulation_task_source()
575 .queue(task!(sign: move || {
576 let subtle = this.root();
577 let promise = trusted_promise.root();
578 let key = trusted_key.root();
579
580 if normalized_algorithm.name() != key.algorithm().name() {
588 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
589 return;
590 }
591
592 if !key.usages().contains(&KeyUsage::Sign) {
595 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
596 return;
597 }
598
599 let signature = match normalized_algorithm.sign(&key, &data) {
602 Ok(signature) => signature,
603 Err(error) => {
604 subtle.reject_promise_with_error(promise, error);
605 return;
606 },
607 };
608
609 subtle.resolve_promise_with_data(promise, signature.into());
615 }));
616 promise
617 }
618
619 fn Verify(
621 &self,
622 cx: &mut CurrentRealm,
623 algorithm: AlgorithmIdentifier,
624 key: &CryptoKey,
625 signature: ArrayBufferViewOrArrayBuffer,
626 data: ArrayBufferViewOrArrayBuffer,
627 ) -> Rc<Promise> {
628 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
636 Ok(algorithm) => algorithm,
637 Err(error) => {
638 let promise = Promise::new_in_realm(cx);
639 promise.reject_error(error, CanGc::from_cx(cx));
640 return promise;
641 },
642 };
643
644 let signature = match &signature {
647 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
648 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
649 };
650
651 let data = match &data {
654 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
655 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
656 };
657
658 let promise = Promise::new_in_realm(cx);
661
662 let this = Trusted::new(self);
664 let trusted_promise = TrustedPromise::new(promise.clone());
665 let trusted_key = Trusted::new(key);
666 self.global()
667 .task_manager()
668 .dom_manipulation_task_source()
669 .queue(task!(sign: move || {
670 let subtle = this.root();
671 let promise = trusted_promise.root();
672 let key = trusted_key.root();
673
674 if normalized_algorithm.name() != key.algorithm().name() {
682 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
683 return;
684 }
685
686 if !key.usages().contains(&KeyUsage::Verify) {
689 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
690 return;
691 }
692
693 let result = match normalized_algorithm.verify(&key, &data, &signature) {
697 Ok(result) => result,
698 Err(error) => {
699 subtle.reject_promise_with_error(promise, error);
700 return;
701 },
702 };
703
704 subtle.resolve_promise_with_bool(promise, result);
708 }));
709 promise
710 }
711
712 fn Digest(
714 &self,
715 cx: &mut CurrentRealm,
716 algorithm: AlgorithmIdentifier,
717 data: ArrayBufferViewOrArrayBuffer,
718 ) -> Rc<Promise> {
719 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
726 Ok(normalized_algorithm) => normalized_algorithm,
727 Err(error) => {
728 let promise = Promise::new_in_realm(cx);
729 promise.reject_error(error, CanGc::from_cx(cx));
730 return promise;
731 },
732 };
733
734 let data = match data {
737 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
738 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
739 };
740
741 let promise = Promise::new_in_realm(cx);
744
745 let this = Trusted::new(self);
747 let trusted_promise = TrustedPromise::new(promise.clone());
748 self.global()
749 .task_manager()
750 .dom_manipulation_task_source()
751 .queue(task!(digest_: move || {
752 let subtle = this.root();
753 let promise = trusted_promise.root();
754
755 let digest = match normalized_algorithm.digest(&data) {
762 Ok(digest) => digest,
763 Err(error) => {
764 subtle.reject_promise_with_error(promise, error);
765 return;
766 }
767 };
768
769 subtle.resolve_promise_with_data(promise, digest.into());
775 }));
776 promise
777 }
778
779 fn GenerateKey(
781 &self,
782 cx: &mut CurrentRealm,
783 algorithm: AlgorithmIdentifier,
784 extractable: bool,
785 key_usages: Vec<KeyUsage>,
786 ) -> Rc<Promise> {
787 let promise = Promise::new_in_realm(cx);
794 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
795 {
796 Ok(normalized_algorithm) => normalized_algorithm,
797 Err(error) => {
798 promise.reject_error(error, CanGc::from_cx(cx));
799 return promise;
800 },
801 };
802
803 let trusted_subtle = Trusted::new(self);
809 let trusted_promise = TrustedPromise::new(promise.clone());
810 self.global()
811 .task_manager()
812 .dom_manipulation_task_source()
813 .queue(task!(generate_key: move |cx| {
814 let subtle = trusted_subtle.root();
815 let promise = trusted_promise.root();
816
817 let result = match normalized_algorithm.generate_key(
824 cx,
825 &subtle.global(),
826 extractable,
827 key_usages,
828 ) {
829 Ok(result) => result,
830 Err(error) => {
831 subtle.reject_promise_with_error(promise, error);
832 return;
833 }
834 };
835
836 match &result {
844 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
845 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
846 && crpyto_key.usages().is_empty()
847 {
848 subtle.reject_promise_with_error(promise, Error::Syntax(None));
849 return;
850 }
851 },
852 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
853 if crypto_key_pair
854 .privateKey
855 .as_ref()
856 .is_none_or(|private_key| private_key.usages().is_empty())
857 {
858 subtle.reject_promise_with_error(promise, Error::Syntax(None));
859 return;
860 }
861 }
862 };
863
864 match result {
870 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
871 subtle.resolve_promise_with_key(promise, key);
872 },
873 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
874 subtle.resolve_promise_with_key_pair(promise, key_pair);
875 },
876 }
877 }));
878
879 promise
880 }
881
882 fn DeriveKey(
884 &self,
885 cx: &mut CurrentRealm,
886 algorithm: AlgorithmIdentifier,
887 base_key: &CryptoKey,
888 derived_key_type: AlgorithmIdentifier,
889 extractable: bool,
890 usages: Vec<KeyUsage>,
891 ) -> Rc<Promise> {
892 let promise = Promise::new_in_realm(cx);
901 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
902 {
903 Ok(normalized_algorithm) => normalized_algorithm,
904 Err(error) => {
905 promise.reject_error(error, CanGc::from_cx(cx));
906 return promise;
907 },
908 };
909
910 let normalized_derived_key_algorithm_import =
915 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
916 Ok(normalized_algorithm) => normalized_algorithm,
917 Err(error) => {
918 promise.reject_error(error, CanGc::from_cx(cx));
919 return promise;
920 },
921 };
922
923 let normalized_derived_key_algorithm_length =
928 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
929 Ok(normalized_algorithm) => normalized_algorithm,
930 Err(error) => {
931 promise.reject_error(error, CanGc::from_cx(cx));
932 return promise;
933 },
934 };
935
936 let trusted_subtle = Trusted::new(self);
942 let trusted_base_key = Trusted::new(base_key);
943 let trusted_promise = TrustedPromise::new(promise.clone());
944 self.global().task_manager().dom_manipulation_task_source().queue(
945 task!(derive_key: move |cx| {
946 let subtle = trusted_subtle.root();
947 let base_key = trusted_base_key.root();
948 let promise = trusted_promise.root();
949
950 if normalized_algorithm.name() != base_key.algorithm().name() {
958 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
959 return;
960 }
961
962 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
965 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
966 return;
967 }
968
969 let length = match normalized_derived_key_algorithm_length.get_key_length() {
972 Ok(length) => length,
973 Err(error) => {
974 subtle.reject_promise_with_error(promise, error);
975 return;
976 }
977 };
978
979 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
982 Ok(secret) => Zeroizing::new(secret),
983 Err(error) => {
984 subtle.reject_promise_with_error(promise, error);
985 return;
986 }
987 };
988
989 let result = match normalized_derived_key_algorithm_import.import_key(
995 cx,
996 &subtle.global(),
997 KeyFormat::Raw_secret,
998 &secret,
999 extractable,
1000 usages.clone(),
1001 ) {
1002 Ok(algorithm) => algorithm,
1003 Err(error) => {
1004 subtle.reject_promise_with_error(promise, error);
1005 return;
1006 },
1007 };
1008
1009 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1012 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1013 return;
1014 }
1015
1016 subtle.resolve_promise_with_key(promise, result);
1027 }),
1028 );
1029 promise
1030 }
1031
1032 fn DeriveBits(
1034 &self,
1035 cx: &mut CurrentRealm,
1036 algorithm: AlgorithmIdentifier,
1037 base_key: &CryptoKey,
1038 length: Option<u32>,
1039 ) -> Rc<Promise> {
1040 let promise = Promise::new_in_realm(cx);
1048 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1049 {
1050 Ok(normalized_algorithm) => normalized_algorithm,
1051 Err(error) => {
1052 promise.reject_error(error, CanGc::from_cx(cx));
1053 return promise;
1054 },
1055 };
1056
1057 let trsuted_subtle = Trusted::new(self);
1063 let trusted_base_key = Trusted::new(base_key);
1064 let trusted_promise = TrustedPromise::new(promise.clone());
1065 self.global()
1066 .task_manager()
1067 .dom_manipulation_task_source()
1068 .queue(task!(import_key: move || {
1069 let subtle = trsuted_subtle.root();
1070 let base_key = trusted_base_key.root();
1071 let promise = trusted_promise.root();
1072
1073 if normalized_algorithm.name() != base_key.algorithm().name() {
1081 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1082 return;
1083 }
1084
1085 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1088 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1089 return;
1090 }
1091
1092 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1095 Ok(bits) => Zeroizing::new(bits),
1096 Err(error) => {
1097 subtle.reject_promise_with_error(promise, error);
1098 return;
1099 }
1100 };
1101
1102 subtle.resolve_promise_with_data(promise, bits);
1108 }));
1109 promise
1110 }
1111
1112 fn ImportKey(
1114 &self,
1115 cx: &mut CurrentRealm,
1116 format: KeyFormat,
1117 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1118 algorithm: AlgorithmIdentifier,
1119 extractable: bool,
1120 key_usages: Vec<KeyUsage>,
1121 ) -> Rc<Promise> {
1122 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1129 Ok(algorithm) => algorithm,
1130 Err(error) => {
1131 let promise = Promise::new_in_realm(cx);
1132 promise.reject_error(error, CanGc::from_cx(cx));
1133 return promise;
1134 },
1135 };
1136
1137 let key_data = match format {
1139 KeyFormat::Jwk => {
1141 match key_data {
1142 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1143 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1144 let promise = Promise::new_in_realm(cx);
1147 promise.reject_error(
1148 Error::Type(c"The keyData type does not match the format".to_owned()),
1149 CanGc::from_cx(cx),
1150 );
1151 return promise;
1152 },
1153
1154 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1155 match jwk.stringify(cx) {
1163 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1164 Err(error) => {
1165 let promise = Promise::new_in_realm(cx);
1166 promise.reject_error(error, CanGc::from_cx(cx));
1167 return promise;
1168 },
1169 }
1170 },
1171 }
1172 },
1173 _ => {
1175 match key_data {
1176 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1179 let promise = Promise::new_in_realm(cx);
1180 promise.reject_error(
1181 Error::Type(c"The keyData type does not match the format".to_owned()),
1182 CanGc::from_cx(cx),
1183 );
1184 return promise;
1185 },
1186
1187 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1190 Zeroizing::new(view.to_vec())
1191 },
1192 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1193 Zeroizing::new(buffer.to_vec())
1194 },
1195 }
1196 },
1197 };
1198
1199 let promise = Promise::new_in_realm(cx);
1202
1203 let this = Trusted::new(self);
1205 let trusted_promise = TrustedPromise::new(promise.clone());
1206 self.global()
1207 .task_manager()
1208 .dom_manipulation_task_source()
1209 .queue(task!(import_key: move |cx| {
1210 let subtle = this.root();
1211 let promise = trusted_promise.root();
1212
1213 let result = match normalized_algorithm.import_key(
1221 cx,
1222 &subtle.global(),
1223 format,
1224 &key_data,
1225 extractable,
1226 key_usages.clone(),
1227 ) {
1228 Ok(key) => key,
1229 Err(error) => {
1230 subtle.reject_promise_with_error(promise, error);
1231 return;
1232 },
1233 };
1234
1235 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1238 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1239 return;
1240 }
1241
1242 result.set_extractable(extractable);
1244
1245 result.set_usages(cx, &key_usages);
1247
1248 subtle.resolve_promise_with_key(promise, result);
1254 }));
1255
1256 promise
1257 }
1258
1259 fn ExportKey(&self, cx: &mut CurrentRealm, format: KeyFormat, key: &CryptoKey) -> Rc<Promise> {
1261 let promise = Promise::new_in_realm(cx);
1268
1269 let trusted_subtle = Trusted::new(self);
1271 let trusted_promise = TrustedPromise::new(promise.clone());
1272 let trusted_key = Trusted::new(key);
1273 self.global()
1274 .task_manager()
1275 .dom_manipulation_task_source()
1276 .queue(task!(export_key: move |cx| {
1277 let subtle = trusted_subtle.root();
1278 let promise = trusted_promise.root();
1279 let key = trusted_key.root();
1280
1281 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1292 cx,
1293 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1294 ) {
1295 Ok(normalized_algorithm) => normalized_algorithm,
1296 Err(error) => {
1297 subtle.reject_promise_with_error(promise, error);
1298 return;
1299 },
1300 };
1301
1302 if !key.Extractable() {
1305 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1306 return;
1307 }
1308
1309 let result = match export_key_algorithm.export_key(format, &key) {
1312 Ok(exported_key) => exported_key,
1313 Err(error) => {
1314 subtle.reject_promise_with_error(promise, error);
1315 return;
1316 },
1317 };
1318
1319 match result {
1332 ExportedKey::Bytes(bytes) => {
1333 subtle.resolve_promise_with_data(promise, bytes);
1334 },
1335 ExportedKey::Jwk(jwk) => {
1336 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1337 },
1338 }
1339 }));
1340 promise
1341 }
1342
1343 fn WrapKey(
1345 &self,
1346 cx: &mut CurrentRealm,
1347 format: KeyFormat,
1348 key: &CryptoKey,
1349 wrapping_key: &CryptoKey,
1350 algorithm: AlgorithmIdentifier,
1351 ) -> Rc<Promise> {
1352 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1362 WrapKeyAlgorithm(WrapKeyAlgorithm),
1363 EncryptAlgorithm(EncryptAlgorithm),
1364 }
1365 let normalized_algorithm = if let Ok(algorithm) =
1366 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1367 {
1368 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1369 } else {
1370 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1371 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1372 Err(error) => {
1373 let promise = Promise::new_in_realm(cx);
1374 promise.reject_error(error, CanGc::from_cx(cx));
1375 return promise;
1376 },
1377 }
1378 };
1379
1380 let promise = Promise::new_in_realm(cx);
1383
1384 let trusted_subtle = Trusted::new(self);
1386 let trusted_key = Trusted::new(key);
1387 let trusted_wrapping_key = Trusted::new(wrapping_key);
1388 let trusted_promise = TrustedPromise::new(promise.clone());
1389 self.global()
1390 .task_manager()
1391 .dom_manipulation_task_source()
1392 .queue(task!(wrap_key: move |cx| {
1393 let subtle = trusted_subtle.root();
1394 let key = trusted_key.root();
1395 let wrapping_key = trusted_wrapping_key.root();
1396 let promise = trusted_promise.root();
1397
1398 let normalized_algorithm_name = match &normalized_algorithm {
1406 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1407 algorithm.name()
1408 },
1409 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1410 algorithm.name()
1411 },
1412 };
1413 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1414 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1415 return;
1416 }
1417
1418 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1421 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1422 return;
1423 }
1424
1425 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1431 cx,
1432 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1433 ) {
1434 Ok(normalized_algorithm) => normalized_algorithm,
1435 Err(error) => {
1436 subtle.reject_promise_with_error(promise, error);
1437 return;
1438 },
1439 };
1440
1441 if !key.Extractable() {
1444 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1445 return;
1446 }
1447
1448 let exported_key = match export_key_algorithm.export_key(format, &key) {
1451 Ok(exported_key) => exported_key,
1452 Err(error) => {
1453 subtle.reject_promise_with_error(promise, error);
1454 return;
1455 },
1456 };
1457
1458 let bytes = match exported_key {
1470 ExportedKey::Bytes(bytes) => bytes,
1471 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1472 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.as_bytes().to_vec()),
1473 Err(error) => {
1474 subtle.reject_promise_with_error(promise, error);
1475 return;
1476 },
1477 },
1478 };
1479
1480 let result = match normalized_algorithm {
1492 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1493 algorithm.wrap_key(&wrapping_key, &bytes)
1494 },
1495 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1496 algorithm.encrypt(&wrapping_key, &bytes)
1497 },
1498 };
1499 let result = match result {
1500 Ok(result) => result,
1501 Err(error) => {
1502 subtle.reject_promise_with_error(promise, error);
1503 return;
1504 },
1505 };
1506
1507 subtle.resolve_promise_with_data(promise, result.into());
1513 }));
1514 promise
1515 }
1516
1517 fn UnwrapKey(
1519 &self,
1520 cx: &mut CurrentRealm,
1521 format: KeyFormat,
1522 wrapped_key: ArrayBufferViewOrArrayBuffer,
1523 unwrapping_key: &CryptoKey,
1524 algorithm: AlgorithmIdentifier,
1525 unwrapped_key_algorithm: AlgorithmIdentifier,
1526 extractable: bool,
1527 usages: Vec<KeyUsage>,
1528 ) -> Rc<Promise> {
1529 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1540 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1541 DecryptAlgorithm(DecryptAlgorithm),
1542 }
1543 let normalized_algorithm = if let Ok(algorithm) =
1544 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1545 {
1546 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1547 } else {
1548 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1549 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1550 Err(error) => {
1551 let promise = Promise::new_in_realm(cx);
1552 promise.reject_error(error, CanGc::from_cx(cx));
1553 return promise;
1554 },
1555 }
1556 };
1557
1558 let normalized_key_algorithm =
1562 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1563 Ok(algorithm) => algorithm,
1564 Err(error) => {
1565 let promise = Promise::new_in_realm(cx);
1566 promise.reject_error(error, CanGc::from_cx(cx));
1567 return promise;
1568 },
1569 };
1570
1571 let wrapped_key = match wrapped_key {
1574 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1575 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1576 };
1577
1578 let promise = Promise::new_in_realm(cx);
1581
1582 let trusted_subtle = Trusted::new(self);
1584 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1585 let trusted_promise = TrustedPromise::new(promise.clone());
1586 self.global().task_manager().dom_manipulation_task_source().queue(
1587 task!(unwrap_key: move |cx| {
1588 let subtle = trusted_subtle.root();
1589 let unwrapping_key = trusted_unwrapping_key.root();
1590 let promise = trusted_promise.root();
1591
1592 let normalized_algorithm_name = match &normalized_algorithm {
1600 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1601 algorithm.name()
1602 },
1603 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1604 algorithm.name()
1605 },
1606 };
1607 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1608 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1609 return;
1610 }
1611
1612 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1615 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1616 return;
1617 }
1618
1619 let bytes = match normalized_algorithm {
1631 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1632 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1633 },
1634 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1635 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1636 },
1637 };
1638 let bytes = match bytes {
1639 Ok(bytes) => Zeroizing::new(bytes),
1640 Err(error) => {
1641 subtle.reject_promise_with_error(promise, error);
1642 return;
1643 },
1644 };
1645
1646 if format == KeyFormat::Jwk
1657 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1658 subtle.reject_promise_with_error(promise, error);
1659 return;
1660 }
1661 let key = bytes;
1662
1663 let result = match normalized_key_algorithm.import_key(
1667 cx,
1668 &subtle.global(),
1669 format,
1670 &key,
1671 extractable,
1672 usages.clone(),
1673 ) {
1674 Ok(result) => result,
1675 Err(error) => {
1676 subtle.reject_promise_with_error(promise, error);
1677 return;
1678 },
1679 };
1680
1681 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1684 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1685 return;
1686 }
1687
1688 subtle.resolve_promise_with_key(promise, result);
1699 }),
1700 );
1701 promise
1702 }
1703
1704 fn EncapsulateKey(
1706 &self,
1707 cx: &mut CurrentRealm,
1708 encapsulation_algorithm: AlgorithmIdentifier,
1709 encapsulation_key: &CryptoKey,
1710 shared_key_algorithm: AlgorithmIdentifier,
1711 extractable: bool,
1712 usages: Vec<KeyUsage>,
1713 ) -> Rc<Promise> {
1714 let promise = Promise::new_in_realm(cx);
1724 let normalized_encapsulation_algorithm =
1725 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1726 Ok(algorithm) => algorithm,
1727 Err(error) => {
1728 promise.reject_error(error, CanGc::from_cx(cx));
1729 return promise;
1730 },
1731 };
1732
1733 let normalized_shared_key_algorithm =
1738 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1739 Ok(algorithm) => algorithm,
1740 Err(error) => {
1741 promise.reject_error(error, CanGc::from_cx(cx));
1742 return promise;
1743 },
1744 };
1745
1746 let trusted_subtle = Trusted::new(self);
1752 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1753 let trusted_promise = TrustedPromise::new(promise.clone());
1754 self.global().task_manager().dom_manipulation_task_source().queue(
1755 task!(encapsulate_keys: move |cx| {
1756 let subtle = trusted_subtle.root();
1757 let encapsulation_key = trusted_encapsulated_key.root();
1758 let promise = trusted_promise.root();
1759
1760 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1768 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1769 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1770 normalizedEncapsulationAlgorithm".to_string(),
1771 )));
1772 return;
1773 }
1774
1775 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1778 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1779 "[[usages]] internal slot of encapsulationKey does not contain an \
1780 entry that is \"encapsulateBits\"".to_string(),
1781 )));
1782 return;
1783 }
1784
1785 let encapsulated_bits_result =
1791 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1792 let encapsulated_bits = match encapsulated_bits_result {
1793 Ok(encapsulated_bits) => encapsulated_bits,
1794 Err(error) => {
1795 subtle.reject_promise_with_error(promise, error);
1796 return;
1797 },
1798 };
1799
1800 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1808 Some(shared_key) => shared_key,
1809 None => {
1810 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1811 "Shared key is missing in the result of the encapsulate operation"
1812 .to_string())));
1813 return;
1814 },
1815 };
1816 let shared_key_result = normalized_shared_key_algorithm.import_key(
1817 cx,
1818 &subtle.global(),
1819 KeyFormat::Raw_secret,
1820 encapsulated_shared_key,
1821 extractable,
1822 usages.clone(),
1823 );
1824 let shared_key = match shared_key_result {
1825 Ok(shared_key) => shared_key,
1826 Err(error) => {
1827 subtle.reject_promise_with_error(promise, error);
1828 return;
1829 },
1830 };
1831
1832 let encapsulated_key = SubtleEncapsulatedKey {
1835 shared_key: Some(Trusted::new(&shared_key)),
1836 ciphertext:encapsulated_bits.ciphertext,
1837 };
1838
1839 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1845 })
1846 );
1847 promise
1848 }
1849
1850 fn EncapsulateBits(
1852 &self,
1853 cx: &mut CurrentRealm,
1854 encapsulation_algorithm: AlgorithmIdentifier,
1855 encapsulation_key: &CryptoKey,
1856 ) -> Rc<Promise> {
1857 let promise = Promise::new_in_realm(cx);
1865 let normalized_encapsulation_algorithm =
1866 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1867 Ok(algorithm) => algorithm,
1868 Err(error) => {
1869 promise.reject_error(error, CanGc::from_cx(cx));
1870 return promise;
1871 },
1872 };
1873
1874 let trusted_subtle = Trusted::new(self);
1880 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1881 let trusted_promise = TrustedPromise::new(promise.clone());
1882 self.global().task_manager().dom_manipulation_task_source().queue(
1883 task!(derive_key: move || {
1884 let subtle = trusted_subtle.root();
1885 let encapsulation_key = trusted_encapsulation_key.root();
1886 let promise = trusted_promise.root();
1887
1888 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1896 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1897 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1898 normalizedEncapsulationAlgorithm".to_string(),
1899 )));
1900 return;
1901 }
1902
1903 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1906 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1907 "[[usages]] internal slot of encapsulationKey does not contain an \
1908 entry that is \"encapsulateBits\"".to_string(),
1909 )));
1910 return;
1911 }
1912
1913 let encapsulated_bits =
1919 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1920 Ok(encapsulated_bits) => encapsulated_bits,
1921 Err(error) => {
1922 subtle.reject_promise_with_error(promise, error);
1923 return;
1924 },
1925 };
1926
1927 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1933 }),
1934 );
1935 promise
1936 }
1937
1938 fn DecapsulateKey(
1940 &self,
1941 cx: &mut CurrentRealm,
1942 decapsulation_algorithm: AlgorithmIdentifier,
1943 decapsulation_key: &CryptoKey,
1944 ciphertext: ArrayBufferViewOrArrayBuffer,
1945 shared_key_algorithm: AlgorithmIdentifier,
1946 extractable: bool,
1947 usages: Vec<KeyUsage>,
1948 ) -> Rc<Promise> {
1949 let normalized_decapsulation_algorithm =
1959 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
1960 Ok(normalized_algorithm) => normalized_algorithm,
1961 Err(error) => {
1962 let promise = Promise::new_in_realm(cx);
1963 promise.reject_error(error, CanGc::from_cx(cx));
1964 return promise;
1965 },
1966 };
1967
1968 let normalized_shared_key_algorithm =
1973 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1974 Ok(normalized_algorithm) => normalized_algorithm,
1975 Err(error) => {
1976 let promise = Promise::new_in_realm(cx);
1977 promise.reject_error(error, CanGc::from_cx(cx));
1978 return promise;
1979 },
1980 };
1981
1982 let ciphertext = match ciphertext {
1985 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1986 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1987 };
1988
1989 let promise = Promise::new_in_realm(cx);
1992
1993 let trusted_subtle = Trusted::new(self);
1995 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
1996 let trusted_promise = TrustedPromise::new(promise.clone());
1997 self.global()
1998 .task_manager()
1999 .dom_manipulation_task_source()
2000 .queue(task!(decapsulate_key: move |cx| {
2001 let subtle = trusted_subtle.root();
2002 let promise = trusted_promise.root();
2003 let decapsulation_key = trusted_decapsulation_key.root();
2004
2005 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2013 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2014 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2015 normalizedDecapsulationAlgorithm".to_string()
2016 )));
2017 return;
2018 }
2019
2020 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2023 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2024 "[[usages]] internal slot of decapsulationKey does not contain an \
2025 entry that is \"decapsulateBits\"".to_string(),
2026 )));
2027 return;
2028 }
2029
2030 let decapsulated_bits_result =
2036 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2037 let decapsulated_bits = match decapsulated_bits_result {
2038 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2039 Err(error) => {
2040 subtle.reject_promise_with_error(promise, error);
2041 return;
2042 },
2043 };
2044
2045
2046 let shared_key_result = normalized_shared_key_algorithm.import_key(
2054 cx,
2055 &subtle.global(),
2056 KeyFormat::Raw_secret,
2057 &decapsulated_bits,
2058 extractable,
2059 usages.clone(),
2060 );
2061 let shared_key = match shared_key_result {
2062 Ok(shared_key) => shared_key,
2063 Err(error) => {
2064 subtle.reject_promise_with_error(promise, error);
2065 return;
2066 },
2067 };
2068
2069
2070 subtle.resolve_promise_with_key(promise, shared_key);
2076 }));
2077 promise
2078 }
2079
2080 fn DecapsulateBits(
2082 &self,
2083 cx: &mut CurrentRealm,
2084 decapsulation_algorithm: AlgorithmIdentifier,
2085 decapsulation_key: &CryptoKey,
2086 ciphertext: ArrayBufferViewOrArrayBuffer,
2087 ) -> Rc<Promise> {
2088 let normalized_decapsulation_algorithm =
2096 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2097 Ok(normalized_algorithm) => normalized_algorithm,
2098 Err(error) => {
2099 let promise = Promise::new_in_realm(cx);
2100 promise.reject_error(error, CanGc::from_cx(cx));
2101 return promise;
2102 },
2103 };
2104
2105 let ciphertext = match ciphertext {
2108 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2109 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2110 };
2111
2112 let promise = Promise::new_in_realm(cx);
2115
2116 let trusted_subtle = Trusted::new(self);
2118 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2119 let trusted_promise = TrustedPromise::new(promise.clone());
2120 self.global()
2121 .task_manager()
2122 .dom_manipulation_task_source()
2123 .queue(task!(decapsulate_bits: move || {
2124 let subtle = trusted_subtle.root();
2125 let promise = trusted_promise.root();
2126 let decapsulation_key = trusted_decapsulation_key.root();
2127
2128 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2136 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2137 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2138 normalizedDecapsulationAlgorithm".to_string()
2139 )));
2140 return;
2141 }
2142
2143 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2146 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2147 "[[usages]] internal slot of decapsulationKey does not contain an \
2148 entry that is \"decapsulateBits\"".to_string(),
2149 )));
2150 return;
2151 }
2152
2153 let decapsulated_bits_result =
2159 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2160 let decapsulated_bits = match decapsulated_bits_result {
2161 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2162 Err(error) => {
2163 subtle.reject_promise_with_error(promise, error);
2164 return;
2165 },
2166 };
2167
2168 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2174 }));
2175 promise
2176 }
2177
2178 fn GetPublicKey(
2180 &self,
2181 cx: &mut CurrentRealm,
2182 key: &CryptoKey,
2183 usages: Vec<KeyUsage>,
2184 ) -> Rc<Promise> {
2185 let algorithm = key.algorithm();
2190
2191 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2198 cx,
2199 &AlgorithmIdentifier::String(DOMString::from(algorithm.name().as_str())),
2200 ) {
2201 Ok(normalized_algorithm) => normalized_algorithm,
2202 Err(error) => {
2203 let promise = Promise::new_in_realm(cx);
2204 promise.reject_error(error, CanGc::from_cx(cx));
2205 return promise;
2206 },
2207 };
2208
2209 let promise = Promise::new_in_realm(cx);
2212
2213 let trusted_subtle = Trusted::new(self);
2215 let trusted_promise = TrustedPromise::new(promise.clone());
2216 let trusted_key = Trusted::new(key);
2217 self.global()
2218 .task_manager()
2219 .dom_manipulation_task_source()
2220 .queue(task!(get_public_key: move |cx| {
2221 let subtle = trusted_subtle.root();
2222 let promise = trusted_promise.root();
2223 let key = trusted_key.root();
2224
2225 if key.Type() != KeyType::Private {
2232 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2233 "[[type]] internal slot of key is not \"private\"".to_string()
2234 )));
2235 return;
2236 }
2237
2238 let result = match get_public_key_algorithm.get_public_key(
2252 cx,
2253 &subtle.global(),
2254 &key,
2255 key.algorithm(),
2256 usages.clone(),
2257 ) {
2258 Ok(public_key) => public_key,
2259 Err(error) => {
2260 subtle.reject_promise_with_error(promise, error);
2261 return;
2262 },
2263 };
2264
2265 subtle.resolve_promise_with_key(promise, result);
2271 }));
2272 promise
2273 }
2274
2275 fn Supports(
2277 cx: &mut js::context::JSContext,
2278 _global: &GlobalScope,
2279 operation: DOMString,
2280 algorithm: AlgorithmIdentifier,
2281 length: Option<u32>,
2282 ) -> bool {
2283 let operation = &*operation.str();
2288 if !matches!(
2289 operation,
2290 "encrypt" |
2291 "decrypt" |
2292 "sign" |
2293 "verify" |
2294 "digest" |
2295 "generateKey" |
2296 "deriveKey" |
2297 "deriveBits" |
2298 "importKey" |
2299 "exportKey" |
2300 "wrapKey" |
2301 "unwrapKey" |
2302 "encapsulateKey" |
2303 "encapsulateBits" |
2304 "decapsulateKey" |
2305 "decapsulateBits" |
2306 "getPublicKey"
2307 ) {
2308 return false;
2309 }
2310
2311 check_support_for_algorithm(cx, operation, &algorithm, length)
2314 }
2315
2316 fn Supports_(
2318 cx: &mut js::context::JSContext,
2319 _global: &GlobalScope,
2320 operation: DOMString,
2321 algorithm: AlgorithmIdentifier,
2322 additional_algorithm: AlgorithmIdentifier,
2323 ) -> bool {
2324 let mut operation = &*operation.str();
2329 if !matches!(
2330 operation,
2331 "encrypt" |
2332 "decrypt" |
2333 "sign" |
2334 "verify" |
2335 "digest" |
2336 "generateKey" |
2337 "deriveKey" |
2338 "deriveBits" |
2339 "importKey" |
2340 "exportKey" |
2341 "wrapKey" |
2342 "unwrapKey" |
2343 "encapsulateKey" |
2344 "encapsulateBits" |
2345 "decapsulateKey" |
2346 "decapsulateBits" |
2347 "getPublicKey"
2348 ) {
2349 return false;
2350 }
2351
2352 if matches!(
2360 operation,
2361 "deriveKey" | "unwrapKey" | "encapsulateKey" | "decapsulateKey"
2362 ) && !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2363 {
2364 return false;
2365 }
2366 if operation == "wrapKey" &&
2367 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2368 {
2369 return false;
2370 }
2371
2372 let mut length = None;
2374
2375 if operation == "deriveKey" {
2377 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2380 return false;
2381 }
2382
2383 let Ok(normalized_additional_algorithm) =
2386 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2387 else {
2388 return false;
2389 };
2390
2391 match normalized_additional_algorithm.get_key_length() {
2394 Ok(key_length) => {
2395 length = key_length;
2396 },
2397 Err(_) => return false,
2398 };
2399
2400 operation = "deriveBits";
2402 }
2403
2404 check_support_for_algorithm(cx, operation, &algorithm, length)
2407 }
2408}
2409
2410pub(crate) fn check_support_for_algorithm(
2412 cx: &mut js::context::JSContext,
2413 mut operation: &str,
2414 algorithm: &AlgorithmIdentifier,
2415 length: Option<u32>,
2416) -> bool {
2417 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2419 operation = "encapsulate";
2420 }
2421
2422 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2424 operation = "decapsulate";
2425 }
2426
2427 if operation == "getPublicKey" {
2429 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2433 else {
2434 return false;
2435 };
2436
2437 return normalize_algorithm::<GetPublicKeyOperation>(
2444 cx,
2445 &AlgorithmIdentifier::String(DOMString::from(normalized_algorithm.name().as_str())),
2446 )
2447 .is_ok();
2448 }
2449
2450 match operation {
2489 "encrypt" => {
2490 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2491 else {
2492 return false;
2493 };
2494
2495 match normalized_algorithm {
2496 EncryptAlgorithm::RsaOaep(_) => true,
2497 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2498 normalized_algorithm.counter.len() == 16 &&
2499 normalized_algorithm.length != 0 &&
2500 normalized_algorithm.length <= 128
2501 },
2502 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2503 normalized_algorithm.iv.len() == 16
2504 },
2505 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2506 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2507 normalized_algorithm.tag_length.is_none_or(|length| {
2508 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2509 })
2510 },
2511 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2512 normalized_algorithm.iv.len() <= 15 &&
2513 normalized_algorithm
2514 .tag_length
2515 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2516 },
2517 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2518 normalized_algorithm.iv.len() == 12 &&
2519 normalized_algorithm
2520 .tag_length
2521 .is_none_or(|length| length == 128)
2522 },
2523 }
2524 },
2525 "decrypt" => {
2526 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2527 else {
2528 return false;
2529 };
2530
2531 match normalized_algorithm {
2532 DecryptAlgorithm::RsaOaep(_) => true,
2533 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2534 normalized_algorithm.counter.len() == 16 &&
2535 normalized_algorithm.length != 0 &&
2536 normalized_algorithm.length <= 128
2537 },
2538 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2539 normalized_algorithm.iv.len() == 16
2540 },
2541 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2542 normalized_algorithm
2543 .tag_length
2544 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2545 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2546 normalized_algorithm
2547 .additional_data
2548 .is_none_or(|data| data.len() <= u32::MAX as usize)
2549 },
2550 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2551 normalized_algorithm.iv.len() <= 15 &&
2552 normalized_algorithm
2553 .tag_length
2554 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2555 },
2556 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2557 normalized_algorithm.iv.len() == 12 &&
2558 normalized_algorithm
2559 .tag_length
2560 .is_none_or(|length| length == 128)
2561 },
2562 }
2563 },
2564 "sign" => {
2565 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2566 else {
2567 return false;
2568 };
2569
2570 match normalized_algorithm {
2571 SignAlgorithm::RsassaPkcs1V1_5(_) |
2572 SignAlgorithm::RsaPss(_) |
2573 SignAlgorithm::Ecdsa(_) |
2574 SignAlgorithm::Ed25519(_) |
2575 SignAlgorithm::Hmac(_) |
2576 SignAlgorithm::MlDsa(_) => true,
2577 }
2578 },
2579 "verify" => {
2580 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2581 else {
2582 return false;
2583 };
2584
2585 match normalized_algorithm {
2586 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2587 VerifyAlgorithm::RsaPss(_) |
2588 VerifyAlgorithm::Ecdsa(_) |
2589 VerifyAlgorithm::Ed25519(_) |
2590 VerifyAlgorithm::Hmac(_) |
2591 VerifyAlgorithm::MlDsa(_) => true,
2592 }
2593 },
2594 "digest" => {
2595 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2596 else {
2597 return false;
2598 };
2599
2600 match normalized_algorithm {
2601 DigestAlgorithm::Sha(_) |
2602 DigestAlgorithm::Sha3(_) |
2603 DigestAlgorithm::CShake(_) |
2604 DigestAlgorithm::TurboShake(_) => true,
2605 }
2606 },
2607 "deriveBits" => {
2608 let Ok(normalized_algorithm) =
2609 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2610 else {
2611 return false;
2612 };
2613
2614 match normalized_algorithm {
2615 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => length.is_none_or(|length| {
2616 ecdh_operation::secret_length(&normalized_algorithm)
2617 .is_ok_and(|secret_length| secret_length * 8 >= length)
2618 }),
2619 DeriveBitsAlgorithm::X25519(_) => {
2620 length.is_none_or(|length| x25519_operation::SECRET_LENGTH as u32 * 8 >= length)
2621 },
2622 DeriveBitsAlgorithm::Hkdf(_) => length.is_some_and(|length| length % 8 == 0),
2623 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2624 length.is_some_and(|length| length % 8 == 0) &&
2625 normalized_algorithm.iterations != 0
2626 },
2627 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2628 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2629 normalized_algorithm
2630 .version
2631 .is_none_or(|version| version == 19) &&
2632 normalized_algorithm.parallelism != 0 &&
2633 normalized_algorithm.parallelism <= 16777215 &&
2634 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2635 normalized_algorithm.passes != 0
2636 },
2637 }
2638 },
2639 "wrapKey" => {
2640 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2641 else {
2642 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2643 };
2644
2645 match normalized_algorithm {
2646 WrapKeyAlgorithm::AesKw(_) => true,
2647 }
2648 },
2649 "unwrapKey" => {
2650 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2651 else {
2652 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2653 };
2654
2655 match normalized_algorithm {
2656 UnwrapKeyAlgorithm::AesKw(_) => true,
2657 }
2658 },
2659 "generateKey" => {
2660 let Ok(normalized_algorithm) =
2661 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2662 else {
2663 return false;
2664 };
2665
2666 match normalized_algorithm {
2667 GenerateKeyAlgorithm::RsassaPkcs1V1_5(_) |
2668 GenerateKeyAlgorithm::RsaPss(_) |
2669 GenerateKeyAlgorithm::RsaOaep(_) => true,
2670 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2671 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2672 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2673 },
2674 GenerateKeyAlgorithm::Ed25519(_) | GenerateKeyAlgorithm::X25519(_) => true,
2675 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2676 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2677 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2678 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2679 matches!(normalized_algorithm.length, 128 | 192 | 256)
2680 },
2681 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2682 normalized_algorithm.length.is_none_or(|length| length != 0)
2683 },
2684 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2685 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2686 matches!(normalized_algorithm.length, 128 | 192 | 256)
2687 },
2688 GenerateKeyAlgorithm::ChaCha20Poly1305(_) => true,
2689 }
2690 },
2691 "importKey" => {
2692 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2693 else {
2694 return false;
2695 };
2696
2697 match normalized_algorithm {
2698 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2699 ImportKeyAlgorithm::RsaPss(_) |
2700 ImportKeyAlgorithm::RsaOaep(_) |
2701 ImportKeyAlgorithm::Ecdsa(_) |
2702 ImportKeyAlgorithm::Ecdh(_) |
2703 ImportKeyAlgorithm::Ed25519(_) |
2704 ImportKeyAlgorithm::X25519(_) |
2705 ImportKeyAlgorithm::AesCtr(_) |
2706 ImportKeyAlgorithm::AesCbc(_) |
2707 ImportKeyAlgorithm::AesGcm(_) |
2708 ImportKeyAlgorithm::AesKw(_) |
2709 ImportKeyAlgorithm::Hmac(_) |
2710 ImportKeyAlgorithm::Hkdf(_) |
2711 ImportKeyAlgorithm::Pbkdf2(_) |
2712 ImportKeyAlgorithm::MlKem(_) |
2713 ImportKeyAlgorithm::MlDsa(_) |
2714 ImportKeyAlgorithm::AesOcb(_) |
2715 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2716 ImportKeyAlgorithm::Argon2(_) => true,
2717 }
2718 },
2719 "exportKey" => {
2720 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2721 else {
2722 return false;
2723 };
2724
2725 match normalized_algorithm {
2726 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2727 ExportKeyAlgorithm::RsaPss(_) |
2728 ExportKeyAlgorithm::RsaOaep(_) |
2729 ExportKeyAlgorithm::Ecdsa(_) |
2730 ExportKeyAlgorithm::Ecdh(_) |
2731 ExportKeyAlgorithm::Ed25519(_) |
2732 ExportKeyAlgorithm::X25519(_) |
2733 ExportKeyAlgorithm::AesCtr(_) |
2734 ExportKeyAlgorithm::AesCbc(_) |
2735 ExportKeyAlgorithm::AesGcm(_) |
2736 ExportKeyAlgorithm::AesKw(_) |
2737 ExportKeyAlgorithm::Hmac(_) |
2738 ExportKeyAlgorithm::MlKem(_) |
2739 ExportKeyAlgorithm::MlDsa(_) |
2740 ExportKeyAlgorithm::AesOcb(_) |
2741 ExportKeyAlgorithm::ChaCha20Poly1305(_) => true,
2742 }
2743 },
2744 "get key length" => {
2745 let Ok(normalized_algorithm) =
2746 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2747 else {
2748 return false;
2749 };
2750
2751 match normalized_algorithm {
2752 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2753 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2754 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2755 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2756 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2757 },
2758 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2759 normalized_derived_key_algorithm
2760 .length
2761 .is_none_or(|length| length != 0)
2762 },
2763 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2764 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2765 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2766 },
2767 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) | GetKeyLengthAlgorithm::Argon2(_) => {
2768 true
2769 },
2770 }
2771 },
2772 "encapsulate" => {
2773 let Ok(normalized_algorithm) =
2774 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2775 else {
2776 return false;
2777 };
2778
2779 match normalized_algorithm {
2780 EncapsulateAlgorithm::MlKem(_) => true,
2781 }
2782 },
2783 "decapsulate" => {
2784 let Ok(normalized_algorithm) =
2785 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2786 else {
2787 return false;
2788 };
2789
2790 match normalized_algorithm {
2791 DecapsulateAlgorithm::MlKem(_) => true,
2792 }
2793 },
2794 _ => false,
2795 }
2796
2797 }
2801
2802trait TryFromWithCxAndName<T>: Sized {
2804 type Error;
2805
2806 fn try_from_with_cx_and_name(
2807 value: T,
2808 cx: &mut js::context::JSContext,
2809 algorithm_name: CryptoAlgorithm,
2810 ) -> Result<Self, Self::Error>;
2811}
2812
2813trait TryIntoWithCxAndName<T>: Sized {
2815 type Error;
2816
2817 fn try_into_with_cx_and_name(
2818 self,
2819 cx: &mut js::context::JSContext,
2820 algorithm_name: CryptoAlgorithm,
2821 ) -> Result<T, Self::Error>;
2822}
2823
2824impl<T, U> TryIntoWithCxAndName<U> for T
2825where
2826 U: TryFromWithCxAndName<T>,
2827{
2828 type Error = U::Error;
2829
2830 fn try_into_with_cx_and_name(
2831 self,
2832 cx: &mut js::context::JSContext,
2833 algorithm_name: CryptoAlgorithm,
2834 ) -> Result<U, Self::Error> {
2835 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2836 }
2837}
2838
2839#[derive(Clone, MallocSizeOf)]
2844struct SubtleAlgorithm {
2845 name: CryptoAlgorithm,
2847}
2848
2849impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAlgorithm {
2850 type Error = Error;
2851
2852 fn try_from_with_cx_and_name(
2853 _object: HandleObject<'a>,
2854 _cx: &mut js::context::JSContext,
2855 algorithm_name: CryptoAlgorithm,
2856 ) -> Result<Self, Self::Error> {
2857 Ok(SubtleAlgorithm {
2858 name: algorithm_name,
2859 })
2860 }
2861}
2862
2863#[derive(Clone, MallocSizeOf)]
2865pub(crate) struct SubtleKeyAlgorithm {
2866 name: CryptoAlgorithm,
2868}
2869
2870impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2871 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2872 let dictionary = KeyAlgorithm {
2873 name: self.name.as_str().into(),
2874 };
2875 dictionary.safe_to_jsval(cx, rval, can_gc);
2876 }
2877}
2878
2879#[derive(Clone, MallocSizeOf)]
2881pub(crate) struct SubtleRsaHashedKeyGenParams {
2882 name: CryptoAlgorithm,
2884
2885 modulus_length: u32,
2887
2888 public_exponent: Vec<u8>,
2890
2891 hash: DigestAlgorithm,
2893}
2894
2895impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedKeyGenParams {
2896 type Error = Error;
2897
2898 fn try_from_with_cx_and_name(
2899 object: HandleObject,
2900 cx: &mut js::context::JSContext,
2901 algorithm_name: CryptoAlgorithm,
2902 ) -> Result<Self, Self::Error> {
2903 let hash = get_required_parameter(cx, object, c"hash", ())?;
2904
2905 Ok(SubtleRsaHashedKeyGenParams {
2906 name: algorithm_name,
2907 modulus_length: get_required_parameter(
2908 cx,
2909 object,
2910 c"modulusLength",
2911 ConversionBehavior::Default,
2912 )?,
2913 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2914 cx,
2915 object,
2916 c"publicExponent",
2917 (),
2918 )?
2919 .to_vec(),
2920 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2921 })
2922 }
2923}
2924
2925#[derive(Clone, MallocSizeOf)]
2927pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2928 name: CryptoAlgorithm,
2930
2931 modulus_length: u32,
2933
2934 public_exponent: Vec<u8>,
2936
2937 hash: DigestAlgorithm,
2939}
2940
2941impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2942 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2943 rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>());
2944 let public_exponent =
2945 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut(), can_gc)
2946 .expect("Fail to convert publicExponent to Uint8Array");
2947 let key_algorithm = KeyAlgorithm {
2948 name: self.name.as_str().into(),
2949 };
2950 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2951 parent: key_algorithm,
2952 modulusLength: self.modulus_length,
2953 publicExponent: public_exponent,
2954 });
2955 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
2956 parent: rsa_key_algorithm,
2957 hash: KeyAlgorithm {
2958 name: self.hash.name().as_str().into(),
2959 },
2960 });
2961 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval, can_gc);
2962 }
2963}
2964
2965#[derive(Clone, MallocSizeOf)]
2967struct SubtleRsaHashedImportParams {
2968 name: CryptoAlgorithm,
2970
2971 hash: DigestAlgorithm,
2973}
2974
2975impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedImportParams {
2976 type Error = Error;
2977
2978 fn try_from_with_cx_and_name(
2979 object: HandleObject,
2980 cx: &mut js::context::JSContext,
2981 algorithm_name: CryptoAlgorithm,
2982 ) -> Result<Self, Self::Error> {
2983 let hash = get_required_parameter(cx, object, c"hash", ())?;
2984
2985 Ok(SubtleRsaHashedImportParams {
2986 name: algorithm_name,
2987 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2988 })
2989 }
2990}
2991
2992#[derive(Clone, MallocSizeOf)]
2994struct SubtleRsaPssParams {
2995 name: CryptoAlgorithm,
2997
2998 salt_length: u32,
3000}
3001
3002impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaPssParams {
3003 type Error = Error;
3004
3005 fn try_from_with_cx_and_name(
3006 object: HandleObject,
3007 cx: &mut js::context::JSContext,
3008 algorithm_name: CryptoAlgorithm,
3009 ) -> Result<Self, Self::Error> {
3010 Ok(SubtleRsaPssParams {
3011 name: algorithm_name,
3012 salt_length: get_required_parameter(
3013 cx,
3014 object,
3015 c"saltLength",
3016 ConversionBehavior::EnforceRange,
3017 )?,
3018 })
3019 }
3020}
3021
3022#[derive(Clone, MallocSizeOf)]
3024struct SubtleRsaOaepParams {
3025 name: CryptoAlgorithm,
3027
3028 label: Option<Vec<u8>>,
3030}
3031
3032impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaOaepParams {
3033 type Error = Error;
3034
3035 fn try_from_with_cx_and_name(
3036 object: HandleObject<'a>,
3037 cx: &mut js::context::JSContext,
3038 algorithm_name: CryptoAlgorithm,
3039 ) -> Result<Self, Self::Error> {
3040 Ok(SubtleRsaOaepParams {
3041 name: algorithm_name,
3042 label: get_optional_buffer_source(cx, object, c"label")?,
3043 })
3044 }
3045}
3046
3047#[derive(Clone, MallocSizeOf)]
3049struct SubtleEcdsaParams {
3050 name: CryptoAlgorithm,
3052
3053 hash: DigestAlgorithm,
3055}
3056
3057impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdsaParams {
3058 type Error = Error;
3059
3060 fn try_from_with_cx_and_name(
3061 object: HandleObject<'a>,
3062 cx: &mut js::context::JSContext,
3063 algorithm_name: CryptoAlgorithm,
3064 ) -> Result<Self, Self::Error> {
3065 let hash = get_required_parameter(cx, object, c"hash", ())?;
3066
3067 Ok(SubtleEcdsaParams {
3068 name: algorithm_name,
3069 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3070 })
3071 }
3072}
3073
3074#[derive(Clone, MallocSizeOf)]
3076struct SubtleEcKeyGenParams {
3077 name: CryptoAlgorithm,
3079
3080 named_curve: String,
3082}
3083
3084impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyGenParams {
3085 type Error = Error;
3086
3087 fn try_from_with_cx_and_name(
3088 object: HandleObject<'a>,
3089 cx: &mut js::context::JSContext,
3090 algorithm_name: CryptoAlgorithm,
3091 ) -> Result<Self, Self::Error> {
3092 Ok(SubtleEcKeyGenParams {
3093 name: algorithm_name,
3094 named_curve: get_required_parameter::<DOMString>(
3095 cx,
3096 object,
3097 c"namedCurve",
3098 StringificationBehavior::Default,
3099 )?
3100 .to_string(),
3101 })
3102 }
3103}
3104
3105#[derive(Clone, MallocSizeOf)]
3107pub(crate) struct SubtleEcKeyAlgorithm {
3108 name: CryptoAlgorithm,
3110
3111 named_curve: String,
3113}
3114
3115impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
3116 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3117 let parent = KeyAlgorithm {
3118 name: self.name.as_str().into(),
3119 };
3120 let dictionary = EcKeyAlgorithm {
3121 parent,
3122 namedCurve: self.named_curve.clone().into(),
3123 };
3124 dictionary.safe_to_jsval(cx, rval, can_gc);
3125 }
3126}
3127
3128#[derive(Clone, MallocSizeOf)]
3130struct SubtleEcKeyImportParams {
3131 name: CryptoAlgorithm,
3133
3134 named_curve: String,
3136}
3137
3138impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyImportParams {
3139 type Error = Error;
3140
3141 fn try_from_with_cx_and_name(
3142 object: HandleObject<'a>,
3143 cx: &mut js::context::JSContext,
3144 algorithm_name: CryptoAlgorithm,
3145 ) -> Result<Self, Self::Error> {
3146 Ok(SubtleEcKeyImportParams {
3147 name: algorithm_name,
3148 named_curve: get_required_parameter::<DOMString>(
3149 cx,
3150 object,
3151 c"namedCurve",
3152 StringificationBehavior::Default,
3153 )?
3154 .to_string(),
3155 })
3156 }
3157}
3158
3159#[derive(Clone, MallocSizeOf)]
3161struct SubtleEcdhKeyDeriveParams {
3162 name: CryptoAlgorithm,
3164
3165 public: Trusted<CryptoKey>,
3167}
3168
3169impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdhKeyDeriveParams {
3170 type Error = Error;
3171
3172 fn try_from_with_cx_and_name(
3173 object: HandleObject<'a>,
3174 cx: &mut js::context::JSContext,
3175 algorithm_name: CryptoAlgorithm,
3176 ) -> Result<Self, Self::Error> {
3177 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3178
3179 Ok(SubtleEcdhKeyDeriveParams {
3180 name: algorithm_name,
3181 public: Trusted::new(&public),
3182 })
3183 }
3184}
3185
3186#[derive(Clone, MallocSizeOf)]
3188struct SubtleAesCtrParams {
3189 name: CryptoAlgorithm,
3191
3192 counter: Vec<u8>,
3194
3195 length: u8,
3197}
3198
3199impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCtrParams {
3200 type Error = Error;
3201
3202 fn try_from_with_cx_and_name(
3203 object: HandleObject<'a>,
3204 cx: &mut js::context::JSContext,
3205 algorithm_name: CryptoAlgorithm,
3206 ) -> Result<Self, Self::Error> {
3207 Ok(SubtleAesCtrParams {
3208 name: algorithm_name,
3209 counter: get_required_buffer_source(cx, object, c"counter")?,
3210 length: get_required_parameter(
3211 cx,
3212 object,
3213 c"length",
3214 ConversionBehavior::EnforceRange,
3215 )?,
3216 })
3217 }
3218}
3219
3220#[derive(Clone, MallocSizeOf)]
3222pub(crate) struct SubtleAesKeyAlgorithm {
3223 name: CryptoAlgorithm,
3225
3226 length: u16,
3228}
3229
3230impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
3231 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3232 let parent = KeyAlgorithm {
3233 name: self.name.as_str().into(),
3234 };
3235 let dictionary = AesKeyAlgorithm {
3236 parent,
3237 length: self.length,
3238 };
3239 dictionary.safe_to_jsval(cx, rval, can_gc);
3240 }
3241}
3242
3243#[derive(Clone, MallocSizeOf)]
3245struct SubtleAesKeyGenParams {
3246 name: CryptoAlgorithm,
3248
3249 length: u16,
3251}
3252
3253impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesKeyGenParams {
3254 type Error = Error;
3255
3256 fn try_from_with_cx_and_name(
3257 object: HandleObject<'a>,
3258 cx: &mut js::context::JSContext,
3259 algorithm_name: CryptoAlgorithm,
3260 ) -> Result<Self, Self::Error> {
3261 Ok(SubtleAesKeyGenParams {
3262 name: algorithm_name,
3263 length: get_required_parameter(
3264 cx,
3265 object,
3266 c"length",
3267 ConversionBehavior::EnforceRange,
3268 )?,
3269 })
3270 }
3271}
3272
3273#[derive(Clone, MallocSizeOf)]
3275struct SubtleAesDerivedKeyParams {
3276 name: CryptoAlgorithm,
3278
3279 length: u16,
3281}
3282
3283impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesDerivedKeyParams {
3284 type Error = Error;
3285
3286 fn try_from_with_cx_and_name(
3287 object: HandleObject<'a>,
3288 cx: &mut js::context::JSContext,
3289 algorithm_name: CryptoAlgorithm,
3290 ) -> Result<Self, Self::Error> {
3291 Ok(SubtleAesDerivedKeyParams {
3292 name: algorithm_name,
3293 length: get_required_parameter(
3294 cx,
3295 object,
3296 c"length",
3297 ConversionBehavior::EnforceRange,
3298 )?,
3299 })
3300 }
3301}
3302
3303#[derive(Clone, MallocSizeOf)]
3305struct SubtleAesCbcParams {
3306 name: CryptoAlgorithm,
3308
3309 iv: Vec<u8>,
3311}
3312
3313impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCbcParams {
3314 type Error = Error;
3315
3316 fn try_from_with_cx_and_name(
3317 object: HandleObject<'a>,
3318 cx: &mut js::context::JSContext,
3319 algorithm_name: CryptoAlgorithm,
3320 ) -> Result<Self, Self::Error> {
3321 Ok(SubtleAesCbcParams {
3322 name: algorithm_name,
3323 iv: get_required_buffer_source(cx, object, c"iv")?,
3324 })
3325 }
3326}
3327
3328#[derive(Clone, MallocSizeOf)]
3330struct SubtleAesGcmParams {
3331 name: CryptoAlgorithm,
3333
3334 iv: Vec<u8>,
3336
3337 additional_data: Option<Vec<u8>>,
3339
3340 tag_length: Option<u8>,
3342}
3343
3344impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesGcmParams {
3345 type Error = Error;
3346
3347 fn try_from_with_cx_and_name(
3348 object: HandleObject<'a>,
3349 cx: &mut js::context::JSContext,
3350 algorithm_name: CryptoAlgorithm,
3351 ) -> Result<Self, Self::Error> {
3352 Ok(SubtleAesGcmParams {
3353 name: algorithm_name,
3354 iv: get_required_buffer_source(cx, object, c"iv")?,
3355 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3356 tag_length: get_optional_parameter(
3357 cx,
3358 object,
3359 c"tagLength",
3360 ConversionBehavior::EnforceRange,
3361 )?,
3362 })
3363 }
3364}
3365
3366#[derive(Clone, MallocSizeOf)]
3368struct SubtleHmacImportParams {
3369 name: CryptoAlgorithm,
3371
3372 hash: DigestAlgorithm,
3374
3375 length: Option<u32>,
3377}
3378
3379impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacImportParams {
3380 type Error = Error;
3381
3382 fn try_from_with_cx_and_name(
3383 object: HandleObject<'a>,
3384 cx: &mut js::context::JSContext,
3385 algorithm_name: CryptoAlgorithm,
3386 ) -> Result<Self, Self::Error> {
3387 let hash = get_required_parameter(cx, object, c"hash", ())?;
3388
3389 Ok(SubtleHmacImportParams {
3390 name: algorithm_name,
3391 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3392 length: get_optional_parameter(
3393 cx,
3394 object,
3395 c"length",
3396 ConversionBehavior::EnforceRange,
3397 )?,
3398 })
3399 }
3400}
3401
3402#[derive(Clone, MallocSizeOf)]
3404pub(crate) struct SubtleHmacKeyAlgorithm {
3405 name: CryptoAlgorithm,
3407
3408 hash: SubtleKeyAlgorithm,
3410
3411 length: u32,
3413}
3414
3415impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
3416 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3417 let parent = KeyAlgorithm {
3418 name: self.name.as_str().into(),
3419 };
3420 let hash = KeyAlgorithm {
3421 name: self.hash.name.as_str().into(),
3422 };
3423 let dictionary = HmacKeyAlgorithm {
3424 parent,
3425 hash,
3426 length: self.length,
3427 };
3428 dictionary.safe_to_jsval(cx, rval, can_gc);
3429 }
3430}
3431
3432#[derive(Clone, MallocSizeOf)]
3434struct SubtleHmacKeyGenParams {
3435 name: CryptoAlgorithm,
3437
3438 hash: DigestAlgorithm,
3440
3441 length: Option<u32>,
3443}
3444
3445impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacKeyGenParams {
3446 type Error = Error;
3447
3448 fn try_from_with_cx_and_name(
3449 object: HandleObject<'a>,
3450 cx: &mut js::context::JSContext,
3451 algorithm_name: CryptoAlgorithm,
3452 ) -> Result<Self, Self::Error> {
3453 let hash = get_required_parameter(cx, object, c"hash", ())?;
3454
3455 Ok(SubtleHmacKeyGenParams {
3456 name: algorithm_name,
3457 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3458 length: get_optional_parameter(
3459 cx,
3460 object,
3461 c"length",
3462 ConversionBehavior::EnforceRange,
3463 )?,
3464 })
3465 }
3466}
3467
3468#[derive(Clone, MallocSizeOf)]
3470pub(crate) struct SubtleHkdfParams {
3471 name: CryptoAlgorithm,
3473
3474 hash: DigestAlgorithm,
3476
3477 salt: Vec<u8>,
3479
3480 info: Vec<u8>,
3482}
3483
3484impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHkdfParams {
3485 type Error = Error;
3486
3487 fn try_from_with_cx_and_name(
3488 object: HandleObject<'a>,
3489 cx: &mut js::context::JSContext,
3490 algorithm_name: CryptoAlgorithm,
3491 ) -> Result<Self, Self::Error> {
3492 let hash = get_required_parameter(cx, object, c"hash", ())?;
3493
3494 Ok(SubtleHkdfParams {
3495 name: algorithm_name,
3496 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3497 salt: get_required_buffer_source(cx, object, c"salt")?,
3498 info: get_required_buffer_source(cx, object, c"info")?,
3499 })
3500 }
3501}
3502
3503#[derive(Clone, MallocSizeOf)]
3505pub(crate) struct SubtlePbkdf2Params {
3506 name: CryptoAlgorithm,
3508
3509 salt: Vec<u8>,
3511
3512 iterations: u32,
3514
3515 hash: DigestAlgorithm,
3517}
3518
3519impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtlePbkdf2Params {
3520 type Error = Error;
3521
3522 fn try_from_with_cx_and_name(
3523 object: HandleObject<'a>,
3524 cx: &mut js::context::JSContext,
3525 algorithm_name: CryptoAlgorithm,
3526 ) -> Result<Self, Self::Error> {
3527 let hash = get_required_parameter(cx, object, c"hash", ())?;
3528
3529 Ok(SubtlePbkdf2Params {
3530 name: algorithm_name,
3531 salt: get_required_buffer_source(cx, object, c"salt")?,
3532 iterations: get_required_parameter(
3533 cx,
3534 object,
3535 c"iterations",
3536 ConversionBehavior::EnforceRange,
3537 )?,
3538 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3539 })
3540 }
3541}
3542
3543#[derive(Clone, MallocSizeOf)]
3545struct SubtleContextParams {
3546 name: CryptoAlgorithm,
3548
3549 context: Option<Vec<u8>>,
3551}
3552
3553impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleContextParams {
3554 type Error = Error;
3555
3556 fn try_from_with_cx_and_name(
3557 object: HandleObject<'a>,
3558 cx: &mut js::context::JSContext,
3559 algorithm_name: CryptoAlgorithm,
3560 ) -> Result<Self, Self::Error> {
3561 Ok(SubtleContextParams {
3562 name: algorithm_name,
3563 context: get_optional_buffer_source(cx, object, c"context")?,
3564 })
3565 }
3566}
3567
3568#[derive(Clone, MallocSizeOf)]
3570struct SubtleAeadParams {
3571 name: CryptoAlgorithm,
3573
3574 iv: Vec<u8>,
3576
3577 additional_data: Option<Vec<u8>>,
3579
3580 tag_length: Option<u8>,
3582}
3583
3584impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAeadParams {
3585 type Error = Error;
3586
3587 fn try_from_with_cx_and_name(
3588 object: HandleObject<'a>,
3589 cx: &mut js::context::JSContext,
3590 algorithm_name: CryptoAlgorithm,
3591 ) -> Result<Self, Self::Error> {
3592 Ok(SubtleAeadParams {
3593 name: algorithm_name,
3594 iv: get_required_buffer_source(cx, object, c"iv")?,
3595 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3596 tag_length: get_optional_parameter(
3597 cx,
3598 object,
3599 c"tagLength",
3600 ConversionBehavior::EnforceRange,
3601 )?,
3602 })
3603 }
3604}
3605
3606#[derive(Clone, MallocSizeOf)]
3608struct SubtleCShakeParams {
3609 name: CryptoAlgorithm,
3611
3612 output_length: u32,
3614
3615 function_name: Option<Vec<u8>>,
3617
3618 customization: Option<Vec<u8>>,
3620}
3621
3622impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleCShakeParams {
3623 type Error = Error;
3624
3625 fn try_from_with_cx_and_name(
3626 object: HandleObject<'a>,
3627 cx: &mut js::context::JSContext,
3628 algorithm_name: CryptoAlgorithm,
3629 ) -> Result<Self, Self::Error> {
3630 Ok(SubtleCShakeParams {
3631 name: algorithm_name,
3632 output_length: get_required_parameter(
3633 cx,
3634 object,
3635 c"outputLength",
3636 ConversionBehavior::EnforceRange,
3637 )?,
3638 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3639 customization: get_optional_buffer_source(cx, object, c"customization")?,
3640 })
3641 }
3642}
3643
3644#[derive(Clone, MallocSizeOf)]
3646struct SubtleTurboShakeParams {
3647 name: CryptoAlgorithm,
3649
3650 output_length: u32,
3652
3653 domain_separation: Option<u8>,
3655}
3656
3657impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleTurboShakeParams {
3658 type Error = Error;
3659
3660 fn try_from_with_cx_and_name(
3661 object: HandleObject<'a>,
3662 cx: &mut js::context::JSContext,
3663 algorithm_name: CryptoAlgorithm,
3664 ) -> Result<Self, Self::Error> {
3665 Ok(SubtleTurboShakeParams {
3666 name: algorithm_name,
3667 output_length: get_required_parameter(
3668 cx,
3669 object,
3670 c"outputLength",
3671 ConversionBehavior::EnforceRange,
3672 )?,
3673 domain_separation: get_optional_parameter(
3674 cx,
3675 object,
3676 c"domainSeparation",
3677 ConversionBehavior::EnforceRange,
3678 )?,
3679 })
3680 }
3681}
3682
3683#[derive(Clone, MallocSizeOf)]
3685struct SubtleArgon2Params {
3686 name: CryptoAlgorithm,
3688
3689 nonce: Vec<u8>,
3691
3692 parallelism: u32,
3694
3695 memory: u32,
3697
3698 passes: u32,
3700
3701 version: Option<u8>,
3703
3704 secret_value: Option<Vec<u8>>,
3706
3707 associated_data: Option<Vec<u8>>,
3709}
3710
3711impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleArgon2Params {
3712 type Error = Error;
3713
3714 fn try_from_with_cx_and_name(
3715 object: HandleObject<'a>,
3716 cx: &mut js::context::JSContext,
3717 algorithm_name: CryptoAlgorithm,
3718 ) -> Result<Self, Self::Error> {
3719 Ok(SubtleArgon2Params {
3720 name: algorithm_name,
3721 nonce: get_required_buffer_source(cx, object, c"nonce")?,
3722 parallelism: get_required_parameter(
3723 cx,
3724 object,
3725 c"parallelism",
3726 ConversionBehavior::EnforceRange,
3727 )?,
3728 memory: get_required_parameter(
3729 cx,
3730 object,
3731 c"memory",
3732 ConversionBehavior::EnforceRange,
3733 )?,
3734 passes: get_required_parameter(
3735 cx,
3736 object,
3737 c"passes",
3738 ConversionBehavior::EnforceRange,
3739 )?,
3740 version: get_optional_parameter(
3741 cx,
3742 object,
3743 c"version",
3744 ConversionBehavior::EnforceRange,
3745 )?,
3746 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
3747 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
3748 })
3749 }
3750}
3751
3752struct SubtleEncapsulatedKey {
3754 shared_key: Option<Trusted<CryptoKey>>,
3756
3757 ciphertext: Option<Vec<u8>>,
3759}
3760
3761impl SafeToJSValConvertible for SubtleEncapsulatedKey {
3762 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3763 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
3764 let ciphertext = self.ciphertext.as_ref().map(|data| {
3765 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3766 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3767 .expect("Failed to convert ciphertext to ArrayBufferU8")
3768 });
3769 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
3770 sharedKey: shared_key,
3771 ciphertext,
3772 });
3773 encapsulated_key.safe_to_jsval(cx, rval, can_gc);
3774 }
3775}
3776
3777struct SubtleEncapsulatedBits {
3779 shared_key: Option<Zeroizing<Vec<u8>>>,
3781
3782 ciphertext: Option<Vec<u8>>,
3784}
3785
3786impl SafeToJSValConvertible for SubtleEncapsulatedBits {
3787 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3788 let shared_key = self.shared_key.as_ref().map(|data| {
3789 rooted!(in(*cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
3790 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut(), can_gc)
3791 .expect("Failed to convert shared key to ArrayBufferU8")
3792 });
3793 let ciphertext = self.ciphertext.as_ref().map(|data| {
3794 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3795 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3796 .expect("Failed to convert ciphertext to ArrayBufferU8")
3797 });
3798 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
3799 sharedKey: shared_key,
3800 ciphertext,
3801 });
3802 encapsulated_bits.safe_to_jsval(cx, rval, can_gc);
3803 }
3804}
3805
3806#[expect(unsafe_code)]
3808fn get_optional_parameter<T: SafeFromJSValConvertible>(
3809 cx: &mut js::context::JSContext,
3810 object: HandleObject,
3811 parameter: &std::ffi::CStr,
3812 option: T::Config,
3813) -> Fallible<Option<T>> {
3814 rooted!(&in(cx) let mut rval = UndefinedValue());
3815 if unsafe {
3816 get_dictionary_property(
3817 cx.raw_cx(),
3818 object,
3819 parameter,
3820 rval.handle_mut(),
3821 CanGc::from_cx(cx),
3822 )
3823 .map_err(|_| Error::JSFailed)?
3824 } && !rval.is_undefined()
3825 {
3826 let conversion_result =
3827 T::safe_from_jsval(cx.into(), rval.handle(), option, CanGc::from_cx(cx))
3828 .map_err(|_| Error::JSFailed)?;
3829 match conversion_result {
3830 ConversionResult::Success(value) => Ok(Some(value)),
3831 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
3832 }
3833 } else {
3834 Ok(None)
3835 }
3836}
3837
3838fn get_required_parameter<T: SafeFromJSValConvertible>(
3840 cx: &mut js::context::JSContext,
3841 object: HandleObject,
3842 parameter: &std::ffi::CStr,
3843 option: T::Config,
3844) -> Fallible<T> {
3845 get_optional_parameter(cx, object, parameter, option)?
3846 .ok_or(Error::Type(c"Missing required parameter".into()))
3847}
3848
3849#[expect(unsafe_code)]
3851fn get_optional_parameter_in_box<T: SafeFromJSValConvertible + Trace>(
3852 cx: &mut js::context::JSContext,
3853 object: HandleObject,
3854 parameter: &std::ffi::CStr,
3855 option: T::Config,
3856) -> Fallible<Option<RootedTraceableBox<T>>> {
3857 rooted!(&in(cx) let mut rval = UndefinedValue());
3858 if unsafe {
3859 get_dictionary_property(
3860 cx.raw_cx(),
3861 object,
3862 parameter,
3863 rval.handle_mut(),
3864 CanGc::from_cx(cx),
3865 )
3866 .map_err(|_| Error::JSFailed)?
3867 } && !rval.is_undefined()
3868 {
3869 let conversion_result: ConversionResult<T> = SafeFromJSValConvertible::safe_from_jsval(
3870 cx.into(),
3871 rval.handle(),
3872 option,
3873 CanGc::from_cx(cx),
3874 )
3875 .map_err(|_| Error::JSFailed)?;
3876 match conversion_result {
3877 ConversionResult::Success(value) => Ok(Some(RootedTraceableBox::new(value))),
3878 ConversionResult::Failure(error) => Err(Error::Type(error.into())),
3879 }
3880 } else {
3881 Ok(None)
3882 }
3883}
3884
3885fn get_required_parameter_in_box<T: SafeFromJSValConvertible + Trace>(
3887 cx: &mut js::context::JSContext,
3888 object: HandleObject,
3889 parameter: &std::ffi::CStr,
3890 option: T::Config,
3891) -> Fallible<RootedTraceableBox<T>> {
3892 get_optional_parameter_in_box(cx, object, parameter, option)?
3893 .ok_or(Error::Type(c"Missing required parameter".into()))
3894}
3895
3896fn get_optional_buffer_source(
3900 cx: &mut js::context::JSContext,
3901 object: HandleObject,
3902 parameter: &std::ffi::CStr,
3903) -> Fallible<Option<Vec<u8>>> {
3904 let buffer_source =
3905 get_optional_parameter::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
3906 match buffer_source {
3907 Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(view)) => Ok(Some(view.to_vec())),
3908 Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer)) => Ok(Some(buffer.to_vec())),
3909 None => Ok(None),
3910 }
3911}
3912
3913fn get_required_buffer_source(
3917 cx: &mut js::context::JSContext,
3918 object: HandleObject,
3919 parameter: &std::ffi::CStr,
3920) -> Fallible<Vec<u8>> {
3921 get_optional_buffer_source(cx, object, parameter)?
3922 .ok_or(Error::Type(c"Missing required parameter".into()))
3923}
3924
3925enum ExportedKey {
3929 Bytes(Zeroizing<Vec<u8>>),
3930 Jwk(Box<JsonWebKey>),
3931}
3932
3933impl ExportedKey {
3934 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
3935 ExportedKey::Bytes(Zeroizing::new(bytes))
3936 }
3937
3938 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
3939 ExportedKey::Jwk(Box::new(jwk))
3940 }
3941}
3942
3943#[derive(Clone, MallocSizeOf)]
3947#[expect(clippy::enum_variant_names)]
3948pub(crate) enum KeyAlgorithmAndDerivatives {
3949 KeyAlgorithm(SubtleKeyAlgorithm),
3950 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
3951 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
3952 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
3953 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
3954}
3955
3956impl KeyAlgorithmAndDerivatives {
3957 fn name(&self) -> CryptoAlgorithm {
3958 match self {
3959 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
3960 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
3961 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
3962 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
3963 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
3964 }
3965 }
3966}
3967
3968impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
3969 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3970 match self {
3971 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
3972 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => {
3973 algo.safe_to_jsval(cx, rval, can_gc)
3974 },
3975 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
3976 algo.safe_to_jsval(cx, rval, can_gc)
3977 },
3978 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
3979 algo.safe_to_jsval(cx, rval, can_gc)
3980 },
3981 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
3982 algo.safe_to_jsval(cx, rval, can_gc)
3983 },
3984 }
3985 }
3986}
3987
3988#[derive(Clone, Copy)]
3989enum JwkStringField {
3990 X,
3991 Y,
3992 D,
3993 N,
3994 E,
3995 P,
3996 Q,
3997 DP,
3998 DQ,
3999 QI,
4000 K,
4001 Priv,
4002 Pub,
4003}
4004
4005impl Display for JwkStringField {
4006 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4007 let field_name = match self {
4008 JwkStringField::X => "x",
4009 JwkStringField::Y => "y",
4010 JwkStringField::D => "d",
4011 JwkStringField::N => "n",
4012 JwkStringField::E => "e",
4013 JwkStringField::P => "q",
4014 JwkStringField::Q => "q",
4015 JwkStringField::DP => "dp",
4016 JwkStringField::DQ => "dq",
4017 JwkStringField::QI => "qi",
4018 JwkStringField::K => "k",
4019 JwkStringField::Priv => "priv",
4020 JwkStringField::Pub => "pub",
4021 };
4022 write!(f, "{}", field_name)
4023 }
4024}
4025
4026trait JsonWebKeyExt {
4027 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4028 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4029 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4030 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4031 fn set_key_ops(&mut self, usages: Vec<KeyUsage>);
4032 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4033 fn decode_optional_string_field(
4034 &self,
4035 field: JwkStringField,
4036 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4037 fn decode_required_string_field(
4038 &self,
4039 field: JwkStringField,
4040 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4041 fn decode_primes_from_oth_field(
4042 &self,
4043 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4044 ) -> Result<(), Error>;
4045}
4046
4047impl JsonWebKeyExt for JsonWebKey {
4048 #[expect(unsafe_code)]
4050 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4051 let json = String::from_utf8_lossy(data);
4056
4057 let json: Vec<_> = json.encode_utf16().collect();
4059
4060 rooted!(&in(cx) let mut result = UndefinedValue());
4064 unsafe {
4065 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4066 return Err(Error::JSFailed);
4067 }
4068 }
4069
4070 let key = match JsonWebKey::new(cx.into(), result.handle(), CanGc::from_cx(cx)) {
4072 Ok(ConversionResult::Success(key)) => key,
4073 Ok(ConversionResult::Failure(error)) => {
4074 return Err(Error::Type(error.into_owned()));
4075 },
4076 Err(()) => {
4077 return Err(Error::JSFailed);
4078 },
4079 };
4080
4081 if key.kty.is_none() {
4083 return Err(Error::Data(None));
4084 }
4085
4086 Ok(key)
4088 }
4089
4090 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4096 rooted!(&in(cx) let mut data = UndefinedValue());
4097 self.safe_to_jsval(cx.into(), data.handle_mut(), CanGc::from_cx(cx));
4098 serialize_jsval_to_json_utf8(cx.into(), data.handle()).map(Zeroizing::new)
4099 }
4100
4101 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4102 let mut usages = vec![];
4103 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
4104 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
4105 }
4106 Ok(usages)
4107 }
4108
4109 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4113 if let Some(ref key_ops) = self.key_ops {
4115 if key_ops
4118 .iter()
4119 .collect::<std::collections::HashSet<_>>()
4120 .len() <
4121 key_ops.len()
4122 {
4123 return Err(Error::Data(None));
4124 }
4125 if let Some(ref use_) = self.use_ &&
4128 key_ops.iter().any(|op| op != use_)
4129 {
4130 return Err(Error::Data(None));
4131 }
4132
4133 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4135 if !specified_usages
4136 .iter()
4137 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4138 {
4139 return Err(Error::Data(None));
4140 }
4141 }
4142
4143 Ok(())
4144 }
4145
4146 fn set_key_ops(&mut self, usages: Vec<KeyUsage>) {
4148 self.key_ops = Some(
4149 usages
4150 .into_iter()
4151 .map(|usage| DOMString::from(usage.as_str()))
4152 .collect(),
4153 );
4154 }
4155
4156 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4159 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4160 match field {
4161 JwkStringField::X => self.x = Some(encoded_data),
4162 JwkStringField::Y => self.y = Some(encoded_data),
4163 JwkStringField::D => self.d = Some(encoded_data),
4164 JwkStringField::N => self.n = Some(encoded_data),
4165 JwkStringField::E => self.e = Some(encoded_data),
4166 JwkStringField::P => self.p = Some(encoded_data),
4167 JwkStringField::Q => self.q = Some(encoded_data),
4168 JwkStringField::DP => self.dp = Some(encoded_data),
4169 JwkStringField::DQ => self.dq = Some(encoded_data),
4170 JwkStringField::QI => self.qi = Some(encoded_data),
4171 JwkStringField::K => self.k = Some(encoded_data),
4172 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4173 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4174 }
4175 }
4176
4177 fn decode_optional_string_field(
4180 &self,
4181 field: JwkStringField,
4182 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4183 let field_string = match field {
4184 JwkStringField::X => &self.x,
4185 JwkStringField::Y => &self.y,
4186 JwkStringField::D => &self.d,
4187 JwkStringField::N => &self.n,
4188 JwkStringField::E => &self.e,
4189 JwkStringField::P => &self.p,
4190 JwkStringField::Q => &self.q,
4191 JwkStringField::DP => &self.dp,
4192 JwkStringField::DQ => &self.dq,
4193 JwkStringField::QI => &self.qi,
4194 JwkStringField::K => &self.k,
4195 JwkStringField::Priv => &self.priv_,
4196 JwkStringField::Pub => &self.pub_,
4197 };
4198
4199 field_string
4200 .as_ref()
4201 .map(|field_string| {
4202 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4203 })
4204 .transpose()
4205 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4206 }
4207
4208 fn decode_required_string_field(
4211 &self,
4212 field: JwkStringField,
4213 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4214 self.decode_optional_string_field(field)?
4215 .ok_or(Error::Data(Some(format!(
4216 "The {} field is not present in jwk",
4217 field
4218 ))))
4219 }
4220
4221 fn decode_primes_from_oth_field(
4230 &self,
4231 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4232 ) -> Result<(), Error> {
4233 if self.oth.is_some() &&
4234 (self.p.is_none() ||
4235 self.q.is_none() ||
4236 self.dp.is_none() ||
4237 self.dq.is_none() ||
4238 self.qi.is_none())
4239 {
4240 return Err(Error::Data(Some(
4241 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4242 )));
4243 }
4244
4245 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4246 let r = Base64UrlUnpadded::decode_vec(
4247 &rsa_other_prime_info
4248 .r
4249 .as_ref()
4250 .ok_or(Error::Data(Some(
4251 "The r field is not present in one of the entry of oth field in jwk"
4252 .to_string(),
4253 )))?
4254 .str(),
4255 )
4256 .map_err(|_| {
4257 Error::Data(Some(
4258 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4259 ))
4260 })?;
4261 primes.push(Zeroizing::new(r));
4262
4263 let _d = Base64UrlUnpadded::decode_vec(
4264 &rsa_other_prime_info
4265 .d
4266 .as_ref()
4267 .ok_or(Error::Data(Some(
4268 "The d field is not present in one of the entry of oth field in jwk"
4269 .to_string(),
4270 )))?
4271 .str(),
4272 )
4273 .map_err(|_| {
4274 Error::Data(Some(
4275 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4276 ))
4277 })?;
4278
4279 let _t = Base64UrlUnpadded::decode_vec(
4280 &rsa_other_prime_info
4281 .t
4282 .as_ref()
4283 .ok_or(Error::Data(Some(
4284 "The t field is not present in one of the entry of oth field in jwk"
4285 .to_string(),
4286 )))?
4287 .str(),
4288 )
4289 .map_err(|_| {
4290 Error::Data(Some(
4291 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4292 ))
4293 })?;
4294 }
4295
4296 Ok(())
4297 }
4298}
4299
4300fn normalize_algorithm<Op: Operation>(
4302 cx: &mut js::context::JSContext,
4303 algorithm: &AlgorithmIdentifier,
4304) -> Result<Op::RegisteredAlgorithm, Error> {
4305 match algorithm {
4306 ObjectOrString::String(name) => {
4308 let algorithm = Algorithm {
4312 name: name.to_owned(),
4313 };
4314 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4315 algorithm.safe_to_jsval(cx.into(), algorithm_value.handle_mut(), CanGc::from_cx(cx));
4316 let algorithm_object = RootedTraceableBox::new(Heap::default());
4317 algorithm_object.set(algorithm_value.to_object());
4318 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
4319 },
4320 ObjectOrString::Object(object) => {
4322 let algorithm_name = get_required_parameter::<DOMString>(
4330 cx,
4331 object.handle(),
4332 c"name",
4333 StringificationBehavior::Default,
4334 )?;
4335
4336 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4377 let normalized_algorithm =
4378 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4379
4380 Ok(normalized_algorithm)
4382 },
4383 }
4384}
4385
4386trait Operation {
4440 type RegisteredAlgorithm: NormalizedAlgorithm;
4441}
4442
4443trait NormalizedAlgorithm: Sized {
4444 fn from_object(
4446 cx: &mut js::context::JSContext,
4447 algorithm_name: CryptoAlgorithm,
4448 object: HandleObject,
4449 ) -> Fallible<Self>;
4450 fn name(&self) -> CryptoAlgorithm;
4451}
4452
4453struct EncryptOperation {}
4455
4456impl Operation for EncryptOperation {
4457 type RegisteredAlgorithm = EncryptAlgorithm;
4458}
4459
4460enum EncryptAlgorithm {
4463 RsaOaep(SubtleRsaOaepParams),
4464 AesCtr(SubtleAesCtrParams),
4465 AesCbc(SubtleAesCbcParams),
4466 AesGcm(SubtleAesGcmParams),
4467 AesOcb(SubtleAeadParams),
4468 ChaCha20Poly1305(SubtleAeadParams),
4469}
4470
4471impl NormalizedAlgorithm for EncryptAlgorithm {
4472 fn from_object(
4473 cx: &mut js::context::JSContext,
4474 algorithm_name: CryptoAlgorithm,
4475 object: HandleObject,
4476 ) -> Fallible<Self> {
4477 match algorithm_name {
4478 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4479 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4480 )),
4481 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4482 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4483 )),
4484 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4485 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4486 )),
4487 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4488 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4489 )),
4490 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4491 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4492 )),
4493 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4494 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4495 )),
4496 _ => Err(Error::NotSupported(Some(format!(
4497 "{} does not support \"encrypt\" operation",
4498 algorithm_name.as_str()
4499 )))),
4500 }
4501 }
4502
4503 fn name(&self) -> CryptoAlgorithm {
4504 match self {
4505 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4506 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4507 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4508 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4509 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4510 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4511 }
4512 }
4513}
4514
4515impl EncryptAlgorithm {
4516 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4517 match self {
4518 EncryptAlgorithm::RsaOaep(algorithm) => {
4519 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4520 },
4521 EncryptAlgorithm::AesCtr(algorithm) => {
4522 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4523 },
4524 EncryptAlgorithm::AesCbc(algorithm) => {
4525 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4526 },
4527 EncryptAlgorithm::AesGcm(algorithm) => {
4528 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4529 },
4530 EncryptAlgorithm::AesOcb(algorithm) => {
4531 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4532 },
4533 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4534 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4535 },
4536 }
4537 }
4538}
4539
4540struct DecryptOperation {}
4542
4543impl Operation for DecryptOperation {
4544 type RegisteredAlgorithm = DecryptAlgorithm;
4545}
4546
4547enum DecryptAlgorithm {
4550 RsaOaep(SubtleRsaOaepParams),
4551 AesCtr(SubtleAesCtrParams),
4552 AesCbc(SubtleAesCbcParams),
4553 AesGcm(SubtleAesGcmParams),
4554 AesOcb(SubtleAeadParams),
4555 ChaCha20Poly1305(SubtleAeadParams),
4556}
4557
4558impl NormalizedAlgorithm for DecryptAlgorithm {
4559 fn from_object(
4560 cx: &mut js::context::JSContext,
4561 algorithm_name: CryptoAlgorithm,
4562 object: HandleObject,
4563 ) -> Fallible<Self> {
4564 match algorithm_name {
4565 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4566 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4567 )),
4568 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4569 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4570 )),
4571 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4572 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4573 )),
4574 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4575 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4576 )),
4577 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4578 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4579 )),
4580 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
4581 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4582 )),
4583 _ => Err(Error::NotSupported(Some(format!(
4584 "{} does not support \"decrypt\" operation",
4585 algorithm_name.as_str()
4586 )))),
4587 }
4588 }
4589
4590 fn name(&self) -> CryptoAlgorithm {
4591 match self {
4592 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4593 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4594 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4595 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4596 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4597 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4598 }
4599 }
4600}
4601
4602impl DecryptAlgorithm {
4603 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4604 match self {
4605 DecryptAlgorithm::RsaOaep(algorithm) => {
4606 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
4607 },
4608 DecryptAlgorithm::AesCtr(algorithm) => {
4609 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
4610 },
4611 DecryptAlgorithm::AesCbc(algorithm) => {
4612 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
4613 },
4614 DecryptAlgorithm::AesGcm(algorithm) => {
4615 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
4616 },
4617 DecryptAlgorithm::AesOcb(algorithm) => {
4618 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
4619 },
4620 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4621 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
4622 },
4623 }
4624 }
4625}
4626
4627struct SignOperation {}
4629
4630impl Operation for SignOperation {
4631 type RegisteredAlgorithm = SignAlgorithm;
4632}
4633
4634enum SignAlgorithm {
4637 RsassaPkcs1V1_5(SubtleAlgorithm),
4638 RsaPss(SubtleRsaPssParams),
4639 Ecdsa(SubtleEcdsaParams),
4640 Ed25519(SubtleAlgorithm),
4641 Hmac(SubtleAlgorithm),
4642 MlDsa(SubtleContextParams),
4643}
4644
4645impl NormalizedAlgorithm for SignAlgorithm {
4646 fn from_object(
4647 cx: &mut js::context::JSContext,
4648 algorithm_name: CryptoAlgorithm,
4649 object: HandleObject,
4650 ) -> Fallible<Self> {
4651 match algorithm_name {
4652 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
4653 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4654 )),
4655 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
4656 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4657 )),
4658 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
4659 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4660 )),
4661 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
4662 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4663 )),
4664 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
4665 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4666 )),
4667 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4668 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4669 ),
4670 _ => Err(Error::NotSupported(Some(format!(
4671 "{} does not support \"sign\" operation",
4672 algorithm_name.as_str()
4673 )))),
4674 }
4675 }
4676
4677 fn name(&self) -> CryptoAlgorithm {
4678 match self {
4679 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4680 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
4681 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
4682 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
4683 SignAlgorithm::Hmac(algorithm) => algorithm.name,
4684 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
4685 }
4686 }
4687}
4688
4689impl SignAlgorithm {
4690 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
4691 match self {
4692 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4693 rsassa_pkcs1_v1_5_operation::sign(key, message)
4694 },
4695 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
4696 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
4697 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
4698 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
4699 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
4700 }
4701 }
4702}
4703
4704struct VerifyOperation {}
4706
4707impl Operation for VerifyOperation {
4708 type RegisteredAlgorithm = VerifyAlgorithm;
4709}
4710
4711enum VerifyAlgorithm {
4714 RsassaPkcs1V1_5(SubtleAlgorithm),
4715 RsaPss(SubtleRsaPssParams),
4716 Ecdsa(SubtleEcdsaParams),
4717 Ed25519(SubtleAlgorithm),
4718 Hmac(SubtleAlgorithm),
4719 MlDsa(SubtleContextParams),
4720}
4721
4722impl NormalizedAlgorithm for VerifyAlgorithm {
4723 fn from_object(
4724 cx: &mut js::context::JSContext,
4725 algorithm_name: CryptoAlgorithm,
4726 object: HandleObject,
4727 ) -> Fallible<Self> {
4728 match algorithm_name {
4729 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
4730 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4731 )),
4732 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
4733 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4734 )),
4735 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
4736 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4737 )),
4738 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
4739 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4740 )),
4741 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
4742 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4743 )),
4744 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
4745 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4746 ),
4747 _ => Err(Error::NotSupported(Some(format!(
4748 "{} does not support \"verify\" operation",
4749 algorithm_name.as_str()
4750 )))),
4751 }
4752 }
4753
4754 fn name(&self) -> CryptoAlgorithm {
4755 match self {
4756 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4757 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
4758 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4759 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
4760 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
4761 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
4762 }
4763 }
4764}
4765
4766impl VerifyAlgorithm {
4767 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4768 match self {
4769 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4770 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4771 },
4772 VerifyAlgorithm::RsaPss(algorithm) => {
4773 rsa_pss_operation::verify(algorithm, key, message, signature)
4774 },
4775 VerifyAlgorithm::Ecdsa(algorithm) => {
4776 ecdsa_operation::verify(algorithm, key, message, signature)
4777 },
4778 VerifyAlgorithm::Ed25519(_algorithm) => {
4779 ed25519_operation::verify(key, message, signature)
4780 },
4781 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
4782 VerifyAlgorithm::MlDsa(algorithm) => {
4783 ml_dsa_operation::verify(algorithm, key, message, signature)
4784 },
4785 }
4786 }
4787}
4788
4789struct DigestOperation {}
4791
4792impl Operation for DigestOperation {
4793 type RegisteredAlgorithm = DigestAlgorithm;
4794}
4795
4796#[derive(Clone, MallocSizeOf)]
4799enum DigestAlgorithm {
4800 Sha(SubtleAlgorithm),
4801 Sha3(SubtleAlgorithm),
4802 CShake(SubtleCShakeParams),
4803 TurboShake(SubtleTurboShakeParams),
4804}
4805
4806impl NormalizedAlgorithm for DigestAlgorithm {
4807 fn from_object(
4808 cx: &mut js::context::JSContext,
4809 algorithm_name: CryptoAlgorithm,
4810 object: HandleObject,
4811 ) -> Fallible<Self> {
4812 match algorithm_name {
4813 CryptoAlgorithm::Sha1 |
4814 CryptoAlgorithm::Sha256 |
4815 CryptoAlgorithm::Sha384 |
4816 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
4817 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4818 )),
4819 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
4820 Ok(DigestAlgorithm::Sha3(
4821 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4822 ))
4823 },
4824 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
4825 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4826 )),
4827 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
4828 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4829 ),
4830 _ => Err(Error::NotSupported(Some(format!(
4831 "{} does not support \"digest\" operation",
4832 algorithm_name.as_str()
4833 )))),
4834 }
4835 }
4836
4837 fn name(&self) -> CryptoAlgorithm {
4838 match self {
4839 DigestAlgorithm::Sha(algorithm) => algorithm.name,
4840 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
4841 DigestAlgorithm::CShake(algorithm) => algorithm.name,
4842 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
4843 }
4844 }
4845}
4846
4847impl DigestAlgorithm {
4848 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
4849 match self {
4850 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
4851 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
4852 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
4853 DigestAlgorithm::TurboShake(algorithm) => {
4854 turboshake_operation::digest(algorithm, message)
4855 },
4856 }
4857 }
4858}
4859
4860struct DeriveBitsOperation {}
4862
4863impl Operation for DeriveBitsOperation {
4864 type RegisteredAlgorithm = DeriveBitsAlgorithm;
4865}
4866
4867enum DeriveBitsAlgorithm {
4870 Ecdh(SubtleEcdhKeyDeriveParams),
4871 X25519(SubtleEcdhKeyDeriveParams),
4872 Hkdf(SubtleHkdfParams),
4873 Pbkdf2(SubtlePbkdf2Params),
4874 Argon2(SubtleArgon2Params),
4875}
4876
4877impl NormalizedAlgorithm for DeriveBitsAlgorithm {
4878 fn from_object(
4879 cx: &mut js::context::JSContext,
4880 algorithm_name: CryptoAlgorithm,
4881 object: HandleObject,
4882 ) -> Fallible<Self> {
4883 match algorithm_name {
4884 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
4885 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4886 )),
4887 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
4888 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4889 )),
4890 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
4891 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4892 )),
4893 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
4894 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4895 )),
4896 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
4897 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
4898 ),
4899 _ => Err(Error::NotSupported(Some(format!(
4900 "{} does not support \"deriveBits\" operation",
4901 algorithm_name.as_str()
4902 )))),
4903 }
4904 }
4905
4906 fn name(&self) -> CryptoAlgorithm {
4907 match self {
4908 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
4909 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
4910 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
4911 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
4912 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
4913 }
4914 }
4915}
4916
4917impl DeriveBitsAlgorithm {
4918 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
4919 match self {
4920 DeriveBitsAlgorithm::Ecdh(algorithm) => {
4921 ecdh_operation::derive_bits(algorithm, key, length)
4922 },
4923 DeriveBitsAlgorithm::X25519(algorithm) => {
4924 x25519_operation::derive_bits(algorithm, key, length)
4925 },
4926 DeriveBitsAlgorithm::Hkdf(algorithm) => {
4927 hkdf_operation::derive_bits(algorithm, key, length)
4928 },
4929 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
4930 pbkdf2_operation::derive_bits(algorithm, key, length)
4931 },
4932 DeriveBitsAlgorithm::Argon2(algorithm) => {
4933 argon2_operation::derive_bits(algorithm, key, length)
4934 },
4935 }
4936 }
4937}
4938
4939struct WrapKeyOperation {}
4941
4942impl Operation for WrapKeyOperation {
4943 type RegisteredAlgorithm = WrapKeyAlgorithm;
4944}
4945
4946enum WrapKeyAlgorithm {
4949 AesKw(SubtleAlgorithm),
4950}
4951
4952impl NormalizedAlgorithm for WrapKeyAlgorithm {
4953 fn from_object(
4954 cx: &mut js::context::JSContext,
4955 algorithm_name: CryptoAlgorithm,
4956 object: HandleObject,
4957 ) -> Fallible<Self> {
4958 match algorithm_name {
4959 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
4960 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4961 )),
4962 _ => Err(Error::NotSupported(Some(format!(
4963 "{} does not support \"wrapKey\" operation",
4964 algorithm_name.as_str()
4965 )))),
4966 }
4967 }
4968
4969 fn name(&self) -> CryptoAlgorithm {
4970 match self {
4971 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4972 }
4973 }
4974}
4975
4976impl WrapKeyAlgorithm {
4977 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4978 match self {
4979 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
4980 }
4981 }
4982}
4983
4984struct UnwrapKeyOperation {}
4986
4987impl Operation for UnwrapKeyOperation {
4988 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
4989}
4990
4991enum UnwrapKeyAlgorithm {
4994 AesKw(SubtleAlgorithm),
4995}
4996
4997impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
4998 fn from_object(
4999 cx: &mut js::context::JSContext,
5000 algorithm_name: CryptoAlgorithm,
5001 object: HandleObject,
5002 ) -> Fallible<Self> {
5003 match algorithm_name {
5004 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5005 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5006 )),
5007 _ => Err(Error::NotSupported(Some(format!(
5008 "{} does not support \"unwrapKey\" operation",
5009 algorithm_name.as_str()
5010 )))),
5011 }
5012 }
5013
5014 fn name(&self) -> CryptoAlgorithm {
5015 match self {
5016 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5017 }
5018 }
5019}
5020
5021impl UnwrapKeyAlgorithm {
5022 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5023 match self {
5024 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5025 }
5026 }
5027}
5028
5029struct GenerateKeyOperation {}
5031
5032impl Operation for GenerateKeyOperation {
5033 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5034}
5035
5036enum GenerateKeyAlgorithm {
5039 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
5040 RsaPss(SubtleRsaHashedKeyGenParams),
5041 RsaOaep(SubtleRsaHashedKeyGenParams),
5042 Ecdsa(SubtleEcKeyGenParams),
5043 Ecdh(SubtleEcKeyGenParams),
5044 Ed25519(SubtleAlgorithm),
5045 X25519(SubtleAlgorithm),
5046 AesCtr(SubtleAesKeyGenParams),
5047 AesCbc(SubtleAesKeyGenParams),
5048 AesGcm(SubtleAesKeyGenParams),
5049 AesKw(SubtleAesKeyGenParams),
5050 Hmac(SubtleHmacKeyGenParams),
5051 MlKem(SubtleAlgorithm),
5052 MlDsa(SubtleAlgorithm),
5053 AesOcb(SubtleAesKeyGenParams),
5054 ChaCha20Poly1305(SubtleAlgorithm),
5055}
5056
5057impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5058 fn from_object(
5059 cx: &mut js::context::JSContext,
5060 algorithm_name: CryptoAlgorithm,
5061 object: HandleObject,
5062 ) -> Fallible<Self> {
5063 match algorithm_name {
5064 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5065 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5066 )),
5067 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5068 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5069 )),
5070 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5071 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5072 )),
5073 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5074 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5075 )),
5076 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5077 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5078 )),
5079 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5080 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5081 )),
5082 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5083 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5084 )),
5085 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5086 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5087 )),
5088 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5089 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5090 )),
5091 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5092 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5093 )),
5094 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5095 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5096 )),
5097 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5098 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5099 )),
5100 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5101 Ok(GenerateKeyAlgorithm::MlKem(
5102 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5103 ))
5104 },
5105 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5106 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5107 ),
5108 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5109 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5110 )),
5111 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5112 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5113 )),
5114 _ => Err(Error::NotSupported(Some(format!(
5115 "{} does not support \"generateKey\" operation",
5116 algorithm_name.as_str()
5117 )))),
5118 }
5119 }
5120
5121 fn name(&self) -> CryptoAlgorithm {
5122 match self {
5123 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5124 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5125 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5126 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5127 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5128 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5129 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5130 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5131 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5132 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5133 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5134 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5135 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5136 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5137 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5138 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5139 }
5140 }
5141}
5142
5143impl GenerateKeyAlgorithm {
5144 fn generate_key(
5145 &self,
5146 cx: &mut js::context::JSContext,
5147 global: &GlobalScope,
5148 extractable: bool,
5149 usages: Vec<KeyUsage>,
5150 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5151 match self {
5152 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5153 rsassa_pkcs1_v1_5_operation::generate_key(
5154 cx,
5155 global,
5156 algorithm,
5157 extractable,
5158 usages,
5159 )
5160 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5161 },
5162 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5163 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5164 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5165 },
5166 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5167 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5168 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5169 },
5170 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5171 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5172 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5173 },
5174 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5175 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5176 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5177 },
5178 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5179 ed25519_operation::generate_key(cx, global, extractable, usages)
5180 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5181 },
5182 GenerateKeyAlgorithm::X25519(_algorithm) => {
5183 x25519_operation::generate_key(cx, global, extractable, usages)
5184 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5185 },
5186 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5187 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5188 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5189 },
5190 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5191 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5192 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5193 },
5194 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5195 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5196 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5197 },
5198 GenerateKeyAlgorithm::AesKw(algorithm) => {
5199 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5200 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5201 },
5202 GenerateKeyAlgorithm::Hmac(algorithm) => {
5203 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5204 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5205 },
5206 GenerateKeyAlgorithm::MlKem(algorithm) => {
5207 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5208 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5209 },
5210 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5211 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5212 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5213 },
5214 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5215 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5216 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5217 },
5218 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5219 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5220 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5221 },
5222 }
5223 }
5224}
5225
5226struct ImportKeyOperation {}
5228
5229impl Operation for ImportKeyOperation {
5230 type RegisteredAlgorithm = ImportKeyAlgorithm;
5231}
5232
5233enum ImportKeyAlgorithm {
5236 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
5237 RsaPss(SubtleRsaHashedImportParams),
5238 RsaOaep(SubtleRsaHashedImportParams),
5239 Ecdsa(SubtleEcKeyImportParams),
5240 Ecdh(SubtleEcKeyImportParams),
5241 Ed25519(SubtleAlgorithm),
5242 X25519(SubtleAlgorithm),
5243 AesCtr(SubtleAlgorithm),
5244 AesCbc(SubtleAlgorithm),
5245 AesGcm(SubtleAlgorithm),
5246 AesKw(SubtleAlgorithm),
5247 Hmac(SubtleHmacImportParams),
5248 Hkdf(SubtleAlgorithm),
5249 Pbkdf2(SubtleAlgorithm),
5250 MlKem(SubtleAlgorithm),
5251 MlDsa(SubtleAlgorithm),
5252 AesOcb(SubtleAlgorithm),
5253 ChaCha20Poly1305(SubtleAlgorithm),
5254 Argon2(SubtleAlgorithm),
5255}
5256
5257impl NormalizedAlgorithm for ImportKeyAlgorithm {
5258 fn from_object(
5259 cx: &mut js::context::JSContext,
5260 algorithm_name: CryptoAlgorithm,
5261 object: HandleObject,
5262 ) -> Fallible<Self> {
5263 match algorithm_name {
5264 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5265 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5266 )),
5267 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5268 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5269 )),
5270 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5271 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5272 )),
5273 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5274 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5275 )),
5276 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5277 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5278 )),
5279 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5280 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5281 )),
5282 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5283 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5284 )),
5285 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5286 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5287 )),
5288 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5289 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5290 )),
5291 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5292 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5293 )),
5294 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5295 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5296 )),
5297 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5298 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5299 )),
5300 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5301 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5302 )),
5303 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5304 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5305 )),
5306 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5307 Ok(ImportKeyAlgorithm::MlKem(
5308 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5309 ))
5310 },
5311 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5312 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5313 ),
5314 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5315 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5316 )),
5317 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5318 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5319 )),
5320 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5321 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5322 ),
5323 _ => Err(Error::NotSupported(Some(format!(
5324 "{} does not support \"importKey\" operation",
5325 algorithm_name.as_str()
5326 )))),
5327 }
5328 }
5329
5330 fn name(&self) -> CryptoAlgorithm {
5331 match self {
5332 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5333 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5334 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5335 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5336 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5337 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5338 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5339 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5340 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5341 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5342 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5343 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5344 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
5345 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5346 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5347 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5348 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5349 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5350 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
5351 }
5352 }
5353}
5354
5355impl ImportKeyAlgorithm {
5356 fn import_key(
5357 &self,
5358 cx: &mut js::context::JSContext,
5359 global: &GlobalScope,
5360 format: KeyFormat,
5361 key_data: &[u8],
5362 extractable: bool,
5363 usages: Vec<KeyUsage>,
5364 ) -> Result<DomRoot<CryptoKey>, Error> {
5365 match self {
5366 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5367 rsassa_pkcs1_v1_5_operation::import_key(
5368 cx,
5369 global,
5370 algorithm,
5371 format,
5372 key_data,
5373 extractable,
5374 usages,
5375 )
5376 },
5377 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
5378 cx,
5379 global,
5380 algorithm,
5381 format,
5382 key_data,
5383 extractable,
5384 usages,
5385 ),
5386 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
5387 cx,
5388 global,
5389 algorithm,
5390 format,
5391 key_data,
5392 extractable,
5393 usages,
5394 ),
5395 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
5396 cx,
5397 global,
5398 algorithm,
5399 format,
5400 key_data,
5401 extractable,
5402 usages,
5403 ),
5404 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
5405 cx,
5406 global,
5407 algorithm,
5408 format,
5409 key_data,
5410 extractable,
5411 usages,
5412 ),
5413 ImportKeyAlgorithm::Ed25519(_algorithm) => {
5414 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5415 },
5416 ImportKeyAlgorithm::X25519(_algorithm) => {
5417 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5418 },
5419 ImportKeyAlgorithm::AesCtr(_algorithm) => {
5420 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
5421 },
5422 ImportKeyAlgorithm::AesCbc(_algorithm) => {
5423 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
5424 },
5425 ImportKeyAlgorithm::AesGcm(_algorithm) => {
5426 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
5427 },
5428 ImportKeyAlgorithm::AesKw(_algorithm) => {
5429 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
5430 },
5431 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
5432 cx,
5433 global,
5434 algorithm,
5435 format,
5436 key_data,
5437 extractable,
5438 usages,
5439 ),
5440 ImportKeyAlgorithm::Hkdf(_algorithm) => {
5441 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
5442 },
5443 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
5444 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
5445 },
5446 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
5447 cx,
5448 global,
5449 algorithm,
5450 format,
5451 key_data,
5452 extractable,
5453 usages,
5454 ),
5455 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
5456 cx,
5457 global,
5458 algorithm,
5459 format,
5460 key_data,
5461 extractable,
5462 usages,
5463 ),
5464 ImportKeyAlgorithm::AesOcb(_algorithm) => {
5465 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
5466 },
5467 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5468 chacha20_poly1305_operation::import_key(
5469 cx,
5470 global,
5471 format,
5472 key_data,
5473 extractable,
5474 usages,
5475 )
5476 },
5477 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
5478 cx,
5479 global,
5480 algorithm,
5481 format,
5482 key_data,
5483 extractable,
5484 usages,
5485 ),
5486 }
5487 }
5488}
5489
5490struct ExportKeyOperation {}
5492
5493impl Operation for ExportKeyOperation {
5494 type RegisteredAlgorithm = ExportKeyAlgorithm;
5495}
5496
5497enum ExportKeyAlgorithm {
5500 RsassaPkcs1V1_5(SubtleAlgorithm),
5501 RsaPss(SubtleAlgorithm),
5502 RsaOaep(SubtleAlgorithm),
5503 Ecdsa(SubtleAlgorithm),
5504 Ecdh(SubtleAlgorithm),
5505 Ed25519(SubtleAlgorithm),
5506 X25519(SubtleAlgorithm),
5507 AesCtr(SubtleAlgorithm),
5508 AesCbc(SubtleAlgorithm),
5509 AesGcm(SubtleAlgorithm),
5510 AesKw(SubtleAlgorithm),
5511 Hmac(SubtleAlgorithm),
5512 MlKem(SubtleAlgorithm),
5513 MlDsa(SubtleAlgorithm),
5514 AesOcb(SubtleAlgorithm),
5515 ChaCha20Poly1305(SubtleAlgorithm),
5516}
5517
5518impl NormalizedAlgorithm for ExportKeyAlgorithm {
5519 fn from_object(
5520 cx: &mut js::context::JSContext,
5521 algorithm_name: CryptoAlgorithm,
5522 object: HandleObject,
5523 ) -> Fallible<Self> {
5524 match algorithm_name {
5525 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
5526 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5527 )),
5528 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
5529 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5530 )),
5531 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
5532 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5533 )),
5534 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
5535 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5536 )),
5537 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
5538 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5539 )),
5540 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
5541 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5542 )),
5543 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
5544 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5545 )),
5546 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
5547 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5548 )),
5549 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
5550 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5551 )),
5552 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
5553 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5554 )),
5555 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
5556 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5557 )),
5558 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
5559 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5560 )),
5561 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5562 Ok(ExportKeyAlgorithm::MlKem(
5563 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5564 ))
5565 },
5566 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5567 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5568 ),
5569 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
5570 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5571 )),
5572 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
5573 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5574 )),
5575 _ => Err(Error::NotSupported(Some(format!(
5576 "{} does not support \"exportKey\" operation",
5577 algorithm_name.as_str()
5578 )))),
5579 }
5580 }
5581
5582 fn name(&self) -> CryptoAlgorithm {
5583 match self {
5584 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5585 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5586 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5587 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5588 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5589 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5590 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5591 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5592 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5593 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5594 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5595 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5596 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5597 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5598 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5599 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5600 }
5601 }
5602}
5603
5604impl ExportKeyAlgorithm {
5605 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
5606 match self {
5607 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5608 rsassa_pkcs1_v1_5_operation::export_key(format, key)
5609 },
5610 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
5611 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
5612 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
5613 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
5614 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
5615 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
5616 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
5617 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
5618 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
5619 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
5620 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
5621 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
5622 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
5623 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
5624 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5625 chacha20_poly1305_operation::export_key(format, key)
5626 },
5627 }
5628 }
5629}
5630
5631struct GetKeyLengthOperation {}
5633
5634impl Operation for GetKeyLengthOperation {
5635 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
5636}
5637
5638enum GetKeyLengthAlgorithm {
5641 AesCtr(SubtleAesDerivedKeyParams),
5642 AesCbc(SubtleAesDerivedKeyParams),
5643 AesGcm(SubtleAesDerivedKeyParams),
5644 AesKw(SubtleAesDerivedKeyParams),
5645 Hmac(SubtleHmacImportParams),
5646 Hkdf(SubtleAlgorithm),
5647 Pbkdf2(SubtleAlgorithm),
5648 AesOcb(SubtleAesDerivedKeyParams),
5649 ChaCha20Poly1305(SubtleAlgorithm),
5650 Argon2(SubtleAlgorithm),
5651}
5652
5653impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
5654 fn from_object(
5655 cx: &mut js::context::JSContext,
5656 algorithm_name: CryptoAlgorithm,
5657 object: HandleObject,
5658 ) -> Fallible<Self> {
5659 match algorithm_name {
5660 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
5661 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5662 )),
5663 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
5664 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5665 )),
5666 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
5667 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5668 )),
5669 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
5670 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5671 )),
5672 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
5673 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5674 )),
5675 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
5676 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5677 )),
5678 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
5679 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5680 )),
5681 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
5682 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5683 )),
5684 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
5685 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5686 )),
5687 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
5688 Ok(GetKeyLengthAlgorithm::Argon2(
5689 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5690 ))
5691 },
5692 _ => Err(Error::NotSupported(Some(format!(
5693 "{} does not support \"get key length\" operation",
5694 algorithm_name.as_str()
5695 )))),
5696 }
5697 }
5698
5699 fn name(&self) -> CryptoAlgorithm {
5700 match self {
5701 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
5702 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
5703 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
5704 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
5705 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
5706 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
5707 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5708 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
5709 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5710 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
5711 }
5712 }
5713}
5714
5715impl GetKeyLengthAlgorithm {
5716 fn get_key_length(&self) -> Result<Option<u32>, Error> {
5717 match self {
5718 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
5719 aes_ctr_operation::get_key_length(algorithm)
5720 },
5721 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
5722 aes_cbc_operation::get_key_length(algorithm)
5723 },
5724 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
5725 aes_gcm_operation::get_key_length(algorithm)
5726 },
5727 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
5728 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
5729 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
5730 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
5731 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
5732 aes_ocb_operation::get_key_length(algorithm)
5733 },
5734 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
5735 chacha20_poly1305_operation::get_key_length()
5736 },
5737 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
5738 }
5739 }
5740}
5741
5742struct EncapsulateOperation {}
5744
5745impl Operation for EncapsulateOperation {
5746 type RegisteredAlgorithm = EncapsulateAlgorithm;
5747}
5748
5749enum EncapsulateAlgorithm {
5752 MlKem(SubtleAlgorithm),
5753}
5754
5755impl NormalizedAlgorithm for EncapsulateAlgorithm {
5756 fn from_object(
5757 cx: &mut js::context::JSContext,
5758 algorithm_name: CryptoAlgorithm,
5759 object: HandleObject,
5760 ) -> Fallible<Self> {
5761 match algorithm_name {
5762 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5763 Ok(EncapsulateAlgorithm::MlKem(
5764 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5765 ))
5766 },
5767 _ => Err(Error::NotSupported(Some(format!(
5768 "{} does not support \"encapsulate\" operation",
5769 algorithm_name.as_str()
5770 )))),
5771 }
5772 }
5773
5774 fn name(&self) -> CryptoAlgorithm {
5775 match self {
5776 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
5777 }
5778 }
5779}
5780
5781impl EncapsulateAlgorithm {
5782 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
5783 match self {
5784 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
5785 }
5786 }
5787}
5788
5789struct DecapsulateOperation {}
5791
5792impl Operation for DecapsulateOperation {
5793 type RegisteredAlgorithm = DecapsulateAlgorithm;
5794}
5795
5796enum DecapsulateAlgorithm {
5799 MlKem(SubtleAlgorithm),
5800}
5801
5802impl NormalizedAlgorithm for DecapsulateAlgorithm {
5803 fn from_object(
5804 cx: &mut js::context::JSContext,
5805 algorithm_name: CryptoAlgorithm,
5806 object: HandleObject,
5807 ) -> Fallible<Self> {
5808 match algorithm_name {
5809 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5810 Ok(DecapsulateAlgorithm::MlKem(
5811 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5812 ))
5813 },
5814 _ => Err(Error::NotSupported(Some(format!(
5815 "{} does not support \"decapsulate\" operation",
5816 algorithm_name.as_str()
5817 )))),
5818 }
5819 }
5820
5821 fn name(&self) -> CryptoAlgorithm {
5822 match self {
5823 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
5824 }
5825 }
5826}
5827
5828impl DecapsulateAlgorithm {
5829 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5830 match self {
5831 DecapsulateAlgorithm::MlKem(algorithm) => {
5832 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
5833 },
5834 }
5835 }
5836}
5837
5838struct GetPublicKeyOperation {}
5840
5841impl Operation for GetPublicKeyOperation {
5842 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
5843}
5844
5845enum GetPublicKeyAlgorithm {
5848 RsassaPkcs1v1_5(SubtleAlgorithm),
5849 RsaPss(SubtleAlgorithm),
5850 RsaOaep(SubtleAlgorithm),
5851 Ecdsa(SubtleAlgorithm),
5852 Ecdh(SubtleAlgorithm),
5853 Ed25519(SubtleAlgorithm),
5854 X25519(SubtleAlgorithm),
5855}
5856
5857impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
5858 fn from_object(
5859 cx: &mut js::context::JSContext,
5860 algorithm_name: CryptoAlgorithm,
5861 object: HandleObject,
5862 ) -> Fallible<Self> {
5863 match algorithm_name {
5864 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
5865 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5866 )),
5867 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
5868 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5869 )),
5870 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
5871 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5872 )),
5873 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
5874 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5875 )),
5876 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
5877 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5878 )),
5879 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
5880 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5881 )),
5882 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
5883 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5884 )),
5885 _ => Err(Error::NotSupported(Some(format!(
5886 "{} does not support \"getPublicKey\" operation",
5887 algorithm_name.as_str()
5888 )))),
5889 }
5890 }
5891
5892 fn name(&self) -> CryptoAlgorithm {
5893 match self {
5894 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
5895 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5896 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5897 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5898 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5899 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5900 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
5901 }
5902 }
5903}
5904
5905impl GetPublicKeyAlgorithm {
5906 fn get_public_key(
5907 &self,
5908 cx: &mut js::context::JSContext,
5909 global: &GlobalScope,
5910 key: &CryptoKey,
5911 algorithm: &KeyAlgorithmAndDerivatives,
5912 usages: Vec<KeyUsage>,
5913 ) -> Result<DomRoot<CryptoKey>, Error> {
5914 match self {
5915 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
5916 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
5917 },
5918 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
5919 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
5920 },
5921 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
5922 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
5923 },
5924 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
5925 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
5926 },
5927 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
5928 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
5929 },
5930 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
5931 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
5932 },
5933 GetPublicKeyAlgorithm::X25519(_algorithm) => {
5934 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
5935 },
5936 }
5937 }
5938}