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 x25519_operation;
30
31use std::fmt::Display;
32use std::ptr;
33use std::rc::Rc;
34use std::str::FromStr;
35
36use base64ct::{Base64UrlUnpadded, Encoding};
37use dom_struct::dom_struct;
38use js::conversions::ConversionResult;
39use js::jsapi::{Heap, JSObject};
40use js::jsval::{ObjectValue, UndefinedValue};
41use js::realm::CurrentRealm;
42use js::rust::wrappers2::JS_ParseJSON;
43use js::rust::{HandleValue, MutableHandleValue};
44use js::typedarray::ArrayBufferU8;
45use strum::{EnumString, IntoStaticStr, VariantArray};
46
47use crate::dom::bindings::buffer_source::create_buffer_source;
48use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
49 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
50};
51use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
52 AeadParams, AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
53 AesKeyGenParams, Algorithm, AlgorithmIdentifier, Argon2Params, CShakeParams, ContextParams,
54 EcKeyAlgorithm, EcKeyGenParams, EcKeyImportParams, EcdhKeyDeriveParams, EcdsaParams,
55 EncapsulatedBits, EncapsulatedKey, HkdfParams, HmacImportParams, HmacKeyAlgorithm,
56 HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, RsaHashedImportParams,
57 RsaHashedKeyAlgorithm, RsaHashedKeyGenParams, RsaKeyAlgorithm, RsaOaepParams, RsaPssParams,
58 SubtleCryptoMethods,
59};
60use crate::dom::bindings::codegen::UnionTypes::{
61 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
62};
63use crate::dom::bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
64use crate::dom::bindings::error::{Error, Fallible};
65use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
66use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_cx};
67use crate::dom::bindings::root::DomRoot;
68use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
69use crate::dom::bindings::trace::RootedTraceableBox;
70use crate::dom::bindings::utils::set_dictionary_property;
71use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
72use crate::dom::globalscope::GlobalScope;
73use crate::dom::promise::Promise;
74use crate::script_runtime::{CanGc, JSContext};
75
76const NAMED_CURVE_P256: &str = "P-256";
78const NAMED_CURVE_P384: &str = "P-384";
79const NAMED_CURVE_P521: &str = "P-521";
80
81static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
82
83#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
84enum CryptoAlgorithm {
85 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
86 RsassaPkcs1V1_5,
87 #[strum(serialize = "RSA-PSS")]
88 RsaPss,
89 #[strum(serialize = "RSA-OAEP")]
90 RsaOaep,
91 #[strum(serialize = "ECDSA")]
92 Ecdsa,
93 #[strum(serialize = "ECDH")]
94 Ecdh,
95 #[strum(serialize = "Ed25519")]
96 Ed25519,
97 #[strum(serialize = "X25519")]
98 X25519,
99 #[strum(serialize = "AES-CTR")]
100 AesCtr,
101 #[strum(serialize = "AES-CBC")]
102 AesCbc,
103 #[strum(serialize = "AES-GCM")]
104 AesGcm,
105 #[strum(serialize = "AES-KW")]
106 AesKw,
107 #[strum(serialize = "HMAC")]
108 Hmac,
109 #[strum(serialize = "SHA-1")]
110 Sha1,
111 #[strum(serialize = "SHA-256")]
112 Sha256,
113 #[strum(serialize = "SHA-384")]
114 Sha384,
115 #[strum(serialize = "SHA-512")]
116 Sha512,
117 #[strum(serialize = "HKDF")]
118 Hkdf,
119 #[strum(serialize = "PBKDF2")]
120 Pbkdf2,
121 #[strum(serialize = "ML-KEM-512")]
122 MlKem512,
123 #[strum(serialize = "ML-KEM-768")]
124 MlKem768,
125 #[strum(serialize = "ML-KEM-1024")]
126 MlKem1024,
127 #[strum(serialize = "ML-DSA-44")]
128 MlDsa44,
129 #[strum(serialize = "ML-DSA-65")]
130 MlDsa65,
131 #[strum(serialize = "ML-DSA-87")]
132 MlDsa87,
133 #[strum(serialize = "AES-OCB")]
134 AesOcb,
135 #[strum(serialize = "ChaCha20-Poly1305")]
136 ChaCha20Poly1305,
137 #[strum(serialize = "SHA3-256")]
138 Sha3_256,
139 #[strum(serialize = "SHA3-384")]
140 Sha3_384,
141 #[strum(serialize = "SHA3-512")]
142 Sha3_512,
143 #[strum(serialize = "cSHAKE128")]
144 CShake128,
145 #[strum(serialize = "cSHAKE256")]
146 CShake256,
147 #[strum(serialize = "Argon2d")]
148 Argon2D,
149 #[strum(serialize = "Argon2i")]
150 Argon2I,
151 #[strum(serialize = "Argon2id")]
152 Argon2ID,
153}
154
155impl CryptoAlgorithm {
156 fn as_str(&self) -> &'static str {
158 (*self).into()
159 }
160
161 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
162 Self::VARIANTS
163 .iter()
164 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
165 .cloned()
166 .ok_or(Error::NotSupported(Some(format!(
167 "Unsupported algorithm: {algorithm_name}"
168 ))))
169 }
170
171 fn from_domstring(name: &DOMString) -> Fallible<Self> {
172 CryptoAlgorithm::try_from(&*name.str()).map_err(|_| Error::NotSupported(None))
173 }
174}
175
176#[dom_struct]
177pub(crate) struct SubtleCrypto {
178 reflector_: Reflector,
179}
180
181impl SubtleCrypto {
182 fn new_inherited() -> SubtleCrypto {
183 SubtleCrypto {
184 reflector_: Reflector::new(),
185 }
186 }
187
188 pub(crate) fn new(
189 cx: &mut js::context::JSContext,
190 global: &GlobalScope,
191 ) -> DomRoot<SubtleCrypto> {
192 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
193 }
194
195 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Vec<u8>) {
199 let trusted_promise = TrustedPromise::new(promise);
200 self.global()
201 .task_manager()
202 .crypto_task_source()
203 .queue(task!(resolve_data: move |cx| {
204 let promise = trusted_promise.root();
205
206 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
207 match create_buffer_source::<ArrayBufferU8>(
208 cx.into(),
209 &data,
210 array_buffer_ptr.handle_mut(),
211 CanGc::from_cx(cx),
212 ) {
213 Ok(_) => promise.resolve_native(&*array_buffer_ptr, CanGc::from_cx(cx)),
214 Err(_) => promise.reject_error(Error::JSFailed, CanGc::from_cx(cx)),
215 }
216 }));
217 }
218
219 fn resolve_promise_with_jwk(
223 &self,
224 cx: &mut js::context::JSContext,
225 promise: Rc<Promise>,
226 jwk: Box<JsonWebKey>,
227 ) {
228 let stringified_jwk = match jwk.stringify(cx) {
231 Ok(stringified_jwk) => stringified_jwk.to_string(),
232 Err(error) => {
233 self.reject_promise_with_error(promise, error);
234 return;
235 },
236 };
237
238 let trusted_subtle = Trusted::new(self);
239 let trusted_promise = TrustedPromise::new(promise);
240 self.global()
241 .task_manager()
242 .crypto_task_source()
243 .queue(task!(resolve_jwk: move |cx| {
244 let subtle = trusted_subtle.root();
245 let promise = trusted_promise.root();
246
247 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
248 Ok(jwk) => {
249 rooted!(&in(cx) let mut rval = UndefinedValue());
250 jwk.safe_to_jsval(cx.into(), rval.handle_mut(), CanGc::from_cx(cx));
251 rooted!(&in(cx) let mut object = rval.to_object());
252 promise.resolve_native(&*object, CanGc::from_cx(cx));
253 },
254 Err(error) => {
255 subtle.reject_promise_with_error(promise, error);
256 return;
257 },
258 }
259 }));
260 }
261
262 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: DomRoot<CryptoKey>) {
265 let trusted_key = Trusted::new(&*key);
266 let trusted_promise = TrustedPromise::new(promise);
267 self.global()
268 .task_manager()
269 .crypto_task_source()
270 .queue(task!(resolve_key: move |cx| {
271 let key = trusted_key.root();
272 let promise = trusted_promise.root();
273 promise.resolve_native(&key, CanGc::from_cx(cx));
274 }));
275 }
276
277 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
280 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
281 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
282 let trusted_promise = TrustedPromise::new(promise);
283 self.global()
284 .task_manager()
285 .crypto_task_source()
286 .queue(task!(resolve_key: move |cx| {
287 let key_pair = CryptoKeyPair {
288 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
289 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
290 };
291 let promise = trusted_promise.root();
292 promise.resolve_native(&key_pair, CanGc::from_cx(cx));
293 }));
294 }
295
296 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
299 let trusted_promise = TrustedPromise::new(promise);
300 self.global()
301 .task_manager()
302 .crypto_task_source()
303 .queue(task!(resolve_bool: move |cx| {
304 let promise = trusted_promise.root();
305 promise.resolve_native(&result, CanGc::from_cx(cx));
306 }));
307 }
308
309 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
312 let trusted_promise = TrustedPromise::new(promise);
313 self.global()
314 .task_manager()
315 .crypto_task_source()
316 .queue(task!(reject_error: move |cx| {
317 let promise = trusted_promise.root();
318 promise.reject_error(error, CanGc::from_cx(cx));
319 }));
320 }
321
322 fn resolve_promise_with_encapsulated_key(
326 &self,
327 promise: Rc<Promise>,
328 encapsulated_key: SubtleEncapsulatedKey,
329 ) {
330 let trusted_promise = TrustedPromise::new(promise);
331 self.global().task_manager().crypto_task_source().queue(
332 task!(resolve_encapsulated_key: move |cx| {
333 let promise = trusted_promise.root();
334 promise.resolve_native(&encapsulated_key, CanGc::from_cx(cx));
335 }),
336 );
337 }
338
339 fn resolve_promise_with_encapsulated_bits(
343 &self,
344 promise: Rc<Promise>,
345 encapsulated_bits: SubtleEncapsulatedBits,
346 ) {
347 let trusted_promise = TrustedPromise::new(promise);
348 self.global().task_manager().crypto_task_source().queue(
349 task!(resolve_encapsulated_bits: move |cx| {
350 let promise = trusted_promise.root();
351 promise.resolve_native(&encapsulated_bits, CanGc::from_cx(cx));
352 }),
353 );
354 }
355}
356
357impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
358 fn Encrypt(
360 &self,
361 cx: &mut CurrentRealm,
362 algorithm: AlgorithmIdentifier,
363 key: &CryptoKey,
364 data: ArrayBufferViewOrArrayBuffer,
365 ) -> Rc<Promise> {
366 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
374 Ok(normalized_algorithm) => normalized_algorithm,
375 Err(error) => {
376 let promise = Promise::new_in_realm(cx);
377 promise.reject_error(error, CanGc::from_cx(cx));
378 return promise;
379 },
380 };
381
382 let data = match data {
385 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
386 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
387 };
388
389 let promise = Promise::new_in_realm(cx);
392
393 let this = Trusted::new(self);
395 let trusted_promise = TrustedPromise::new(promise.clone());
396 let trusted_key = Trusted::new(key);
397 self.global()
398 .task_manager()
399 .dom_manipulation_task_source()
400 .queue(task!(encrypt: move || {
401 let subtle = this.root();
402 let promise = trusted_promise.root();
403 let key = trusted_key.root();
404
405 if normalized_algorithm.name() != key.algorithm().name() {
413 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
414 return;
415 }
416
417 if !key.usages().contains(&KeyUsage::Encrypt) {
420 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
421 return;
422 }
423
424 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
428 Ok(ciphertext) => ciphertext,
429 Err(error) => {
430 subtle.reject_promise_with_error(promise, error);
431 return;
432 },
433 };
434
435 subtle.resolve_promise_with_data(promise, ciphertext);
441 }));
442 promise
443 }
444
445 fn Decrypt(
447 &self,
448 cx: &mut CurrentRealm,
449 algorithm: AlgorithmIdentifier,
450 key: &CryptoKey,
451 data: ArrayBufferViewOrArrayBuffer,
452 ) -> Rc<Promise> {
453 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
461 Ok(normalized_algorithm) => normalized_algorithm,
462 Err(error) => {
463 let promise = Promise::new_in_realm(cx);
464 promise.reject_error(error, CanGc::from_cx(cx));
465 return promise;
466 },
467 };
468
469 let data = match data {
472 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
473 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
474 };
475
476 let promise = Promise::new_in_realm(cx);
479
480 let this = Trusted::new(self);
482 let trusted_promise = TrustedPromise::new(promise.clone());
483 let trusted_key = Trusted::new(key);
484 self.global()
485 .task_manager()
486 .dom_manipulation_task_source()
487 .queue(task!(decrypt: move || {
488 let subtle = this.root();
489 let promise = trusted_promise.root();
490 let key = trusted_key.root();
491
492 if normalized_algorithm.name() != key.algorithm().name() {
500 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
501 return;
502 }
503
504 if !key.usages().contains(&KeyUsage::Decrypt) {
507 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
508 return;
509 }
510
511 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
515 Ok(plaintext) => plaintext,
516 Err(error) => {
517 subtle.reject_promise_with_error(promise, error);
518 return;
519 },
520 };
521
522 subtle.resolve_promise_with_data(promise, plaintext);
528 }));
529 promise
530 }
531
532 fn Sign(
534 &self,
535 cx: &mut CurrentRealm,
536 algorithm: AlgorithmIdentifier,
537 key: &CryptoKey,
538 data: ArrayBufferViewOrArrayBuffer,
539 ) -> Rc<Promise> {
540 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
548 Ok(normalized_algorithm) => normalized_algorithm,
549 Err(error) => {
550 let promise = Promise::new_in_realm(cx);
551 promise.reject_error(error, CanGc::from_cx(cx));
552 return promise;
553 },
554 };
555
556 let data = match &data {
559 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
560 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
561 };
562
563 let promise = Promise::new_in_realm(cx);
566
567 let this = Trusted::new(self);
569 let trusted_promise = TrustedPromise::new(promise.clone());
570 let trusted_key = Trusted::new(key);
571 self.global()
572 .task_manager()
573 .dom_manipulation_task_source()
574 .queue(task!(sign: move || {
575 let subtle = this.root();
576 let promise = trusted_promise.root();
577 let key = trusted_key.root();
578
579 if normalized_algorithm.name() != key.algorithm().name() {
587 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
588 return;
589 }
590
591 if !key.usages().contains(&KeyUsage::Sign) {
594 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
595 return;
596 }
597
598 let signature = match normalized_algorithm.sign(&key, &data) {
601 Ok(signature) => signature,
602 Err(error) => {
603 subtle.reject_promise_with_error(promise, error);
604 return;
605 },
606 };
607
608 subtle.resolve_promise_with_data(promise, signature);
614 }));
615 promise
616 }
617
618 fn Verify(
620 &self,
621 cx: &mut CurrentRealm,
622 algorithm: AlgorithmIdentifier,
623 key: &CryptoKey,
624 signature: ArrayBufferViewOrArrayBuffer,
625 data: ArrayBufferViewOrArrayBuffer,
626 ) -> Rc<Promise> {
627 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
635 Ok(algorithm) => algorithm,
636 Err(error) => {
637 let promise = Promise::new_in_realm(cx);
638 promise.reject_error(error, CanGc::from_cx(cx));
639 return promise;
640 },
641 };
642
643 let signature = match &signature {
646 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
647 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
648 };
649
650 let data = match &data {
653 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
654 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
655 };
656
657 let promise = Promise::new_in_realm(cx);
660
661 let this = Trusted::new(self);
663 let trusted_promise = TrustedPromise::new(promise.clone());
664 let trusted_key = Trusted::new(key);
665 self.global()
666 .task_manager()
667 .dom_manipulation_task_source()
668 .queue(task!(sign: move || {
669 let subtle = this.root();
670 let promise = trusted_promise.root();
671 let key = trusted_key.root();
672
673 if normalized_algorithm.name() != key.algorithm().name() {
681 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
682 return;
683 }
684
685 if !key.usages().contains(&KeyUsage::Verify) {
688 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
689 return;
690 }
691
692 let result = match normalized_algorithm.verify(&key, &data, &signature) {
696 Ok(result) => result,
697 Err(error) => {
698 subtle.reject_promise_with_error(promise, error);
699 return;
700 },
701 };
702
703 subtle.resolve_promise_with_bool(promise, result);
707 }));
708 promise
709 }
710
711 fn Digest(
713 &self,
714 cx: &mut CurrentRealm,
715 algorithm: AlgorithmIdentifier,
716 data: ArrayBufferViewOrArrayBuffer,
717 ) -> Rc<Promise> {
718 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
725 Ok(normalized_algorithm) => normalized_algorithm,
726 Err(error) => {
727 let promise = Promise::new_in_realm(cx);
728 promise.reject_error(error, CanGc::from_cx(cx));
729 return promise;
730 },
731 };
732
733 let data = match data {
736 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
737 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
738 };
739
740 let promise = Promise::new_in_realm(cx);
743
744 let this = Trusted::new(self);
746 let trusted_promise = TrustedPromise::new(promise.clone());
747 self.global()
748 .task_manager()
749 .dom_manipulation_task_source()
750 .queue(task!(digest_: move || {
751 let subtle = this.root();
752 let promise = trusted_promise.root();
753
754 let digest = match normalized_algorithm.digest(&data) {
761 Ok(digest) => digest,
762 Err(error) => {
763 subtle.reject_promise_with_error(promise, error);
764 return;
765 }
766 };
767
768 subtle.resolve_promise_with_data(promise, digest);
774 }));
775 promise
776 }
777
778 fn GenerateKey(
780 &self,
781 cx: &mut CurrentRealm,
782 algorithm: AlgorithmIdentifier,
783 extractable: bool,
784 key_usages: Vec<KeyUsage>,
785 ) -> Rc<Promise> {
786 let promise = Promise::new_in_realm(cx);
793 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
794 {
795 Ok(normalized_algorithm) => normalized_algorithm,
796 Err(error) => {
797 promise.reject_error(error, CanGc::from_cx(cx));
798 return promise;
799 },
800 };
801
802 let trusted_subtle = Trusted::new(self);
808 let trusted_promise = TrustedPromise::new(promise.clone());
809 self.global()
810 .task_manager()
811 .dom_manipulation_task_source()
812 .queue(task!(generate_key: move |cx| {
813 let subtle = trusted_subtle.root();
814 let promise = trusted_promise.root();
815
816 let result = match normalized_algorithm.generate_key(
823 cx,
824 &subtle.global(),
825 extractable,
826 key_usages,
827 ) {
828 Ok(result) => result,
829 Err(error) => {
830 subtle.reject_promise_with_error(promise, error);
831 return;
832 }
833 };
834
835 match &result {
843 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
844 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
845 && crpyto_key.usages().is_empty()
846 {
847 subtle.reject_promise_with_error(promise, Error::Syntax(None));
848 return;
849 }
850 },
851 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
852 if crypto_key_pair
853 .privateKey
854 .as_ref()
855 .is_none_or(|private_key| private_key.usages().is_empty())
856 {
857 subtle.reject_promise_with_error(promise, Error::Syntax(None));
858 return;
859 }
860 }
861 };
862
863 match result {
869 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
870 subtle.resolve_promise_with_key(promise, key);
871 },
872 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
873 subtle.resolve_promise_with_key_pair(promise, key_pair);
874 },
875 }
876 }));
877
878 promise
879 }
880
881 fn DeriveKey(
883 &self,
884 cx: &mut CurrentRealm,
885 algorithm: AlgorithmIdentifier,
886 base_key: &CryptoKey,
887 derived_key_type: AlgorithmIdentifier,
888 extractable: bool,
889 usages: Vec<KeyUsage>,
890 ) -> Rc<Promise> {
891 let promise = Promise::new_in_realm(cx);
900 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
901 {
902 Ok(normalized_algorithm) => normalized_algorithm,
903 Err(error) => {
904 promise.reject_error(error, CanGc::from_cx(cx));
905 return promise;
906 },
907 };
908
909 let normalized_derived_key_algorithm_import =
914 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
915 Ok(normalized_algorithm) => normalized_algorithm,
916 Err(error) => {
917 promise.reject_error(error, CanGc::from_cx(cx));
918 return promise;
919 },
920 };
921
922 let normalized_derived_key_algorithm_length =
927 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
928 Ok(normalized_algorithm) => normalized_algorithm,
929 Err(error) => {
930 promise.reject_error(error, CanGc::from_cx(cx));
931 return promise;
932 },
933 };
934
935 let trusted_subtle = Trusted::new(self);
941 let trusted_base_key = Trusted::new(base_key);
942 let trusted_promise = TrustedPromise::new(promise.clone());
943 self.global().task_manager().dom_manipulation_task_source().queue(
944 task!(derive_key: move |cx| {
945 let subtle = trusted_subtle.root();
946 let base_key = trusted_base_key.root();
947 let promise = trusted_promise.root();
948
949 if normalized_algorithm.name() != base_key.algorithm().name() {
957 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
958 return;
959 }
960
961 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
964 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
965 return;
966 }
967
968 let length = match normalized_derived_key_algorithm_length.get_key_length() {
971 Ok(length) => length,
972 Err(error) => {
973 subtle.reject_promise_with_error(promise, error);
974 return;
975 }
976 };
977
978 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
981 Ok(secret) => secret,
982 Err(error) => {
983 subtle.reject_promise_with_error(promise, error);
984 return;
985 }
986 };
987
988 let result = match normalized_derived_key_algorithm_import.import_key(
994 cx,
995 &subtle.global(),
996 KeyFormat::Raw_secret,
997 &secret,
998 extractable,
999 usages.clone(),
1000 ) {
1001 Ok(algorithm) => algorithm,
1002 Err(error) => {
1003 subtle.reject_promise_with_error(promise, error);
1004 return;
1005 },
1006 };
1007
1008 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1011 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1012 return;
1013 }
1014
1015 subtle.resolve_promise_with_key(promise, result);
1026 }),
1027 );
1028 promise
1029 }
1030
1031 fn DeriveBits(
1033 &self,
1034 cx: &mut CurrentRealm,
1035 algorithm: AlgorithmIdentifier,
1036 base_key: &CryptoKey,
1037 length: Option<u32>,
1038 ) -> Rc<Promise> {
1039 let promise = Promise::new_in_realm(cx);
1047 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1048 {
1049 Ok(normalized_algorithm) => normalized_algorithm,
1050 Err(error) => {
1051 promise.reject_error(error, CanGc::from_cx(cx));
1052 return promise;
1053 },
1054 };
1055
1056 let trsuted_subtle = Trusted::new(self);
1062 let trusted_base_key = Trusted::new(base_key);
1063 let trusted_promise = TrustedPromise::new(promise.clone());
1064 self.global()
1065 .task_manager()
1066 .dom_manipulation_task_source()
1067 .queue(task!(import_key: move || {
1068 let subtle = trsuted_subtle.root();
1069 let base_key = trusted_base_key.root();
1070 let promise = trusted_promise.root();
1071
1072 if normalized_algorithm.name() != base_key.algorithm().name() {
1080 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1081 return;
1082 }
1083
1084 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1087 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1088 return;
1089 }
1090
1091 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1094 Ok(bits) => bits,
1095 Err(error) => {
1096 subtle.reject_promise_with_error(promise, error);
1097 return;
1098 }
1099 };
1100
1101 subtle.resolve_promise_with_data(promise, bits);
1107 }));
1108 promise
1109 }
1110
1111 fn ImportKey(
1113 &self,
1114 cx: &mut CurrentRealm,
1115 format: KeyFormat,
1116 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1117 algorithm: AlgorithmIdentifier,
1118 extractable: bool,
1119 key_usages: Vec<KeyUsage>,
1120 ) -> Rc<Promise> {
1121 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1128 Ok(algorithm) => algorithm,
1129 Err(error) => {
1130 let promise = Promise::new_in_realm(cx);
1131 promise.reject_error(error, CanGc::from_cx(cx));
1132 return promise;
1133 },
1134 };
1135
1136 let key_data = match format {
1138 KeyFormat::Jwk => {
1140 match key_data {
1141 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1142 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1143 let promise = Promise::new_in_realm(cx);
1146 promise.reject_error(
1147 Error::Type(c"The keyData type does not match the format".to_owned()),
1148 CanGc::from_cx(cx),
1149 );
1150 return promise;
1151 },
1152
1153 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1154 match jwk.stringify(cx) {
1162 Ok(stringified) => stringified.as_bytes().to_vec(),
1163 Err(error) => {
1164 let promise = Promise::new_in_realm(cx);
1165 promise.reject_error(error, CanGc::from_cx(cx));
1166 return promise;
1167 },
1168 }
1169 },
1170 }
1171 },
1172 _ => {
1174 match key_data {
1175 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1178 let promise = Promise::new_in_realm(cx);
1179 promise.reject_error(
1180 Error::Type(c"The keyData type does not match the format".to_owned()),
1181 CanGc::from_cx(cx),
1182 );
1183 return promise;
1184 },
1185
1186 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1189 view.to_vec()
1190 },
1191 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1192 buffer.to_vec()
1193 },
1194 }
1195 },
1196 };
1197
1198 let promise = Promise::new_in_realm(cx);
1201
1202 let this = Trusted::new(self);
1204 let trusted_promise = TrustedPromise::new(promise.clone());
1205 self.global()
1206 .task_manager()
1207 .dom_manipulation_task_source()
1208 .queue(task!(import_key: move |cx| {
1209 let subtle = this.root();
1210 let promise = trusted_promise.root();
1211
1212 let result = match normalized_algorithm.import_key(
1220 cx,
1221 &subtle.global(),
1222 format,
1223 &key_data,
1224 extractable,
1225 key_usages.clone(),
1226 ) {
1227 Ok(key) => key,
1228 Err(error) => {
1229 subtle.reject_promise_with_error(promise, error);
1230 return;
1231 },
1232 };
1233
1234 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1237 subtle.reject_promise_with_error(promise, Error::Syntax(None));
1238 return;
1239 }
1240
1241 result.set_extractable(extractable);
1243
1244 result.set_usages(cx, &key_usages);
1246
1247 subtle.resolve_promise_with_key(promise, result);
1253 }));
1254
1255 promise
1256 }
1257
1258 fn ExportKey(&self, cx: &mut CurrentRealm, format: KeyFormat, key: &CryptoKey) -> Rc<Promise> {
1260 let promise = Promise::new_in_realm(cx);
1267
1268 let trusted_subtle = Trusted::new(self);
1270 let trusted_promise = TrustedPromise::new(promise.clone());
1271 let trusted_key = Trusted::new(key);
1272 self.global()
1273 .task_manager()
1274 .dom_manipulation_task_source()
1275 .queue(task!(export_key: move |cx| {
1276 let subtle = trusted_subtle.root();
1277 let promise = trusted_promise.root();
1278 let key = trusted_key.root();
1279
1280 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1291 cx,
1292 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1293 ) {
1294 Ok(normalized_algorithm) => normalized_algorithm,
1295 Err(error) => {
1296 subtle.reject_promise_with_error(promise, error);
1297 return;
1298 },
1299 };
1300
1301 if !key.Extractable() {
1304 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1305 return;
1306 }
1307
1308 let result = match export_key_algorithm.export_key(format, &key) {
1311 Ok(exported_key) => exported_key,
1312 Err(error) => {
1313 subtle.reject_promise_with_error(promise, error);
1314 return;
1315 },
1316 };
1317
1318 match result {
1331 ExportedKey::Bytes(bytes) => {
1332 subtle.resolve_promise_with_data(promise, bytes);
1333 },
1334 ExportedKey::Jwk(jwk) => {
1335 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1336 },
1337 }
1338 }));
1339 promise
1340 }
1341
1342 fn WrapKey(
1344 &self,
1345 cx: &mut CurrentRealm,
1346 format: KeyFormat,
1347 key: &CryptoKey,
1348 wrapping_key: &CryptoKey,
1349 algorithm: AlgorithmIdentifier,
1350 ) -> Rc<Promise> {
1351 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1361 WrapKeyAlgorithm(WrapKeyAlgorithm),
1362 EncryptAlgorithm(EncryptAlgorithm),
1363 }
1364 let normalized_algorithm = if let Ok(algorithm) =
1365 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1366 {
1367 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1368 } else {
1369 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1370 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1371 Err(error) => {
1372 let promise = Promise::new_in_realm(cx);
1373 promise.reject_error(error, CanGc::from_cx(cx));
1374 return promise;
1375 },
1376 }
1377 };
1378
1379 let promise = Promise::new_in_realm(cx);
1382
1383 let trusted_subtle = Trusted::new(self);
1385 let trusted_key = Trusted::new(key);
1386 let trusted_wrapping_key = Trusted::new(wrapping_key);
1387 let trusted_promise = TrustedPromise::new(promise.clone());
1388 self.global()
1389 .task_manager()
1390 .dom_manipulation_task_source()
1391 .queue(task!(wrap_key: move |cx| {
1392 let subtle = trusted_subtle.root();
1393 let key = trusted_key.root();
1394 let wrapping_key = trusted_wrapping_key.root();
1395 let promise = trusted_promise.root();
1396
1397 let normalized_algorithm_name = match &normalized_algorithm {
1405 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1406 algorithm.name()
1407 },
1408 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1409 algorithm.name()
1410 },
1411 };
1412 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1413 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1414 return;
1415 }
1416
1417 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1420 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1421 return;
1422 }
1423
1424 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1430 cx,
1431 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1432 ) {
1433 Ok(normalized_algorithm) => normalized_algorithm,
1434 Err(error) => {
1435 subtle.reject_promise_with_error(promise, error);
1436 return;
1437 },
1438 };
1439
1440 if !key.Extractable() {
1443 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1444 return;
1445 }
1446
1447 let exported_key = match export_key_algorithm.export_key(format, &key) {
1450 Ok(exported_key) => exported_key,
1451 Err(error) => {
1452 subtle.reject_promise_with_error(promise, error);
1453 return;
1454 },
1455 };
1456
1457 let bytes = match exported_key {
1469 ExportedKey::Bytes(bytes) => bytes,
1470 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1471 Ok(stringified_jwk) => stringified_jwk.as_bytes().to_vec(),
1472 Err(error) => {
1473 subtle.reject_promise_with_error(promise, error);
1474 return;
1475 },
1476 },
1477 };
1478
1479 let result = match normalized_algorithm {
1491 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1492 algorithm.wrap_key(&wrapping_key, &bytes)
1493 },
1494 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1495 algorithm.encrypt(&wrapping_key, &bytes)
1496 },
1497 };
1498 let result = match result {
1499 Ok(result) => result,
1500 Err(error) => {
1501 subtle.reject_promise_with_error(promise, error);
1502 return;
1503 },
1504 };
1505
1506 subtle.resolve_promise_with_data(promise, result);
1512 }));
1513 promise
1514 }
1515
1516 fn UnwrapKey(
1518 &self,
1519 cx: &mut CurrentRealm,
1520 format: KeyFormat,
1521 wrapped_key: ArrayBufferViewOrArrayBuffer,
1522 unwrapping_key: &CryptoKey,
1523 algorithm: AlgorithmIdentifier,
1524 unwrapped_key_algorithm: AlgorithmIdentifier,
1525 extractable: bool,
1526 usages: Vec<KeyUsage>,
1527 ) -> Rc<Promise> {
1528 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1539 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1540 DecryptAlgorithm(DecryptAlgorithm),
1541 }
1542 let normalized_algorithm = if let Ok(algorithm) =
1543 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1544 {
1545 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1546 } else {
1547 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1548 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1549 Err(error) => {
1550 let promise = Promise::new_in_realm(cx);
1551 promise.reject_error(error, CanGc::from_cx(cx));
1552 return promise;
1553 },
1554 }
1555 };
1556
1557 let normalized_key_algorithm =
1561 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1562 Ok(algorithm) => algorithm,
1563 Err(error) => {
1564 let promise = Promise::new_in_realm(cx);
1565 promise.reject_error(error, CanGc::from_cx(cx));
1566 return promise;
1567 },
1568 };
1569
1570 let wrapped_key = match wrapped_key {
1573 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
1574 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
1575 };
1576
1577 let promise = Promise::new_in_realm(cx);
1580
1581 let trusted_subtle = Trusted::new(self);
1583 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1584 let trusted_promise = TrustedPromise::new(promise.clone());
1585 self.global().task_manager().dom_manipulation_task_source().queue(
1586 task!(unwrap_key: move |cx| {
1587 let subtle = trusted_subtle.root();
1588 let unwrapping_key = trusted_unwrapping_key.root();
1589 let promise = trusted_promise.root();
1590
1591 let normalized_algorithm_name = match &normalized_algorithm {
1599 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1600 algorithm.name()
1601 },
1602 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1603 algorithm.name()
1604 },
1605 };
1606 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1607 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1608 return;
1609 }
1610
1611 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1614 subtle.reject_promise_with_error(promise, Error::InvalidAccess(None));
1615 return;
1616 }
1617
1618 let bytes = match normalized_algorithm {
1630 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1631 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1632 },
1633 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1634 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1635 },
1636 };
1637 let bytes = match bytes {
1638 Ok(bytes) => bytes,
1639 Err(error) => {
1640 subtle.reject_promise_with_error(promise, error);
1641 return;
1642 },
1643 };
1644
1645 if format == KeyFormat::Jwk {
1656 if let Err(error) = JsonWebKey::parse(cx, &bytes) {
1657 subtle.reject_promise_with_error(promise, error);
1658 return;
1659 }
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) => 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) => 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
2276trait TryFromWithCx<T>: Sized {
2278 type Error;
2279
2280 fn try_from_with_cx(value: T, cx: &mut js::context::JSContext) -> Result<Self, Self::Error>;
2281}
2282
2283trait TryIntoWithCx<T>: Sized {
2285 type Error;
2286
2287 fn try_into_with_cx(self, cx: &mut js::context::JSContext) -> Result<T, Self::Error>;
2288}
2289
2290impl<T, U> TryIntoWithCx<U> for T
2291where
2292 U: TryFromWithCx<T>,
2293{
2294 type Error = U::Error;
2295
2296 fn try_into_with_cx(self, cx: &mut js::context::JSContext) -> Result<U, Self::Error> {
2297 U::try_from_with_cx(self, cx)
2298 }
2299}
2300
2301#[derive(Clone, MallocSizeOf)]
2306struct SubtleAlgorithm {
2307 name: CryptoAlgorithm,
2309}
2310
2311impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAlgorithm {
2312 type Error = Error;
2313
2314 fn try_from_with_cx(
2315 value: HandleValue<'a>,
2316 cx: &mut js::context::JSContext,
2317 ) -> Result<Self, Self::Error> {
2318 let dictionary = dictionary_from_jsval::<Algorithm>(cx, value)?;
2319
2320 Ok(SubtleAlgorithm {
2321 name: CryptoAlgorithm::from_domstring(&dictionary.name)?,
2322 })
2323 }
2324}
2325
2326#[derive(Clone, MallocSizeOf)]
2328pub(crate) struct SubtleKeyAlgorithm {
2329 name: CryptoAlgorithm,
2331}
2332
2333impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2334 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2335 let dictionary = KeyAlgorithm {
2336 name: self.name.as_str().into(),
2337 };
2338 dictionary.safe_to_jsval(cx, rval, can_gc);
2339 }
2340}
2341
2342#[derive(Clone, MallocSizeOf)]
2344pub(crate) struct SubtleRsaHashedKeyGenParams {
2345 name: CryptoAlgorithm,
2347
2348 modulus_length: u32,
2350
2351 public_exponent: Vec<u8>,
2353
2354 hash: DigestAlgorithm,
2356}
2357
2358impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleRsaHashedKeyGenParams {
2359 type Error = Error;
2360
2361 fn try_from_with_cx(
2362 value: HandleValue,
2363 cx: &mut js::context::JSContext,
2364 ) -> Result<Self, Self::Error> {
2365 let dictionary =
2366 dictionary_from_jsval::<RootedTraceableBox<RsaHashedKeyGenParams>>(cx, value)?;
2367
2368 Ok(SubtleRsaHashedKeyGenParams {
2369 name: CryptoAlgorithm::from_domstring(&dictionary.parent.parent.name)?,
2370 modulus_length: dictionary.parent.modulusLength,
2371 public_exponent: dictionary.parent.publicExponent.to_vec(),
2372 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2373 })
2374 }
2375}
2376
2377#[derive(Clone, MallocSizeOf)]
2379pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2380 name: CryptoAlgorithm,
2382
2383 modulus_length: u32,
2385
2386 public_exponent: Vec<u8>,
2388
2389 hash: DigestAlgorithm,
2391}
2392
2393impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2394 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2395 rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>());
2396 let public_exponent =
2397 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut(), can_gc)
2398 .expect("Fail to convert publicExponent to Uint8Array");
2399 let key_algorithm = KeyAlgorithm {
2400 name: self.name.as_str().into(),
2401 };
2402 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
2403 parent: key_algorithm,
2404 modulusLength: self.modulus_length,
2405 publicExponent: public_exponent,
2406 });
2407 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
2408 parent: rsa_key_algorithm,
2409 hash: KeyAlgorithm {
2410 name: self.hash.name().as_str().into(),
2411 },
2412 });
2413 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval, can_gc);
2414 }
2415}
2416
2417#[derive(Clone, MallocSizeOf)]
2419struct SubtleRsaHashedImportParams {
2420 name: CryptoAlgorithm,
2422
2423 hash: DigestAlgorithm,
2425}
2426
2427impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleRsaHashedImportParams {
2428 type Error = Error;
2429
2430 fn try_from_with_cx(
2431 value: HandleValue,
2432 cx: &mut js::context::JSContext,
2433 ) -> Result<Self, Self::Error> {
2434 let dictionary =
2435 dictionary_from_jsval::<RootedTraceableBox<RsaHashedImportParams>>(cx, value)?;
2436
2437 Ok(SubtleRsaHashedImportParams {
2438 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2439 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2440 })
2441 }
2442}
2443
2444#[derive(Clone, MallocSizeOf)]
2446struct SubtleRsaPssParams {
2447 name: CryptoAlgorithm,
2449
2450 salt_length: u32,
2452}
2453
2454impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleRsaPssParams {
2455 type Error = Error;
2456
2457 fn try_from_with_cx(
2458 value: HandleValue,
2459 cx: &mut js::context::JSContext,
2460 ) -> Result<Self, Self::Error> {
2461 let dictionary = dictionary_from_jsval::<RsaPssParams>(cx, value)?;
2462
2463 Ok(SubtleRsaPssParams {
2464 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2465 salt_length: dictionary.saltLength,
2466 })
2467 }
2468}
2469
2470#[derive(Clone, MallocSizeOf)]
2472struct SubtleRsaOaepParams {
2473 name: CryptoAlgorithm,
2475
2476 label: Option<Vec<u8>>,
2478}
2479
2480impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleRsaOaepParams {
2481 type Error = Error;
2482
2483 fn try_from_with_cx(
2484 value: HandleValue<'a>,
2485 cx: &mut js::context::JSContext,
2486 ) -> Result<Self, Self::Error> {
2487 let dictionary = dictionary_from_jsval::<RootedTraceableBox<RsaOaepParams>>(cx, value)?;
2488
2489 let label = dictionary.label.as_ref().map(|label| match label {
2490 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2491 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2492 });
2493
2494 Ok(SubtleRsaOaepParams {
2495 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2496 label,
2497 })
2498 }
2499}
2500
2501#[derive(Clone, MallocSizeOf)]
2503struct SubtleEcdsaParams {
2504 name: CryptoAlgorithm,
2506
2507 hash: DigestAlgorithm,
2509}
2510
2511impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleEcdsaParams {
2512 type Error = Error;
2513
2514 fn try_from_with_cx(
2515 value: HandleValue<'a>,
2516 cx: &mut js::context::JSContext,
2517 ) -> Result<Self, Self::Error> {
2518 let dictionary = dictionary_from_jsval::<RootedTraceableBox<EcdsaParams>>(cx, value)?;
2519
2520 Ok(SubtleEcdsaParams {
2521 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2522 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2523 })
2524 }
2525}
2526
2527#[derive(Clone, MallocSizeOf)]
2529struct SubtleEcKeyGenParams {
2530 name: CryptoAlgorithm,
2532
2533 named_curve: String,
2535}
2536
2537impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleEcKeyGenParams {
2538 type Error = Error;
2539
2540 fn try_from_with_cx(
2541 value: HandleValue<'a>,
2542 cx: &mut js::context::JSContext,
2543 ) -> Result<Self, Self::Error> {
2544 let dictionary = dictionary_from_jsval::<EcKeyGenParams>(cx, value)?;
2545
2546 Ok(SubtleEcKeyGenParams {
2547 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2548 named_curve: dictionary.namedCurve.to_string(),
2549 })
2550 }
2551}
2552
2553#[derive(Clone, MallocSizeOf)]
2555pub(crate) struct SubtleEcKeyAlgorithm {
2556 name: CryptoAlgorithm,
2558
2559 named_curve: String,
2561}
2562
2563impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
2564 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2565 let parent = KeyAlgorithm {
2566 name: self.name.as_str().into(),
2567 };
2568 let dictionary = EcKeyAlgorithm {
2569 parent,
2570 namedCurve: self.named_curve.clone().into(),
2571 };
2572 dictionary.safe_to_jsval(cx, rval, can_gc);
2573 }
2574}
2575
2576#[derive(Clone, MallocSizeOf)]
2578struct SubtleEcKeyImportParams {
2579 name: CryptoAlgorithm,
2581
2582 named_curve: String,
2584}
2585
2586impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleEcKeyImportParams {
2587 type Error = Error;
2588
2589 fn try_from_with_cx(
2590 value: HandleValue<'a>,
2591 cx: &mut js::context::JSContext,
2592 ) -> Result<Self, Self::Error> {
2593 let dictionary = dictionary_from_jsval::<EcKeyImportParams>(cx, value)?;
2594
2595 Ok(SubtleEcKeyImportParams {
2596 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2597 named_curve: dictionary.namedCurve.to_string(),
2598 })
2599 }
2600}
2601
2602#[derive(Clone, MallocSizeOf)]
2604struct SubtleEcdhKeyDeriveParams {
2605 name: CryptoAlgorithm,
2607
2608 public: Trusted<CryptoKey>,
2610}
2611
2612impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleEcdhKeyDeriveParams {
2613 type Error = Error;
2614
2615 fn try_from_with_cx(
2616 value: HandleValue<'a>,
2617 cx: &mut js::context::JSContext,
2618 ) -> Result<Self, Self::Error> {
2619 let dictionary = dictionary_from_jsval::<EcdhKeyDeriveParams>(cx, value)?;
2620
2621 Ok(SubtleEcdhKeyDeriveParams {
2622 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2623 public: Trusted::new(&dictionary.public),
2624 })
2625 }
2626}
2627
2628#[derive(Clone, MallocSizeOf)]
2630struct SubtleAesCtrParams {
2631 name: CryptoAlgorithm,
2633
2634 counter: Vec<u8>,
2636
2637 length: u8,
2639}
2640
2641impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAesCtrParams {
2642 type Error = Error;
2643
2644 fn try_from_with_cx(
2645 value: HandleValue<'a>,
2646 cx: &mut js::context::JSContext,
2647 ) -> Result<Self, Self::Error> {
2648 let dictionary = dictionary_from_jsval::<RootedTraceableBox<AesCtrParams>>(cx, value)?;
2649
2650 let counter = match &dictionary.counter {
2651 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2652 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2653 };
2654
2655 Ok(SubtleAesCtrParams {
2656 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2657 counter,
2658 length: dictionary.length,
2659 })
2660 }
2661}
2662
2663#[derive(Clone, MallocSizeOf)]
2665pub(crate) struct SubtleAesKeyAlgorithm {
2666 name: CryptoAlgorithm,
2668
2669 length: u16,
2671}
2672
2673impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
2674 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2675 let parent = KeyAlgorithm {
2676 name: self.name.as_str().into(),
2677 };
2678 let dictionary = AesKeyAlgorithm {
2679 parent,
2680 length: self.length,
2681 };
2682 dictionary.safe_to_jsval(cx, rval, can_gc);
2683 }
2684}
2685
2686#[derive(Clone, MallocSizeOf)]
2688struct SubtleAesKeyGenParams {
2689 name: CryptoAlgorithm,
2691
2692 length: u16,
2694}
2695
2696impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAesKeyGenParams {
2697 type Error = Error;
2698
2699 fn try_from_with_cx(
2700 value: HandleValue<'a>,
2701 cx: &mut js::context::JSContext,
2702 ) -> Result<Self, Self::Error> {
2703 let dictionary = dictionary_from_jsval::<AesKeyGenParams>(cx, value)?;
2704
2705 Ok(SubtleAesKeyGenParams {
2706 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2707 length: dictionary.length,
2708 })
2709 }
2710}
2711
2712#[derive(Clone, MallocSizeOf)]
2714struct SubtleAesDerivedKeyParams {
2715 name: CryptoAlgorithm,
2717
2718 length: u16,
2720}
2721
2722impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAesDerivedKeyParams {
2723 type Error = Error;
2724
2725 fn try_from_with_cx(
2726 value: HandleValue<'a>,
2727 cx: &mut js::context::JSContext,
2728 ) -> Result<Self, Self::Error> {
2729 let dictionary = dictionary_from_jsval::<AesDerivedKeyParams>(cx, value)?;
2730
2731 Ok(SubtleAesDerivedKeyParams {
2732 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2733 length: dictionary.length,
2734 })
2735 }
2736}
2737
2738#[derive(Clone, MallocSizeOf)]
2740struct SubtleAesCbcParams {
2741 name: CryptoAlgorithm,
2743
2744 iv: Vec<u8>,
2746}
2747
2748impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAesCbcParams {
2749 type Error = Error;
2750
2751 fn try_from_with_cx(
2752 value: HandleValue<'a>,
2753 cx: &mut js::context::JSContext,
2754 ) -> Result<Self, Self::Error> {
2755 let dictionary = dictionary_from_jsval::<RootedTraceableBox<AesCbcParams>>(cx, value)?;
2756
2757 let iv = match &dictionary.iv {
2758 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2759 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2760 };
2761
2762 Ok(SubtleAesCbcParams {
2763 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2764 iv,
2765 })
2766 }
2767}
2768
2769#[derive(Clone, MallocSizeOf)]
2771struct SubtleAesGcmParams {
2772 name: CryptoAlgorithm,
2774
2775 iv: Vec<u8>,
2777
2778 additional_data: Option<Vec<u8>>,
2780
2781 tag_length: Option<u8>,
2783}
2784
2785impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAesGcmParams {
2786 type Error = Error;
2787
2788 fn try_from_with_cx(
2789 value: HandleValue<'a>,
2790 cx: &mut js::context::JSContext,
2791 ) -> Result<Self, Self::Error> {
2792 let dictionary = dictionary_from_jsval::<RootedTraceableBox<AesGcmParams>>(cx, value)?;
2793
2794 let iv = match &dictionary.iv {
2795 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2796 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2797 };
2798 let additional_data = dictionary.additionalData.as_ref().map(|data| match data {
2799 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2800 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2801 });
2802
2803 Ok(SubtleAesGcmParams {
2804 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2805 iv,
2806 additional_data,
2807 tag_length: dictionary.tagLength,
2808 })
2809 }
2810}
2811
2812#[derive(Clone, MallocSizeOf)]
2814struct SubtleHmacImportParams {
2815 name: CryptoAlgorithm,
2817
2818 hash: DigestAlgorithm,
2820
2821 length: Option<u32>,
2823}
2824
2825impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleHmacImportParams {
2826 type Error = Error;
2827
2828 fn try_from_with_cx(
2829 value: HandleValue<'a>,
2830 cx: &mut js::context::JSContext,
2831 ) -> Result<Self, Self::Error> {
2832 let dictionary = dictionary_from_jsval::<RootedTraceableBox<HmacImportParams>>(cx, value)?;
2833
2834 Ok(SubtleHmacImportParams {
2835 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2836 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2837 length: dictionary.length,
2838 })
2839 }
2840}
2841
2842#[derive(Clone, MallocSizeOf)]
2844pub(crate) struct SubtleHmacKeyAlgorithm {
2845 name: CryptoAlgorithm,
2847
2848 hash: SubtleKeyAlgorithm,
2850
2851 length: u32,
2853}
2854
2855impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
2856 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
2857 let parent = KeyAlgorithm {
2858 name: self.name.as_str().into(),
2859 };
2860 let hash = KeyAlgorithm {
2861 name: self.hash.name.as_str().into(),
2862 };
2863 let dictionary = HmacKeyAlgorithm {
2864 parent,
2865 hash,
2866 length: self.length,
2867 };
2868 dictionary.safe_to_jsval(cx, rval, can_gc);
2869 }
2870}
2871
2872#[derive(Clone, MallocSizeOf)]
2874struct SubtleHmacKeyGenParams {
2875 name: CryptoAlgorithm,
2877
2878 hash: DigestAlgorithm,
2880
2881 length: Option<u32>,
2883}
2884
2885impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleHmacKeyGenParams {
2886 type Error = Error;
2887
2888 fn try_from_with_cx(
2889 value: HandleValue<'a>,
2890 cx: &mut js::context::JSContext,
2891 ) -> Result<Self, Self::Error> {
2892 let dictionary = dictionary_from_jsval::<RootedTraceableBox<HmacKeyGenParams>>(cx, value)?;
2893
2894 Ok(SubtleHmacKeyGenParams {
2895 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2896 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2897 length: dictionary.length,
2898 })
2899 }
2900}
2901
2902#[derive(Clone, MallocSizeOf)]
2904pub(crate) struct SubtleHkdfParams {
2905 name: CryptoAlgorithm,
2907
2908 hash: DigestAlgorithm,
2910
2911 salt: Vec<u8>,
2913
2914 info: Vec<u8>,
2916}
2917
2918impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleHkdfParams {
2919 type Error = Error;
2920
2921 fn try_from_with_cx(
2922 value: HandleValue<'a>,
2923 cx: &mut js::context::JSContext,
2924 ) -> Result<Self, Self::Error> {
2925 let dictionary = dictionary_from_jsval::<RootedTraceableBox<HkdfParams>>(cx, value)?;
2926
2927 let salt = match &dictionary.salt {
2928 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2929 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2930 };
2931 let info = match &dictionary.info {
2932 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2933 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2934 };
2935
2936 Ok(SubtleHkdfParams {
2937 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2938 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2939 salt,
2940 info,
2941 })
2942 }
2943}
2944
2945#[derive(Clone, MallocSizeOf)]
2947pub(crate) struct SubtlePbkdf2Params {
2948 name: CryptoAlgorithm,
2950
2951 salt: Vec<u8>,
2953
2954 iterations: u32,
2956
2957 hash: DigestAlgorithm,
2959}
2960
2961impl<'a> TryFromWithCx<HandleValue<'a>> for SubtlePbkdf2Params {
2962 type Error = Error;
2963
2964 fn try_from_with_cx(
2965 value: HandleValue<'a>,
2966 cx: &mut js::context::JSContext,
2967 ) -> Result<Self, Self::Error> {
2968 let dictionary = dictionary_from_jsval::<RootedTraceableBox<Pbkdf2Params>>(cx, value)?;
2969
2970 let salt = match &dictionary.salt {
2971 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
2972 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
2973 };
2974
2975 Ok(SubtlePbkdf2Params {
2976 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
2977 salt,
2978 iterations: dictionary.iterations,
2979 hash: normalize_algorithm::<DigestOperation>(cx, &dictionary.hash)?,
2980 })
2981 }
2982}
2983
2984#[derive(Clone, MallocSizeOf)]
2986struct SubtleContextParams {
2987 name: CryptoAlgorithm,
2989
2990 context: Option<Vec<u8>>,
2992}
2993
2994impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleContextParams {
2995 type Error = Error;
2996
2997 fn try_from_with_cx(
2998 value: HandleValue<'a>,
2999 cx: &mut js::context::JSContext,
3000 ) -> Result<Self, Self::Error> {
3001 let dictionary = dictionary_from_jsval::<RootedTraceableBox<ContextParams>>(cx, value)?;
3002
3003 let context = dictionary.context.as_ref().map(|context| match context {
3004 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3005 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3006 });
3007
3008 Ok(SubtleContextParams {
3009 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
3010 context,
3011 })
3012 }
3013}
3014
3015#[derive(Clone, MallocSizeOf)]
3017struct SubtleAeadParams {
3018 name: CryptoAlgorithm,
3020
3021 iv: Vec<u8>,
3023
3024 additional_data: Option<Vec<u8>>,
3026
3027 tag_length: Option<u8>,
3029}
3030
3031impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleAeadParams {
3032 type Error = Error;
3033
3034 fn try_from_with_cx(
3035 value: HandleValue<'a>,
3036 cx: &mut js::context::JSContext,
3037 ) -> Result<Self, Self::Error> {
3038 let dictionary = dictionary_from_jsval::<RootedTraceableBox<AeadParams>>(cx, value)?;
3039
3040 let iv = match &dictionary.iv {
3041 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3042 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3043 };
3044 let additional_data = dictionary.additionalData.as_ref().map(|data| match data {
3045 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3046 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3047 });
3048
3049 Ok(SubtleAeadParams {
3050 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
3051 iv,
3052 additional_data,
3053 tag_length: dictionary.tagLength,
3054 })
3055 }
3056}
3057
3058#[derive(Clone, MallocSizeOf)]
3060struct SubtleCShakeParams {
3061 name: CryptoAlgorithm,
3063
3064 length: u32,
3066
3067 function_name: Option<Vec<u8>>,
3069
3070 customization: Option<Vec<u8>>,
3072}
3073
3074impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleCShakeParams {
3075 type Error = Error;
3076
3077 fn try_from_with_cx(
3078 value: HandleValue<'a>,
3079 cx: &mut js::context::JSContext,
3080 ) -> Result<Self, Self::Error> {
3081 let dictionary = dictionary_from_jsval::<RootedTraceableBox<CShakeParams>>(cx, value)?;
3082
3083 let function_name =
3084 dictionary
3085 .functionName
3086 .as_ref()
3087 .map(|function_name| match function_name {
3088 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3089 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3090 });
3091 let customization =
3092 dictionary
3093 .customization
3094 .as_ref()
3095 .map(|customization| match customization {
3096 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3097 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3098 });
3099
3100 Ok(SubtleCShakeParams {
3101 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
3102 length: dictionary.length,
3103 function_name,
3104 customization,
3105 })
3106 }
3107}
3108
3109#[derive(Clone, MallocSizeOf)]
3111struct SubtleArgon2Params {
3112 name: CryptoAlgorithm,
3114
3115 nonce: Vec<u8>,
3117
3118 parallelism: u32,
3120
3121 memory: u32,
3123
3124 passes: u32,
3126
3127 version: Option<u8>,
3129
3130 secret_value: Option<Vec<u8>>,
3132
3133 associated_data: Option<Vec<u8>>,
3135}
3136
3137impl<'a> TryFromWithCx<HandleValue<'a>> for SubtleArgon2Params {
3138 type Error = Error;
3139
3140 fn try_from_with_cx(
3141 value: HandleValue<'a>,
3142 cx: &mut js::context::JSContext,
3143 ) -> Result<Self, Self::Error> {
3144 let dictionary = dictionary_from_jsval::<RootedTraceableBox<Argon2Params>>(cx, value)?;
3145
3146 let nonce = match &dictionary.nonce {
3147 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3148 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3149 };
3150 let secret_value = dictionary
3151 .secretValue
3152 .as_ref()
3153 .map(|secret_value| match secret_value {
3154 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3155 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3156 });
3157 let associated_data =
3158 dictionary
3159 .associatedData
3160 .as_ref()
3161 .map(|associated_data| match associated_data {
3162 ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
3163 ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
3164 });
3165
3166 Ok(SubtleArgon2Params {
3167 name: CryptoAlgorithm::from_domstring(&dictionary.parent.name)?,
3168 nonce,
3169 parallelism: dictionary.parallelism,
3170 memory: dictionary.memory,
3171 passes: dictionary.passes,
3172 version: dictionary.version,
3173 secret_value,
3174 associated_data,
3175 })
3176 }
3177}
3178
3179struct SubtleEncapsulatedKey {
3181 shared_key: Option<Trusted<CryptoKey>>,
3183
3184 ciphertext: Option<Vec<u8>>,
3186}
3187
3188impl SafeToJSValConvertible for SubtleEncapsulatedKey {
3189 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3190 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
3191 let ciphertext = self.ciphertext.as_ref().map(|data| {
3192 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3193 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3194 .expect("Failed to convert ciphertext to ArrayBufferU8")
3195 });
3196 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
3197 sharedKey: shared_key,
3198 ciphertext,
3199 });
3200 encapsulated_key.safe_to_jsval(cx, rval, can_gc);
3201 }
3202}
3203
3204struct SubtleEncapsulatedBits {
3206 shared_key: Option<Vec<u8>>,
3208
3209 ciphertext: Option<Vec<u8>>,
3211}
3212
3213impl SafeToJSValConvertible for SubtleEncapsulatedBits {
3214 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3215 let shared_key = self.shared_key.as_ref().map(|data| {
3216 rooted!(in(*cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
3217 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut(), can_gc)
3218 .expect("Failed to convert shared key to ArrayBufferU8")
3219 });
3220 let ciphertext = self.ciphertext.as_ref().map(|data| {
3221 rooted!(in(*cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
3222 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut(), can_gc)
3223 .expect("Failed to convert ciphertext to ArrayBufferU8")
3224 });
3225 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
3226 sharedKey: shared_key,
3227 ciphertext,
3228 });
3229 encapsulated_bits.safe_to_jsval(cx, rval, can_gc);
3230 }
3231}
3232
3233fn dictionary_from_jsval<T>(cx: &mut js::context::JSContext, value: HandleValue) -> Fallible<T>
3235where
3236 T: SafeFromJSValConvertible<Config = ()>,
3237{
3238 let conversion = T::safe_from_jsval(cx.into(), value, (), CanGc::from_cx(cx))
3239 .map_err(|_| Error::JSFailed)?;
3240 match conversion {
3241 ConversionResult::Success(dictionary) => Ok(dictionary),
3242 ConversionResult::Failure(error) => Err(Error::Type(error.into_owned())),
3243 }
3244}
3245
3246enum ExportedKey {
3250 Bytes(Vec<u8>),
3251 Jwk(Box<JsonWebKey>),
3252}
3253
3254#[derive(Clone, MallocSizeOf)]
3258#[expect(clippy::enum_variant_names)]
3259pub(crate) enum KeyAlgorithmAndDerivatives {
3260 KeyAlgorithm(SubtleKeyAlgorithm),
3261 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
3262 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
3263 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
3264 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
3265}
3266
3267impl KeyAlgorithmAndDerivatives {
3268 fn name(&self) -> CryptoAlgorithm {
3269 match self {
3270 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
3271 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
3272 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
3273 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
3274 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
3275 }
3276 }
3277}
3278
3279impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
3280 fn safe_to_jsval(&self, cx: JSContext, rval: MutableHandleValue, can_gc: CanGc) {
3281 match self {
3282 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval, can_gc),
3283 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => {
3284 algo.safe_to_jsval(cx, rval, can_gc)
3285 },
3286 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => {
3287 algo.safe_to_jsval(cx, rval, can_gc)
3288 },
3289 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => {
3290 algo.safe_to_jsval(cx, rval, can_gc)
3291 },
3292 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => {
3293 algo.safe_to_jsval(cx, rval, can_gc)
3294 },
3295 }
3296 }
3297}
3298
3299#[derive(Clone, Copy)]
3300enum JwkStringField {
3301 X,
3302 Y,
3303 D,
3304 N,
3305 E,
3306 P,
3307 Q,
3308 DP,
3309 DQ,
3310 QI,
3311 K,
3312 Priv,
3313 Pub,
3314}
3315
3316impl Display for JwkStringField {
3317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3318 let field_name = match self {
3319 JwkStringField::X => "x",
3320 JwkStringField::Y => "y",
3321 JwkStringField::D => "d",
3322 JwkStringField::N => "n",
3323 JwkStringField::E => "e",
3324 JwkStringField::P => "q",
3325 JwkStringField::Q => "q",
3326 JwkStringField::DP => "dp",
3327 JwkStringField::DQ => "dq",
3328 JwkStringField::QI => "qi",
3329 JwkStringField::K => "k",
3330 JwkStringField::Priv => "priv",
3331 JwkStringField::Pub => "pub",
3332 };
3333 write!(f, "{}", field_name)
3334 }
3335}
3336
3337trait JsonWebKeyExt {
3338 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
3339 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<DOMString, Error>;
3340 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
3341 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
3342 fn set_key_ops(&mut self, usages: Vec<KeyUsage>);
3343 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
3344 fn decode_optional_string_field(&self, field: JwkStringField)
3345 -> Result<Option<Vec<u8>>, Error>;
3346 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error>;
3347 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error>;
3348}
3349
3350impl JsonWebKeyExt for JsonWebKey {
3351 #[expect(unsafe_code)]
3353 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
3354 let json = String::from_utf8_lossy(data);
3359
3360 let json: Vec<_> = json.encode_utf16().collect();
3362
3363 rooted!(&in(cx) let mut result = UndefinedValue());
3367 unsafe {
3368 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
3369 return Err(Error::JSFailed);
3370 }
3371 }
3372
3373 let key = match JsonWebKey::new(cx.into(), result.handle(), CanGc::from_cx(cx)) {
3375 Ok(ConversionResult::Success(key)) => key,
3376 Ok(ConversionResult::Failure(error)) => {
3377 return Err(Error::Type(error.into_owned()));
3378 },
3379 Err(()) => {
3380 return Err(Error::JSFailed);
3381 },
3382 };
3383
3384 if key.kty.is_none() {
3386 return Err(Error::Data(None));
3387 }
3388
3389 Ok(key)
3391 }
3392
3393 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<DOMString, Error> {
3399 rooted!(&in(cx) let mut data = UndefinedValue());
3400 self.safe_to_jsval(cx.into(), data.handle_mut(), CanGc::from_cx(cx));
3401 serialize_jsval_to_json_utf8(cx.into(), data.handle())
3402 }
3403
3404 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
3405 let mut usages = vec![];
3406 for op in self.key_ops.as_ref().ok_or(Error::Data(None))? {
3407 usages.push(KeyUsage::from_str(&op.str()).map_err(|_| Error::Data(None))?);
3408 }
3409 Ok(usages)
3410 }
3411
3412 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
3416 if let Some(ref key_ops) = self.key_ops {
3418 if key_ops
3421 .iter()
3422 .collect::<std::collections::HashSet<_>>()
3423 .len() <
3424 key_ops.len()
3425 {
3426 return Err(Error::Data(None));
3427 }
3428 if let Some(ref use_) = self.use_ {
3431 if key_ops.iter().any(|op| op != use_) {
3432 return Err(Error::Data(None));
3433 }
3434 }
3435
3436 let key_ops_as_usages = self.get_usages_from_key_ops()?;
3438 if !specified_usages
3439 .iter()
3440 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
3441 {
3442 return Err(Error::Data(None));
3443 }
3444 }
3445
3446 Ok(())
3447 }
3448
3449 fn set_key_ops(&mut self, usages: Vec<KeyUsage>) {
3451 self.key_ops = Some(
3452 usages
3453 .into_iter()
3454 .map(|usage| DOMString::from(usage.as_str()))
3455 .collect(),
3456 );
3457 }
3458
3459 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
3462 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
3463 match field {
3464 JwkStringField::X => self.x = Some(encoded_data),
3465 JwkStringField::Y => self.y = Some(encoded_data),
3466 JwkStringField::D => self.d = Some(encoded_data),
3467 JwkStringField::N => self.n = Some(encoded_data),
3468 JwkStringField::E => self.e = Some(encoded_data),
3469 JwkStringField::P => self.p = Some(encoded_data),
3470 JwkStringField::Q => self.q = Some(encoded_data),
3471 JwkStringField::DP => self.dp = Some(encoded_data),
3472 JwkStringField::DQ => self.dq = Some(encoded_data),
3473 JwkStringField::QI => self.qi = Some(encoded_data),
3474 JwkStringField::K => self.k = Some(encoded_data),
3475 JwkStringField::Priv => self.priv_ = Some(encoded_data),
3476 JwkStringField::Pub => self.pub_ = Some(encoded_data),
3477 }
3478 }
3479
3480 fn decode_optional_string_field(
3483 &self,
3484 field: JwkStringField,
3485 ) -> Result<Option<Vec<u8>>, Error> {
3486 let field_string = match field {
3487 JwkStringField::X => &self.x,
3488 JwkStringField::Y => &self.y,
3489 JwkStringField::D => &self.d,
3490 JwkStringField::N => &self.n,
3491 JwkStringField::E => &self.e,
3492 JwkStringField::P => &self.p,
3493 JwkStringField::Q => &self.q,
3494 JwkStringField::DP => &self.dp,
3495 JwkStringField::DQ => &self.dq,
3496 JwkStringField::QI => &self.qi,
3497 JwkStringField::K => &self.k,
3498 JwkStringField::Priv => &self.priv_,
3499 JwkStringField::Pub => &self.pub_,
3500 };
3501
3502 field_string
3503 .as_ref()
3504 .map(|field_string| Base64UrlUnpadded::decode_vec(&field_string.str()))
3505 .transpose()
3506 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
3507 }
3508
3509 fn decode_required_string_field(&self, field: JwkStringField) -> Result<Vec<u8>, Error> {
3512 self.decode_optional_string_field(field)?
3513 .ok_or(Error::Data(Some(format!(
3514 "The {} field is not present in jwk",
3515 field
3516 ))))
3517 }
3518
3519 fn decode_primes_from_oth_field(&self, primes: &mut Vec<Vec<u8>>) -> Result<(), Error> {
3528 if self.oth.is_some() &&
3529 (self.p.is_none() ||
3530 self.q.is_none() ||
3531 self.dp.is_none() ||
3532 self.dq.is_none() ||
3533 self.qi.is_none())
3534 {
3535 return Err(Error::Data(Some(
3536 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
3537 )));
3538 }
3539
3540 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
3541 let r = Base64UrlUnpadded::decode_vec(
3542 &rsa_other_prime_info
3543 .r
3544 .as_ref()
3545 .ok_or(Error::Data(Some(
3546 "The r field is not present in one of the entry of oth field in jwk"
3547 .to_string(),
3548 )))?
3549 .str(),
3550 )
3551 .map_err(|_| {
3552 Error::Data(Some(
3553 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
3554 ))
3555 })?;
3556 primes.push(r);
3557
3558 let _d = Base64UrlUnpadded::decode_vec(
3559 &rsa_other_prime_info
3560 .d
3561 .as_ref()
3562 .ok_or(Error::Data(Some(
3563 "The d field is not present in one of the entry of oth field in jwk"
3564 .to_string(),
3565 )))?
3566 .str(),
3567 )
3568 .map_err(|_| {
3569 Error::Data(Some(
3570 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
3571 ))
3572 })?;
3573
3574 let _t = Base64UrlUnpadded::decode_vec(
3575 &rsa_other_prime_info
3576 .t
3577 .as_ref()
3578 .ok_or(Error::Data(Some(
3579 "The t field is not present in one of the entry of oth field in jwk"
3580 .to_string(),
3581 )))?
3582 .str(),
3583 )
3584 .map_err(|_| {
3585 Error::Data(Some(
3586 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
3587 ))
3588 })?;
3589 }
3590
3591 Ok(())
3592 }
3593}
3594
3595fn normalize_algorithm<Op: Operation>(
3597 cx: &mut js::context::JSContext,
3598 algorithm: &AlgorithmIdentifier,
3599) -> Result<Op::RegisteredAlgorithm, Error> {
3600 match algorithm {
3601 ObjectOrString::String(name) => {
3603 let algorithm = Algorithm {
3607 name: name.to_owned(),
3608 };
3609 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
3610 algorithm.safe_to_jsval(cx.into(), algorithm_value.handle_mut(), CanGc::from_cx(cx));
3611 let algorithm_object = RootedTraceableBox::new(Heap::default());
3612 algorithm_object.set(algorithm_value.to_object());
3613 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
3614 },
3615 ObjectOrString::Object(object) => {
3617 rooted!(&in(cx) let value = ObjectValue(object.get()));
3624 let initial_algorithm = dictionary_from_jsval::<Algorithm>(cx, value.handle())?;
3625
3626 let algorithm_name =
3628 CryptoAlgorithm::from_str_ignore_case(&initial_algorithm.name.str())?;
3629
3630 rooted!(&in(cx) let mut algorithm_name_value = UndefinedValue());
3670 algorithm_name.as_str().safe_to_jsval(
3671 cx.into(),
3672 algorithm_name_value.handle_mut(),
3673 CanGc::from_cx(cx),
3674 );
3675 set_dictionary_property(
3676 cx.into(),
3677 object.handle(),
3678 c"name",
3679 algorithm_name_value.handle(),
3680 )
3681 .map_err(|_| Error::JSFailed)?;
3682 let normalized_algorithm =
3683 Op::RegisteredAlgorithm::from_object_value(cx, algorithm_name, value.handle())?;
3684
3685 Ok(normalized_algorithm)
3687 },
3688 }
3689}
3690
3691trait Operation {
3745 type RegisteredAlgorithm: NormalizedAlgorithm;
3746}
3747
3748trait NormalizedAlgorithm: Sized {
3749 fn from_object_value(
3751 cx: &mut js::context::JSContext,
3752 algorithm_name: CryptoAlgorithm,
3753 value: HandleValue,
3754 ) -> Fallible<Self>;
3755 fn name(&self) -> CryptoAlgorithm;
3756}
3757
3758struct EncryptOperation {}
3760
3761impl Operation for EncryptOperation {
3762 type RegisteredAlgorithm = EncryptAlgorithm;
3763}
3764
3765enum EncryptAlgorithm {
3768 RsaOaep(SubtleRsaOaepParams),
3769 AesCtr(SubtleAesCtrParams),
3770 AesCbc(SubtleAesCbcParams),
3771 AesGcm(SubtleAesGcmParams),
3772 AesOcb(SubtleAeadParams),
3773 ChaCha20Poly1305(SubtleAeadParams),
3774}
3775
3776impl NormalizedAlgorithm for EncryptAlgorithm {
3777 fn from_object_value(
3778 cx: &mut js::context::JSContext,
3779 algorithm_name: CryptoAlgorithm,
3780 value: HandleValue,
3781 ) -> Fallible<Self> {
3782 match algorithm_name {
3783 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(value.try_into_with_cx(cx)?)),
3784 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(value.try_into_with_cx(cx)?)),
3785 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(value.try_into_with_cx(cx)?)),
3786 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(value.try_into_with_cx(cx)?)),
3787 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(value.try_into_with_cx(cx)?)),
3788 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
3789 value.try_into_with_cx(cx)?,
3790 )),
3791 _ => Err(Error::NotSupported(Some(format!(
3792 "{} does not support \"encrypt\" operation",
3793 algorithm_name.as_str()
3794 )))),
3795 }
3796 }
3797
3798 fn name(&self) -> CryptoAlgorithm {
3799 match self {
3800 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
3801 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
3802 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
3803 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
3804 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
3805 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
3806 }
3807 }
3808}
3809
3810impl EncryptAlgorithm {
3811 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
3812 match self {
3813 EncryptAlgorithm::RsaOaep(algorithm) => {
3814 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
3815 },
3816 EncryptAlgorithm::AesCtr(algorithm) => {
3817 aes_ctr_operation::encrypt(algorithm, key, plaintext)
3818 },
3819 EncryptAlgorithm::AesCbc(algorithm) => {
3820 aes_cbc_operation::encrypt(algorithm, key, plaintext)
3821 },
3822 EncryptAlgorithm::AesGcm(algorithm) => {
3823 aes_gcm_operation::encrypt(algorithm, key, plaintext)
3824 },
3825 EncryptAlgorithm::AesOcb(algorithm) => {
3826 aes_ocb_operation::encrypt(algorithm, key, plaintext)
3827 },
3828 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
3829 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
3830 },
3831 }
3832 }
3833}
3834
3835struct DecryptOperation {}
3837
3838impl Operation for DecryptOperation {
3839 type RegisteredAlgorithm = DecryptAlgorithm;
3840}
3841
3842enum DecryptAlgorithm {
3845 RsaOaep(SubtleRsaOaepParams),
3846 AesCtr(SubtleAesCtrParams),
3847 AesCbc(SubtleAesCbcParams),
3848 AesGcm(SubtleAesGcmParams),
3849 AesOcb(SubtleAeadParams),
3850 ChaCha20Poly1305(SubtleAeadParams),
3851}
3852
3853impl NormalizedAlgorithm for DecryptAlgorithm {
3854 fn from_object_value(
3855 cx: &mut js::context::JSContext,
3856 algorithm_name: CryptoAlgorithm,
3857 value: HandleValue,
3858 ) -> Fallible<Self> {
3859 match algorithm_name {
3860 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(value.try_into_with_cx(cx)?)),
3861 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(value.try_into_with_cx(cx)?)),
3862 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(value.try_into_with_cx(cx)?)),
3863 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(value.try_into_with_cx(cx)?)),
3864 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(value.try_into_with_cx(cx)?)),
3865 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
3866 value.try_into_with_cx(cx)?,
3867 )),
3868 _ => Err(Error::NotSupported(Some(format!(
3869 "{} does not support \"decrypt\" operation",
3870 algorithm_name.as_str()
3871 )))),
3872 }
3873 }
3874
3875 fn name(&self) -> CryptoAlgorithm {
3876 match self {
3877 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
3878 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
3879 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
3880 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
3881 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
3882 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
3883 }
3884 }
3885}
3886
3887impl DecryptAlgorithm {
3888 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
3889 match self {
3890 DecryptAlgorithm::RsaOaep(algorithm) => {
3891 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
3892 },
3893 DecryptAlgorithm::AesCtr(algorithm) => {
3894 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
3895 },
3896 DecryptAlgorithm::AesCbc(algorithm) => {
3897 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
3898 },
3899 DecryptAlgorithm::AesGcm(algorithm) => {
3900 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
3901 },
3902 DecryptAlgorithm::AesOcb(algorithm) => {
3903 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
3904 },
3905 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
3906 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
3907 },
3908 }
3909 }
3910}
3911
3912struct SignOperation {}
3914
3915impl Operation for SignOperation {
3916 type RegisteredAlgorithm = SignAlgorithm;
3917}
3918
3919enum SignAlgorithm {
3922 RsassaPkcs1V1_5(SubtleAlgorithm),
3923 RsaPss(SubtleRsaPssParams),
3924 Ecdsa(SubtleEcdsaParams),
3925 Ed25519(SubtleAlgorithm),
3926 Hmac(SubtleAlgorithm),
3927 MlDsa(SubtleContextParams),
3928}
3929
3930impl NormalizedAlgorithm for SignAlgorithm {
3931 fn from_object_value(
3932 cx: &mut js::context::JSContext,
3933 algorithm_name: CryptoAlgorithm,
3934 value: HandleValue,
3935 ) -> Fallible<Self> {
3936 match algorithm_name {
3937 CryptoAlgorithm::RsassaPkcs1V1_5 => {
3938 Ok(SignAlgorithm::RsassaPkcs1V1_5(value.try_into_with_cx(cx)?))
3939 },
3940 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(value.try_into_with_cx(cx)?)),
3941 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
3942 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(value.try_into_with_cx(cx)?)),
3943 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
3944 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => {
3945 Ok(SignAlgorithm::MlDsa(value.try_into_with_cx(cx)?))
3946 },
3947 _ => Err(Error::NotSupported(Some(format!(
3948 "{} does not support \"sign\" operation",
3949 algorithm_name.as_str()
3950 )))),
3951 }
3952 }
3953
3954 fn name(&self) -> CryptoAlgorithm {
3955 match self {
3956 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
3957 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
3958 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
3959 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
3960 SignAlgorithm::Hmac(algorithm) => algorithm.name,
3961 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
3962 }
3963 }
3964}
3965
3966impl SignAlgorithm {
3967 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
3968 match self {
3969 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
3970 rsassa_pkcs1_v1_5_operation::sign(key, message)
3971 },
3972 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
3973 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
3974 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
3975 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
3976 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
3977 }
3978 }
3979}
3980
3981struct VerifyOperation {}
3983
3984impl Operation for VerifyOperation {
3985 type RegisteredAlgorithm = VerifyAlgorithm;
3986}
3987
3988enum VerifyAlgorithm {
3991 RsassaPkcs1V1_5(SubtleAlgorithm),
3992 RsaPss(SubtleRsaPssParams),
3993 Ecdsa(SubtleEcdsaParams),
3994 Ed25519(SubtleAlgorithm),
3995 Hmac(SubtleAlgorithm),
3996 MlDsa(SubtleContextParams),
3997}
3998
3999impl NormalizedAlgorithm for VerifyAlgorithm {
4000 fn from_object_value(
4001 cx: &mut js::context::JSContext,
4002 algorithm_name: CryptoAlgorithm,
4003 value: HandleValue,
4004 ) -> Fallible<Self> {
4005 match algorithm_name {
4006 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
4007 value.try_into_with_cx(cx)?,
4008 )),
4009 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(value.try_into_with_cx(cx)?)),
4010 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
4011 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(value.try_into_with_cx(cx)?)),
4012 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
4013 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => {
4014 Ok(VerifyAlgorithm::MlDsa(value.try_into_with_cx(cx)?))
4015 },
4016 _ => Err(Error::NotSupported(Some(format!(
4017 "{} does not support \"verify\" operation",
4018 algorithm_name.as_str()
4019 )))),
4020 }
4021 }
4022
4023 fn name(&self) -> CryptoAlgorithm {
4024 match self {
4025 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4026 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
4027 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4028 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
4029 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
4030 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
4031 }
4032 }
4033}
4034
4035impl VerifyAlgorithm {
4036 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
4037 match self {
4038 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4039 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
4040 },
4041 VerifyAlgorithm::RsaPss(algorithm) => {
4042 rsa_pss_operation::verify(algorithm, key, message, signature)
4043 },
4044 VerifyAlgorithm::Ecdsa(algorithm) => {
4045 ecdsa_operation::verify(algorithm, key, message, signature)
4046 },
4047 VerifyAlgorithm::Ed25519(_algorithm) => {
4048 ed25519_operation::verify(key, message, signature)
4049 },
4050 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
4051 VerifyAlgorithm::MlDsa(algorithm) => {
4052 ml_dsa_operation::verify(algorithm, key, message, signature)
4053 },
4054 }
4055 }
4056}
4057
4058struct DigestOperation {}
4060
4061impl Operation for DigestOperation {
4062 type RegisteredAlgorithm = DigestAlgorithm;
4063}
4064
4065#[derive(Clone, MallocSizeOf)]
4068enum DigestAlgorithm {
4069 Sha(SubtleAlgorithm),
4070 Sha3(SubtleAlgorithm),
4071 CShake(SubtleCShakeParams),
4072}
4073
4074impl NormalizedAlgorithm for DigestAlgorithm {
4075 fn from_object_value(
4076 cx: &mut js::context::JSContext,
4077 algorithm_name: CryptoAlgorithm,
4078 value: HandleValue,
4079 ) -> Fallible<Self> {
4080 match algorithm_name {
4081 CryptoAlgorithm::Sha1 |
4082 CryptoAlgorithm::Sha256 |
4083 CryptoAlgorithm::Sha384 |
4084 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(value.try_into_with_cx(cx)?)),
4085 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
4086 Ok(DigestAlgorithm::Sha3(value.try_into_with_cx(cx)?))
4087 },
4088 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => {
4089 Ok(DigestAlgorithm::CShake(value.try_into_with_cx(cx)?))
4090 },
4091 _ => Err(Error::NotSupported(Some(format!(
4092 "{} does not support \"digest\" operation",
4093 algorithm_name.as_str()
4094 )))),
4095 }
4096 }
4097
4098 fn name(&self) -> CryptoAlgorithm {
4099 match self {
4100 DigestAlgorithm::Sha(algorithm) => algorithm.name,
4101 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
4102 DigestAlgorithm::CShake(algorithm) => algorithm.name,
4103 }
4104 }
4105}
4106
4107impl DigestAlgorithm {
4108 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
4109 match self {
4110 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
4111 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
4112 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
4113 }
4114 }
4115}
4116
4117struct DeriveBitsOperation {}
4119
4120impl Operation for DeriveBitsOperation {
4121 type RegisteredAlgorithm = DeriveBitsAlgorithm;
4122}
4123
4124enum DeriveBitsAlgorithm {
4127 Ecdh(SubtleEcdhKeyDeriveParams),
4128 X25519(SubtleEcdhKeyDeriveParams),
4129 Hkdf(SubtleHkdfParams),
4130 Pbkdf2(SubtlePbkdf2Params),
4131 Argon2(SubtleArgon2Params),
4132}
4133
4134impl NormalizedAlgorithm for DeriveBitsAlgorithm {
4135 fn from_object_value(
4136 cx: &mut js::context::JSContext,
4137 algorithm_name: CryptoAlgorithm,
4138 value: HandleValue,
4139 ) -> Fallible<Self> {
4140 match algorithm_name {
4141 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(value.try_into_with_cx(cx)?)),
4142 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(value.try_into_with_cx(cx)?)),
4143 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(value.try_into_with_cx(cx)?)),
4144 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(value.try_into_with_cx(cx)?)),
4145 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
4146 Ok(DeriveBitsAlgorithm::Argon2(value.try_into_with_cx(cx)?))
4147 },
4148 _ => Err(Error::NotSupported(Some(format!(
4149 "{} does not support \"deriveBits\" operation",
4150 algorithm_name.as_str()
4151 )))),
4152 }
4153 }
4154
4155 fn name(&self) -> CryptoAlgorithm {
4156 match self {
4157 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
4158 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
4159 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
4160 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
4161 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
4162 }
4163 }
4164}
4165
4166impl DeriveBitsAlgorithm {
4167 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
4168 match self {
4169 DeriveBitsAlgorithm::Ecdh(algorithm) => {
4170 ecdh_operation::derive_bits(algorithm, key, length)
4171 },
4172 DeriveBitsAlgorithm::X25519(algorithm) => {
4173 x25519_operation::derive_bits(algorithm, key, length)
4174 },
4175 DeriveBitsAlgorithm::Hkdf(algorithm) => {
4176 hkdf_operation::derive_bits(algorithm, key, length)
4177 },
4178 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
4179 pbkdf2_operation::derive_bits(algorithm, key, length)
4180 },
4181 DeriveBitsAlgorithm::Argon2(algorithm) => {
4182 argon2_operation::derive_bits(algorithm, key, length)
4183 },
4184 }
4185 }
4186}
4187
4188struct WrapKeyOperation {}
4190
4191impl Operation for WrapKeyOperation {
4192 type RegisteredAlgorithm = WrapKeyAlgorithm;
4193}
4194
4195enum WrapKeyAlgorithm {
4198 AesKw(SubtleAlgorithm),
4199}
4200
4201impl NormalizedAlgorithm for WrapKeyAlgorithm {
4202 fn from_object_value(
4203 cx: &mut js::context::JSContext,
4204 algorithm_name: CryptoAlgorithm,
4205 value: HandleValue,
4206 ) -> Fallible<Self> {
4207 match algorithm_name {
4208 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4209 _ => Err(Error::NotSupported(Some(format!(
4210 "{} does not support \"wrapKey\" operation",
4211 algorithm_name.as_str()
4212 )))),
4213 }
4214 }
4215
4216 fn name(&self) -> CryptoAlgorithm {
4217 match self {
4218 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4219 }
4220 }
4221}
4222
4223impl WrapKeyAlgorithm {
4224 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4225 match self {
4226 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
4227 }
4228 }
4229}
4230
4231struct UnwrapKeyOperation {}
4233
4234impl Operation for UnwrapKeyOperation {
4235 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
4236}
4237
4238enum UnwrapKeyAlgorithm {
4241 AesKw(SubtleAlgorithm),
4242}
4243
4244impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
4245 fn from_object_value(
4246 cx: &mut js::context::JSContext,
4247 algorithm_name: CryptoAlgorithm,
4248 value: HandleValue,
4249 ) -> Fallible<Self> {
4250 match algorithm_name {
4251 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4252 _ => Err(Error::NotSupported(Some(format!(
4253 "{} does not support \"unwrapKey\" operation",
4254 algorithm_name.as_str()
4255 )))),
4256 }
4257 }
4258
4259 fn name(&self) -> CryptoAlgorithm {
4260 match self {
4261 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4262 }
4263 }
4264}
4265
4266impl UnwrapKeyAlgorithm {
4267 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4268 match self {
4269 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
4270 }
4271 }
4272}
4273
4274struct GenerateKeyOperation {}
4276
4277impl Operation for GenerateKeyOperation {
4278 type RegisteredAlgorithm = GenerateKeyAlgorithm;
4279}
4280
4281enum GenerateKeyAlgorithm {
4284 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
4285 RsaPss(SubtleRsaHashedKeyGenParams),
4286 RsaOaep(SubtleRsaHashedKeyGenParams),
4287 Ecdsa(SubtleEcKeyGenParams),
4288 Ecdh(SubtleEcKeyGenParams),
4289 Ed25519(SubtleAlgorithm),
4290 X25519(SubtleAlgorithm),
4291 AesCtr(SubtleAesKeyGenParams),
4292 AesCbc(SubtleAesKeyGenParams),
4293 AesGcm(SubtleAesKeyGenParams),
4294 AesKw(SubtleAesKeyGenParams),
4295 Hmac(SubtleHmacKeyGenParams),
4296 MlKem(SubtleAlgorithm),
4297 MlDsa(SubtleAlgorithm),
4298 AesOcb(SubtleAesKeyGenParams),
4299 ChaCha20Poly1305(SubtleAlgorithm),
4300}
4301
4302impl NormalizedAlgorithm for GenerateKeyAlgorithm {
4303 fn from_object_value(
4304 cx: &mut js::context::JSContext,
4305 algorithm_name: CryptoAlgorithm,
4306 value: HandleValue,
4307 ) -> Fallible<Self> {
4308 match algorithm_name {
4309 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
4310 value.try_into_with_cx(cx)?,
4311 )),
4312 CryptoAlgorithm::RsaPss => {
4313 Ok(GenerateKeyAlgorithm::RsaPss(value.try_into_with_cx(cx)?))
4314 },
4315 CryptoAlgorithm::RsaOaep => {
4316 Ok(GenerateKeyAlgorithm::RsaOaep(value.try_into_with_cx(cx)?))
4317 },
4318 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
4319 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(value.try_into_with_cx(cx)?)),
4320 CryptoAlgorithm::Ed25519 => {
4321 Ok(GenerateKeyAlgorithm::Ed25519(value.try_into_with_cx(cx)?))
4322 },
4323 CryptoAlgorithm::X25519 => {
4324 Ok(GenerateKeyAlgorithm::X25519(value.try_into_with_cx(cx)?))
4325 },
4326 CryptoAlgorithm::AesCtr => {
4327 Ok(GenerateKeyAlgorithm::AesCtr(value.try_into_with_cx(cx)?))
4328 },
4329 CryptoAlgorithm::AesCbc => {
4330 Ok(GenerateKeyAlgorithm::AesCbc(value.try_into_with_cx(cx)?))
4331 },
4332 CryptoAlgorithm::AesGcm => {
4333 Ok(GenerateKeyAlgorithm::AesGcm(value.try_into_with_cx(cx)?))
4334 },
4335 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4336 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
4337 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
4338 Ok(GenerateKeyAlgorithm::MlKem(value.try_into_with_cx(cx)?))
4339 },
4340 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => {
4341 Ok(GenerateKeyAlgorithm::MlDsa(value.try_into_with_cx(cx)?))
4342 },
4343 CryptoAlgorithm::AesOcb => {
4344 Ok(GenerateKeyAlgorithm::AesOcb(value.try_into_with_cx(cx)?))
4345 },
4346 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
4347 value.try_into_with_cx(cx)?,
4348 )),
4349 _ => Err(Error::NotSupported(Some(format!(
4350 "{} does not support \"generateKey\" operation",
4351 algorithm_name.as_str()
4352 )))),
4353 }
4354 }
4355
4356 fn name(&self) -> CryptoAlgorithm {
4357 match self {
4358 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4359 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
4360 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
4361 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4362 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
4363 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
4364 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
4365 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
4366 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
4367 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
4368 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4369 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
4370 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
4371 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
4372 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
4373 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4374 }
4375 }
4376}
4377
4378impl GenerateKeyAlgorithm {
4379 fn generate_key(
4380 &self,
4381 cx: &mut js::context::JSContext,
4382 global: &GlobalScope,
4383 extractable: bool,
4384 usages: Vec<KeyUsage>,
4385 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
4386 match self {
4387 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
4388 rsassa_pkcs1_v1_5_operation::generate_key(
4389 cx,
4390 global,
4391 algorithm,
4392 extractable,
4393 usages,
4394 )
4395 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4396 },
4397 GenerateKeyAlgorithm::RsaPss(algorithm) => {
4398 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
4399 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4400 },
4401 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
4402 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
4403 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4404 },
4405 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
4406 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
4407 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4408 },
4409 GenerateKeyAlgorithm::Ecdh(algorithm) => {
4410 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
4411 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4412 },
4413 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
4414 ed25519_operation::generate_key(cx, global, extractable, usages)
4415 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4416 },
4417 GenerateKeyAlgorithm::X25519(_algorithm) => {
4418 x25519_operation::generate_key(cx, global, extractable, usages)
4419 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4420 },
4421 GenerateKeyAlgorithm::AesCtr(algorithm) => {
4422 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
4423 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4424 },
4425 GenerateKeyAlgorithm::AesCbc(algorithm) => {
4426 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
4427 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4428 },
4429 GenerateKeyAlgorithm::AesGcm(algorithm) => {
4430 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
4431 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4432 },
4433 GenerateKeyAlgorithm::AesKw(algorithm) => {
4434 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
4435 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4436 },
4437 GenerateKeyAlgorithm::Hmac(algorithm) => {
4438 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
4439 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4440 },
4441 GenerateKeyAlgorithm::MlKem(algorithm) => {
4442 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
4443 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4444 },
4445 GenerateKeyAlgorithm::MlDsa(algorithm) => {
4446 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
4447 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
4448 },
4449 GenerateKeyAlgorithm::AesOcb(algorithm) => {
4450 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
4451 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4452 },
4453 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
4454 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
4455 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
4456 },
4457 }
4458 }
4459}
4460
4461struct ImportKeyOperation {}
4463
4464impl Operation for ImportKeyOperation {
4465 type RegisteredAlgorithm = ImportKeyAlgorithm;
4466}
4467
4468enum ImportKeyAlgorithm {
4471 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
4472 RsaPss(SubtleRsaHashedImportParams),
4473 RsaOaep(SubtleRsaHashedImportParams),
4474 Ecdsa(SubtleEcKeyImportParams),
4475 Ecdh(SubtleEcKeyImportParams),
4476 Ed25519(SubtleAlgorithm),
4477 X25519(SubtleAlgorithm),
4478 AesCtr(SubtleAlgorithm),
4479 AesCbc(SubtleAlgorithm),
4480 AesGcm(SubtleAlgorithm),
4481 AesKw(SubtleAlgorithm),
4482 Hmac(SubtleHmacImportParams),
4483 Hkdf(SubtleAlgorithm),
4484 Pbkdf2(SubtleAlgorithm),
4485 MlKem(SubtleAlgorithm),
4486 MlDsa(SubtleAlgorithm),
4487 AesOcb(SubtleAlgorithm),
4488 ChaCha20Poly1305(SubtleAlgorithm),
4489 Argon2(SubtleAlgorithm),
4490}
4491
4492impl NormalizedAlgorithm for ImportKeyAlgorithm {
4493 fn from_object_value(
4494 cx: &mut js::context::JSContext,
4495 algorithm_name: CryptoAlgorithm,
4496 value: HandleValue,
4497 ) -> Fallible<Self> {
4498 match algorithm_name {
4499 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
4500 value.try_into_with_cx(cx)?,
4501 )),
4502 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(value.try_into_with_cx(cx)?)),
4503 CryptoAlgorithm::RsaOaep => {
4504 Ok(ImportKeyAlgorithm::RsaOaep(value.try_into_with_cx(cx)?))
4505 },
4506 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
4507 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(value.try_into_with_cx(cx)?)),
4508 CryptoAlgorithm::Ed25519 => {
4509 Ok(ImportKeyAlgorithm::Ed25519(value.try_into_with_cx(cx)?))
4510 },
4511 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(value.try_into_with_cx(cx)?)),
4512 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(value.try_into_with_cx(cx)?)),
4513 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(value.try_into_with_cx(cx)?)),
4514 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(value.try_into_with_cx(cx)?)),
4515 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4516 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
4517 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(value.try_into_with_cx(cx)?)),
4518 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(value.try_into_with_cx(cx)?)),
4519 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
4520 Ok(ImportKeyAlgorithm::MlKem(value.try_into_with_cx(cx)?))
4521 },
4522 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => {
4523 Ok(ImportKeyAlgorithm::MlDsa(value.try_into_with_cx(cx)?))
4524 },
4525 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(value.try_into_with_cx(cx)?)),
4526 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
4527 value.try_into_with_cx(cx)?,
4528 )),
4529 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
4530 Ok(ImportKeyAlgorithm::Argon2(value.try_into_with_cx(cx)?))
4531 },
4532 _ => Err(Error::NotSupported(Some(format!(
4533 "{} does not support \"importKey\" operation",
4534 algorithm_name.as_str()
4535 )))),
4536 }
4537 }
4538
4539 fn name(&self) -> CryptoAlgorithm {
4540 match self {
4541 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4542 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
4543 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
4544 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4545 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
4546 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
4547 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
4548 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
4549 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
4550 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
4551 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4552 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
4553 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
4554 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
4555 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
4556 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
4557 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
4558 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4559 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
4560 }
4561 }
4562}
4563
4564impl ImportKeyAlgorithm {
4565 fn import_key(
4566 &self,
4567 cx: &mut js::context::JSContext,
4568 global: &GlobalScope,
4569 format: KeyFormat,
4570 key_data: &[u8],
4571 extractable: bool,
4572 usages: Vec<KeyUsage>,
4573 ) -> Result<DomRoot<CryptoKey>, Error> {
4574 match self {
4575 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
4576 rsassa_pkcs1_v1_5_operation::import_key(
4577 cx,
4578 global,
4579 algorithm,
4580 format,
4581 key_data,
4582 extractable,
4583 usages,
4584 )
4585 },
4586 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
4587 cx,
4588 global,
4589 algorithm,
4590 format,
4591 key_data,
4592 extractable,
4593 usages,
4594 ),
4595 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
4596 cx,
4597 global,
4598 algorithm,
4599 format,
4600 key_data,
4601 extractable,
4602 usages,
4603 ),
4604 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
4605 cx,
4606 global,
4607 algorithm,
4608 format,
4609 key_data,
4610 extractable,
4611 usages,
4612 ),
4613 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
4614 cx,
4615 global,
4616 algorithm,
4617 format,
4618 key_data,
4619 extractable,
4620 usages,
4621 ),
4622 ImportKeyAlgorithm::Ed25519(_algorithm) => {
4623 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
4624 },
4625 ImportKeyAlgorithm::X25519(_algorithm) => {
4626 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
4627 },
4628 ImportKeyAlgorithm::AesCtr(_algorithm) => {
4629 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
4630 },
4631 ImportKeyAlgorithm::AesCbc(_algorithm) => {
4632 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
4633 },
4634 ImportKeyAlgorithm::AesGcm(_algorithm) => {
4635 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
4636 },
4637 ImportKeyAlgorithm::AesKw(_algorithm) => {
4638 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
4639 },
4640 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
4641 cx,
4642 global,
4643 algorithm,
4644 format,
4645 key_data,
4646 extractable,
4647 usages,
4648 ),
4649 ImportKeyAlgorithm::Hkdf(_algorithm) => {
4650 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
4651 },
4652 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
4653 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
4654 },
4655 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
4656 cx,
4657 global,
4658 algorithm,
4659 format,
4660 key_data,
4661 extractable,
4662 usages,
4663 ),
4664 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
4665 cx,
4666 global,
4667 algorithm,
4668 format,
4669 key_data,
4670 extractable,
4671 usages,
4672 ),
4673 ImportKeyAlgorithm::AesOcb(_algorithm) => {
4674 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
4675 },
4676 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
4677 chacha20_poly1305_operation::import_key(
4678 cx,
4679 global,
4680 format,
4681 key_data,
4682 extractable,
4683 usages,
4684 )
4685 },
4686 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
4687 cx,
4688 global,
4689 algorithm,
4690 format,
4691 key_data,
4692 extractable,
4693 usages,
4694 ),
4695 }
4696 }
4697}
4698
4699struct ExportKeyOperation {}
4701
4702impl Operation for ExportKeyOperation {
4703 type RegisteredAlgorithm = ExportKeyAlgorithm;
4704}
4705
4706enum ExportKeyAlgorithm {
4709 RsassaPkcs1V1_5(SubtleAlgorithm),
4710 RsaPss(SubtleAlgorithm),
4711 RsaOaep(SubtleAlgorithm),
4712 Ecdsa(SubtleAlgorithm),
4713 Ecdh(SubtleAlgorithm),
4714 Ed25519(SubtleAlgorithm),
4715 X25519(SubtleAlgorithm),
4716 AesCtr(SubtleAlgorithm),
4717 AesCbc(SubtleAlgorithm),
4718 AesGcm(SubtleAlgorithm),
4719 AesKw(SubtleAlgorithm),
4720 Hmac(SubtleAlgorithm),
4721 MlKem(SubtleAlgorithm),
4722 MlDsa(SubtleAlgorithm),
4723 AesOcb(SubtleAlgorithm),
4724 ChaCha20Poly1305(SubtleAlgorithm),
4725}
4726
4727impl NormalizedAlgorithm for ExportKeyAlgorithm {
4728 fn from_object_value(
4729 cx: &mut js::context::JSContext,
4730 algorithm_name: CryptoAlgorithm,
4731 value: HandleValue,
4732 ) -> Fallible<Self> {
4733 match algorithm_name {
4734 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
4735 value.try_into_with_cx(cx)?,
4736 )),
4737 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(value.try_into_with_cx(cx)?)),
4738 CryptoAlgorithm::RsaOaep => {
4739 Ok(ExportKeyAlgorithm::RsaOaep(value.try_into_with_cx(cx)?))
4740 },
4741 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
4742 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(value.try_into_with_cx(cx)?)),
4743 CryptoAlgorithm::Ed25519 => {
4744 Ok(ExportKeyAlgorithm::Ed25519(value.try_into_with_cx(cx)?))
4745 },
4746 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(value.try_into_with_cx(cx)?)),
4747 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(value.try_into_with_cx(cx)?)),
4748 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(value.try_into_with_cx(cx)?)),
4749 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(value.try_into_with_cx(cx)?)),
4750 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4751 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
4752 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
4753 Ok(ExportKeyAlgorithm::MlKem(value.try_into_with_cx(cx)?))
4754 },
4755 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => {
4756 Ok(ExportKeyAlgorithm::MlDsa(value.try_into_with_cx(cx)?))
4757 },
4758 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(value.try_into_with_cx(cx)?)),
4759 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
4760 value.try_into_with_cx(cx)?,
4761 )),
4762 _ => Err(Error::NotSupported(Some(format!(
4763 "{} does not support \"exportKey\" operation",
4764 algorithm_name.as_str()
4765 )))),
4766 }
4767 }
4768
4769 fn name(&self) -> CryptoAlgorithm {
4770 match self {
4771 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
4772 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
4773 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
4774 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
4775 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
4776 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
4777 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
4778 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
4779 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
4780 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
4781 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
4782 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
4783 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
4784 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
4785 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
4786 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4787 }
4788 }
4789}
4790
4791impl ExportKeyAlgorithm {
4792 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
4793 match self {
4794 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
4795 rsassa_pkcs1_v1_5_operation::export_key(format, key)
4796 },
4797 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
4798 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
4799 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
4800 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
4801 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
4802 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
4803 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
4804 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
4805 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
4806 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
4807 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
4808 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
4809 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
4810 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
4811 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
4812 chacha20_poly1305_operation::export_key(format, key)
4813 },
4814 }
4815 }
4816}
4817
4818struct GetKeyLengthOperation {}
4820
4821impl Operation for GetKeyLengthOperation {
4822 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
4823}
4824
4825enum GetKeyLengthAlgorithm {
4828 AesCtr(SubtleAesDerivedKeyParams),
4829 AesCbc(SubtleAesDerivedKeyParams),
4830 AesGcm(SubtleAesDerivedKeyParams),
4831 AesKw(SubtleAesDerivedKeyParams),
4832 Hmac(SubtleHmacImportParams),
4833 Hkdf(SubtleAlgorithm),
4834 Pbkdf2(SubtleAlgorithm),
4835 AesOcb(SubtleAesDerivedKeyParams),
4836 ChaCha20Poly1305(SubtleAlgorithm),
4837 Argon2(SubtleAlgorithm),
4838}
4839
4840impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
4841 fn from_object_value(
4842 cx: &mut js::context::JSContext,
4843 algorithm_name: CryptoAlgorithm,
4844 value: HandleValue,
4845 ) -> Fallible<Self> {
4846 match algorithm_name {
4847 CryptoAlgorithm::AesCtr => {
4848 Ok(GetKeyLengthAlgorithm::AesCtr(value.try_into_with_cx(cx)?))
4849 },
4850 CryptoAlgorithm::AesCbc => {
4851 Ok(GetKeyLengthAlgorithm::AesCbc(value.try_into_with_cx(cx)?))
4852 },
4853 CryptoAlgorithm::AesGcm => {
4854 Ok(GetKeyLengthAlgorithm::AesGcm(value.try_into_with_cx(cx)?))
4855 },
4856 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(value.try_into_with_cx(cx)?)),
4857 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(value.try_into_with_cx(cx)?)),
4858 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(value.try_into_with_cx(cx)?)),
4859 CryptoAlgorithm::Pbkdf2 => {
4860 Ok(GetKeyLengthAlgorithm::Pbkdf2(value.try_into_with_cx(cx)?))
4861 },
4862 CryptoAlgorithm::AesOcb => {
4863 Ok(GetKeyLengthAlgorithm::AesOcb(value.try_into_with_cx(cx)?))
4864 },
4865 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
4866 value.try_into_with_cx(cx)?,
4867 )),
4868 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
4869 Ok(GetKeyLengthAlgorithm::Argon2(value.try_into_with_cx(cx)?))
4870 },
4871 _ => Err(Error::NotSupported(Some(format!(
4872 "{} does not support \"get key length\" operation",
4873 algorithm_name.as_str()
4874 )))),
4875 }
4876 }
4877
4878 fn name(&self) -> CryptoAlgorithm {
4879 match self {
4880 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
4881 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
4882 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
4883 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
4884 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
4885 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
4886 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
4887 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
4888 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4889 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
4890 }
4891 }
4892}
4893
4894impl GetKeyLengthAlgorithm {
4895 fn get_key_length(&self) -> Result<Option<u32>, Error> {
4896 match self {
4897 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
4898 aes_ctr_operation::get_key_length(algorithm)
4899 },
4900 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
4901 aes_cbc_operation::get_key_length(algorithm)
4902 },
4903 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
4904 aes_gcm_operation::get_key_length(algorithm)
4905 },
4906 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
4907 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
4908 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
4909 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
4910 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
4911 aes_ocb_operation::get_key_length(algorithm)
4912 },
4913 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
4914 chacha20_poly1305_operation::get_key_length()
4915 },
4916 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
4917 }
4918 }
4919}
4920
4921struct EncapsulateOperation {}
4923
4924impl Operation for EncapsulateOperation {
4925 type RegisteredAlgorithm = EncapsulateAlgorithm;
4926}
4927
4928enum EncapsulateAlgorithm {
4931 MlKem(SubtleAlgorithm),
4932}
4933
4934impl NormalizedAlgorithm for EncapsulateAlgorithm {
4935 fn from_object_value(
4936 cx: &mut js::context::JSContext,
4937 algorithm_name: CryptoAlgorithm,
4938 value: HandleValue,
4939 ) -> Fallible<Self> {
4940 match algorithm_name {
4941 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
4942 Ok(EncapsulateAlgorithm::MlKem(value.try_into_with_cx(cx)?))
4943 },
4944 _ => Err(Error::NotSupported(Some(format!(
4945 "{} does not support \"encapsulate\" operation",
4946 algorithm_name.as_str()
4947 )))),
4948 }
4949 }
4950
4951 fn name(&self) -> CryptoAlgorithm {
4952 match self {
4953 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
4954 }
4955 }
4956}
4957
4958impl EncapsulateAlgorithm {
4959 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
4960 match self {
4961 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
4962 }
4963 }
4964}
4965
4966struct DecapsulateOperation {}
4968
4969impl Operation for DecapsulateOperation {
4970 type RegisteredAlgorithm = DecapsulateAlgorithm;
4971}
4972
4973enum DecapsulateAlgorithm {
4976 MlKem(SubtleAlgorithm),
4977}
4978
4979impl NormalizedAlgorithm for DecapsulateAlgorithm {
4980 fn from_object_value(
4981 cx: &mut js::context::JSContext,
4982 algorithm_name: CryptoAlgorithm,
4983 value: HandleValue,
4984 ) -> Fallible<Self> {
4985 match algorithm_name {
4986 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
4987 Ok(DecapsulateAlgorithm::MlKem(value.try_into_with_cx(cx)?))
4988 },
4989 _ => Err(Error::NotSupported(Some(format!(
4990 "{} does not support \"decapsulate\" operation",
4991 algorithm_name.as_str()
4992 )))),
4993 }
4994 }
4995
4996 fn name(&self) -> CryptoAlgorithm {
4997 match self {
4998 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
4999 }
5000 }
5001}
5002
5003impl DecapsulateAlgorithm {
5004 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5005 match self {
5006 DecapsulateAlgorithm::MlKem(algorithm) => {
5007 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
5008 },
5009 }
5010 }
5011}
5012
5013struct GetPublicKeyOperation {}
5015
5016impl Operation for GetPublicKeyOperation {
5017 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
5018}
5019
5020enum GetPublicKeyAlgorithm {
5023 RsassaPkcs1v1_5(SubtleAlgorithm),
5024 RsaPss(SubtleAlgorithm),
5025 RsaOaep(SubtleAlgorithm),
5026 Ecdsa(SubtleAlgorithm),
5027 Ecdh(SubtleAlgorithm),
5028 Ed25519(SubtleAlgorithm),
5029 X25519(SubtleAlgorithm),
5030}
5031
5032impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
5033 fn from_object_value(
5034 cx: &mut js::context::JSContext,
5035 algorithm_name: CryptoAlgorithm,
5036 value: HandleValue,
5037 ) -> Fallible<Self> {
5038 match algorithm_name {
5039 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
5040 value.try_into_with_cx(cx)?,
5041 )),
5042 CryptoAlgorithm::RsaPss => {
5043 Ok(GetPublicKeyAlgorithm::RsaPss(value.try_into_with_cx(cx)?))
5044 },
5045 CryptoAlgorithm::RsaOaep => {
5046 Ok(GetPublicKeyAlgorithm::RsaOaep(value.try_into_with_cx(cx)?))
5047 },
5048 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(value.try_into_with_cx(cx)?)),
5049 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(value.try_into_with_cx(cx)?)),
5050 CryptoAlgorithm::Ed25519 => {
5051 Ok(GetPublicKeyAlgorithm::Ed25519(value.try_into_with_cx(cx)?))
5052 },
5053 CryptoAlgorithm::X25519 => {
5054 Ok(GetPublicKeyAlgorithm::X25519(value.try_into_with_cx(cx)?))
5055 },
5056 _ => Err(Error::NotSupported(Some(format!(
5057 "{} does not support \"getPublicKey\" operation",
5058 algorithm_name.as_str()
5059 )))),
5060 }
5061 }
5062
5063 fn name(&self) -> CryptoAlgorithm {
5064 match self {
5065 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
5066 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5067 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5068 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5069 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5070 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5071 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
5072 }
5073 }
5074}
5075
5076impl GetPublicKeyAlgorithm {
5077 fn get_public_key(
5078 &self,
5079 cx: &mut js::context::JSContext,
5080 global: &GlobalScope,
5081 key: &CryptoKey,
5082 algorithm: &KeyAlgorithmAndDerivatives,
5083 usages: Vec<KeyUsage>,
5084 ) -> Result<DomRoot<CryptoKey>, Error> {
5085 match self {
5086 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
5087 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
5088 },
5089 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
5090 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
5091 },
5092 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
5093 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
5094 },
5095 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
5096 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
5097 },
5098 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
5099 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
5100 },
5101 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
5102 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
5103 },
5104 GetPublicKeyAlgorithm::X25519(_algorithm) => {
5105 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
5106 },
5107 }
5108 }
5109}