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