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 ed448_operation;
19mod hkdf_operation;
20mod hmac_operation;
21mod kangarootwelve_operation;
22mod kmac_operation;
23mod ml_dsa_operation;
24mod ml_kem_operation;
25mod pbkdf2_operation;
26mod rsa_common;
27mod rsa_oaep_operation;
28mod rsa_pss_operation;
29mod rsassa_pkcs1_v1_5_operation;
30mod sha3_operation;
31mod sha_operation;
32mod turboshake_operation;
33mod x25519_operation;
34mod x448_operation;
35
36use std::fmt::Display;
37use std::ptr;
38use std::rc::Rc;
39use std::str::FromStr;
40
41use base64ct::{Base64UrlUnpadded, Encoding};
42use dom_struct::dom_struct;
43use js::conversions::{ConversionBehavior, ConversionResult, FromJSValConvertible};
44use js::jsapi::{Heap, JSObject};
45use js::jsval::UndefinedValue;
46use js::realm::CurrentRealm;
47use js::rust::wrappers2::JS_ParseJSON;
48use js::rust::{HandleObject, MutableHandleValue, Trace};
49use js::typedarray::{ArrayBufferU8, HeapUint8Array};
50use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
51use servo_constellation_traits::{
52 SerializableAesKeyAlgorithm, SerializableAlgorithm, SerializableCShakeParams,
53 SerializableDigestAlgorithm, SerializableEcKeyAlgorithm, SerializableHmacKeyAlgorithm,
54 SerializableKangarooTwelveParams, SerializableKeyAlgorithm,
55 SerializableKeyAlgorithmAndDerivatives, SerializableKmacKeyAlgorithm,
56 SerializableRsaHashedKeyAlgorithm, SerializableTurboShakeParams,
57};
58use strum::{EnumString, IntoStaticStr, VariantArray};
59use zeroize::Zeroizing;
60
61use crate::dom::bindings::buffer_source::{create_buffer_source, get_buffer_source_copy};
62use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
63 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
64};
65use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
66 AesKeyAlgorithm, Algorithm, AlgorithmIdentifier, EcKeyAlgorithm, EncapsulatedBits,
67 EncapsulatedKey, HmacKeyAlgorithm, JsonWebKey, KeyAlgorithm, KeyFormat, KmacKeyAlgorithm,
68 RsaHashedKeyAlgorithm, RsaKeyAlgorithm, SubtleCryptoMethods,
69};
70use crate::dom::bindings::codegen::UnionTypes::{
71 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
72};
73use crate::dom::bindings::conversions::{
74 SafeToJSValConvertible, StringificationBehavior, get_property,
75};
76use crate::dom::bindings::error::{Error, Fallible};
77use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
78use crate::dom::bindings::reflector::DomGlobal;
79use crate::dom::bindings::root::DomRoot;
80use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
81use crate::dom::bindings::trace::RootedTraceableBox;
82use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
83use crate::dom::globalscope::GlobalScope;
84use crate::dom::promise::Promise;
85
86const NAMED_CURVE_P256: &str = "P-256";
88const NAMED_CURVE_P384: &str = "P-384";
89const NAMED_CURVE_P521: &str = "P-521";
90
91static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
92
93#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
94enum CryptoAlgorithm {
95 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
96 RsassaPkcs1V1_5,
97 #[strum(serialize = "RSA-PSS")]
98 RsaPss,
99 #[strum(serialize = "RSA-OAEP")]
100 RsaOaep,
101 #[strum(serialize = "ECDSA")]
102 Ecdsa,
103 #[strum(serialize = "ECDH")]
104 Ecdh,
105 #[strum(serialize = "Ed25519")]
106 Ed25519,
107 #[strum(serialize = "X25519")]
108 X25519,
109 #[strum(serialize = "Ed448")]
110 Ed448,
111 #[strum(serialize = "X448")]
112 X448,
113 #[strum(serialize = "AES-CTR")]
114 AesCtr,
115 #[strum(serialize = "AES-CBC")]
116 AesCbc,
117 #[strum(serialize = "AES-GCM")]
118 AesGcm,
119 #[strum(serialize = "AES-KW")]
120 AesKw,
121 #[strum(serialize = "HMAC")]
122 Hmac,
123 #[strum(serialize = "SHA-1")]
124 Sha1,
125 #[strum(serialize = "SHA-256")]
126 Sha256,
127 #[strum(serialize = "SHA-384")]
128 Sha384,
129 #[strum(serialize = "SHA-512")]
130 Sha512,
131 #[strum(serialize = "HKDF")]
132 Hkdf,
133 #[strum(serialize = "PBKDF2")]
134 Pbkdf2,
135 #[strum(serialize = "ML-KEM-512")]
136 MlKem512,
137 #[strum(serialize = "ML-KEM-768")]
138 MlKem768,
139 #[strum(serialize = "ML-KEM-1024")]
140 MlKem1024,
141 #[strum(serialize = "ML-DSA-44")]
142 MlDsa44,
143 #[strum(serialize = "ML-DSA-65")]
144 MlDsa65,
145 #[strum(serialize = "ML-DSA-87")]
146 MlDsa87,
147 #[strum(serialize = "AES-OCB")]
148 AesOcb,
149 #[strum(serialize = "ChaCha20-Poly1305")]
150 ChaCha20Poly1305,
151 #[strum(serialize = "SHA3-256")]
152 Sha3_256,
153 #[strum(serialize = "SHA3-384")]
154 Sha3_384,
155 #[strum(serialize = "SHA3-512")]
156 Sha3_512,
157 #[strum(serialize = "cSHAKE128")]
158 CShake128,
159 #[strum(serialize = "cSHAKE256")]
160 CShake256,
161 #[strum(serialize = "TurboSHAKE128")]
162 TurboShake128,
163 #[strum(serialize = "TurboSHAKE256")]
164 TurboShake256,
165 #[strum(serialize = "KT128")]
166 Kt128,
167 #[strum(serialize = "KT256")]
168 Kt256,
169 #[strum(serialize = "KMAC128")]
170 Kmac128,
171 #[strum(serialize = "KMAC256")]
172 Kmac256,
173 #[strum(serialize = "Argon2d")]
174 Argon2D,
175 #[strum(serialize = "Argon2i")]
176 Argon2I,
177 #[strum(serialize = "Argon2id")]
178 Argon2ID,
179}
180
181impl CryptoAlgorithm {
182 fn as_str(&self) -> &'static str {
184 (*self).into()
185 }
186
187 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
188 Self::VARIANTS
189 .iter()
190 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
191 .cloned()
192 .ok_or(Error::NotSupported(Some(format!(
193 "Unsupported algorithm: {algorithm_name}"
194 ))))
195 }
196}
197
198#[dom_struct]
199pub(crate) struct SubtleCrypto {
200 reflector_: Reflector,
201}
202
203impl SubtleCrypto {
204 fn new_inherited() -> SubtleCrypto {
205 SubtleCrypto {
206 reflector_: Reflector::new(),
207 }
208 }
209
210 pub(crate) fn new(
211 cx: &mut js::context::JSContext,
212 global: &GlobalScope,
213 ) -> DomRoot<SubtleCrypto> {
214 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
215 }
216
217 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Zeroizing<Vec<u8>>) {
221 let trusted_promise = TrustedPromise::new(promise);
222 self.global()
223 .task_manager()
224 .crypto_task_source()
225 .queue(task!(resolve_data: move |cx| {
226 let promise = trusted_promise.root();
227
228 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
229 match create_buffer_source::<ArrayBufferU8>(cx,
230 &data,
231 array_buffer_ptr.handle_mut(),
232 ) {
233 Ok(_) => promise.resolve_native(cx, &*array_buffer_ptr),
234 Err(_) => promise.reject_error(cx, Error::JSFailed),
235 }
236 }));
237 }
238
239 fn resolve_promise_with_jwk(
243 &self,
244 cx: &mut js::context::JSContext,
245 promise: Rc<Promise>,
246 jwk: Box<JsonWebKey>,
247 ) {
248 let stringified_jwk = match jwk.stringify(cx) {
251 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
252 Err(error) => {
253 self.reject_promise_with_error(promise, error);
254 return;
255 },
256 };
257
258 let trusted_subtle = Trusted::new(self);
259 let trusted_promise = TrustedPromise::new(promise);
260 self.global()
261 .task_manager()
262 .crypto_task_source()
263 .queue(task!(resolve_jwk: move |cx| {
264 let subtle = trusted_subtle.root();
265 let promise = trusted_promise.root();
266
267 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
268 Ok(jwk) => {
269 rooted!(&in(cx) let mut rval = UndefinedValue());
270 jwk.safe_to_jsval(cx, rval.handle_mut());
271 rooted!(&in(cx) let mut object = rval.to_object());
272 promise.resolve_native(cx, &*object);
273 },
274 Err(error) => {
275 subtle.reject_promise_with_error(promise, error);
276 return;
277 },
278 }
279 }));
280 }
281
282 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: &CryptoKey) {
285 let trusted_key = Trusted::new(key);
286 let trusted_promise = TrustedPromise::new(promise);
287 self.global()
288 .task_manager()
289 .crypto_task_source()
290 .queue(task!(resolve_key: move |cx| {
291 let key = trusted_key.root();
292 let promise = trusted_promise.root();
293 promise.resolve_native(cx, &key);
294 }));
295 }
296
297 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
300 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
301 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
302 let trusted_promise = TrustedPromise::new(promise);
303 self.global()
304 .task_manager()
305 .crypto_task_source()
306 .queue(task!(resolve_key: move |cx| {
307 let key_pair = CryptoKeyPair {
308 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
309 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
310 };
311 let promise = trusted_promise.root();
312 promise.resolve_native(cx, &key_pair);
313 }));
314 }
315
316 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
319 let trusted_promise = TrustedPromise::new(promise);
320 self.global()
321 .task_manager()
322 .crypto_task_source()
323 .queue(task!(resolve_bool: move |cx| {
324 let promise = trusted_promise.root();
325 promise.resolve_native(cx, &result);
326 }));
327 }
328
329 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
332 let trusted_promise = TrustedPromise::new(promise);
333 self.global()
334 .task_manager()
335 .crypto_task_source()
336 .queue(task!(reject_error: move |cx| {
337 let promise = trusted_promise.root();
338 promise.reject_error(cx, error);
339 }));
340 }
341
342 fn resolve_promise_with_encapsulated_key(
346 &self,
347 promise: Rc<Promise>,
348 encapsulated_key: SubtleEncapsulatedKey,
349 ) {
350 let trusted_promise = TrustedPromise::new(promise);
351 self.global().task_manager().crypto_task_source().queue(
352 task!(resolve_encapsulated_key: move |cx| {
353 let promise = trusted_promise.root();
354 promise.resolve_native(cx, &encapsulated_key);
355 }),
356 );
357 }
358
359 fn resolve_promise_with_encapsulated_bits(
363 &self,
364 promise: Rc<Promise>,
365 encapsulated_bits: SubtleEncapsulatedBits,
366 ) {
367 let trusted_promise = TrustedPromise::new(promise);
368 self.global().task_manager().crypto_task_source().queue(
369 task!(resolve_encapsulated_bits: move |cx| {
370 let promise = trusted_promise.root();
371 promise.resolve_native(cx, &encapsulated_bits);
372 }),
373 );
374 }
375}
376
377impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
378 fn Encrypt(
380 &self,
381 cx: &mut CurrentRealm,
382 algorithm: AlgorithmIdentifier,
383 key: &CryptoKey,
384 data: ArrayBufferViewOrArrayBuffer,
385 ) -> Rc<Promise> {
386 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
394 Ok(normalized_algorithm) => normalized_algorithm,
395 Err(error) => {
396 let promise = Promise::new_in_realm(cx);
397 promise.reject_error(cx, error);
398 return promise;
399 },
400 };
401
402 let data = Zeroizing::new(get_buffer_source_copy((&data).into()));
405
406 let promise = Promise::new_in_realm(cx);
409
410 let this = Trusted::new(self);
412 let trusted_promise = TrustedPromise::new(promise.clone());
413 let trusted_key = Trusted::new(key);
414 self.global()
415 .task_manager()
416 .dom_manipulation_task_source()
417 .queue(task!(encrypt: move || {
418 let subtle = this.root();
419 let promise = trusted_promise.root();
420 let key = trusted_key.root();
421
422 if normalized_algorithm.name() != key.algorithm().name() {
430 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Algorithm's name does not equal key algorithm name".into())));
431 return;
432 }
433
434 if !key.usages().contains(&KeyUsage::Encrypt) {
437 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'encrypt' entry".into())));
438 return;
439 }
440
441 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
445 Ok(ciphertext) => ciphertext,
446 Err(error) => {
447 subtle.reject_promise_with_error(promise, error);
448 return;
449 },
450 };
451
452 subtle.resolve_promise_with_data(promise, ciphertext.into());
458 }));
459 promise
460 }
461
462 fn Decrypt(
464 &self,
465 cx: &mut CurrentRealm,
466 algorithm: AlgorithmIdentifier,
467 key: &CryptoKey,
468 data: ArrayBufferViewOrArrayBuffer,
469 ) -> Rc<Promise> {
470 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
478 Ok(normalized_algorithm) => normalized_algorithm,
479 Err(error) => {
480 let promise = Promise::new_in_realm(cx);
481 promise.reject_error(cx, error);
482 return promise;
483 },
484 };
485
486 let data = get_buffer_source_copy((&data).into());
489
490 let promise = Promise::new_in_realm(cx);
493
494 let this = Trusted::new(self);
496 let trusted_promise = TrustedPromise::new(promise.clone());
497 let trusted_key = Trusted::new(key);
498 self.global()
499 .task_manager()
500 .dom_manipulation_task_source()
501 .queue(task!(decrypt: move || {
502 let subtle = this.root();
503 let promise = trusted_promise.root();
504 let key = trusted_key.root();
505
506 if normalized_algorithm.name() != key.algorithm().name() {
514 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
515 return;
516 }
517
518 if !key.usages().contains(&KeyUsage::Decrypt) {
521 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'decrypt' entry".into())));
522 return;
523 }
524
525 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
529 Ok(plaintext) => Zeroizing::new(plaintext),
530 Err(error) => {
531 subtle.reject_promise_with_error(promise, error);
532 return;
533 },
534 };
535
536 subtle.resolve_promise_with_data(promise, plaintext);
542 }));
543 promise
544 }
545
546 fn Sign(
548 &self,
549 cx: &mut CurrentRealm,
550 algorithm: AlgorithmIdentifier,
551 key: &CryptoKey,
552 data: ArrayBufferViewOrArrayBuffer,
553 ) -> Rc<Promise> {
554 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
562 Ok(normalized_algorithm) => normalized_algorithm,
563 Err(error) => {
564 let promise = Promise::new_in_realm(cx);
565 promise.reject_error(cx, error);
566 return promise;
567 },
568 };
569
570 let data = get_buffer_source_copy((&data).into());
573
574 let promise = Promise::new_in_realm(cx);
577
578 let this = Trusted::new(self);
580 let trusted_promise = TrustedPromise::new(promise.clone());
581 let trusted_key = Trusted::new(key);
582 self.global()
583 .task_manager()
584 .dom_manipulation_task_source()
585 .queue(task!(sign: move || {
586 let subtle = this.root();
587 let promise = trusted_promise.root();
588 let key = trusted_key.root();
589
590 if normalized_algorithm.name() != key.algorithm().name() {
598 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
599 return;
600 }
601
602 if !key.usages().contains(&KeyUsage::Sign) {
605 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'sign' entry".into())));
606 return;
607 }
608
609 let signature = match normalized_algorithm.sign(&key, &data) {
612 Ok(signature) => signature,
613 Err(error) => {
614 subtle.reject_promise_with_error(promise, error);
615 return;
616 },
617 };
618
619 subtle.resolve_promise_with_data(promise, signature.into());
625 }));
626 promise
627 }
628
629 fn Verify(
631 &self,
632 cx: &mut CurrentRealm,
633 algorithm: AlgorithmIdentifier,
634 key: &CryptoKey,
635 signature: ArrayBufferViewOrArrayBuffer,
636 data: ArrayBufferViewOrArrayBuffer,
637 ) -> Rc<Promise> {
638 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
646 Ok(algorithm) => algorithm,
647 Err(error) => {
648 let promise = Promise::new_in_realm(cx);
649 promise.reject_error(cx, error);
650 return promise;
651 },
652 };
653
654 let signature = get_buffer_source_copy((&signature).into());
657
658 let data = get_buffer_source_copy((&data).into());
661
662 let promise = Promise::new_in_realm(cx);
665
666 let this = Trusted::new(self);
668 let trusted_promise = TrustedPromise::new(promise.clone());
669 let trusted_key = Trusted::new(key);
670 self.global()
671 .task_manager()
672 .dom_manipulation_task_source()
673 .queue(task!(sign: move || {
674 let subtle = this.root();
675 let promise = trusted_promise.root();
676 let key = trusted_key.root();
677
678 if normalized_algorithm.name() != key.algorithm().name() {
686 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
687 return;
688 }
689
690 if !key.usages().contains(&KeyUsage::Verify) {
693 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'verify' entry".into())));
694 return;
695 }
696
697 let result = match normalized_algorithm.verify(&key, &data, &signature) {
701 Ok(result) => result,
702 Err(error) => {
703 subtle.reject_promise_with_error(promise, error);
704 return;
705 },
706 };
707
708 subtle.resolve_promise_with_bool(promise, result);
712 }));
713 promise
714 }
715
716 fn Digest(
718 &self,
719 cx: &mut CurrentRealm,
720 algorithm: AlgorithmIdentifier,
721 data: ArrayBufferViewOrArrayBuffer,
722 ) -> Rc<Promise> {
723 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
730 Ok(normalized_algorithm) => normalized_algorithm,
731 Err(error) => {
732 let promise = Promise::new_in_realm(cx);
733 promise.reject_error(cx, error);
734 return promise;
735 },
736 };
737
738 let data = get_buffer_source_copy((&data).into());
741
742 let promise = Promise::new_in_realm(cx);
745
746 let this = Trusted::new(self);
748 let trusted_promise = TrustedPromise::new(promise.clone());
749 self.global()
750 .task_manager()
751 .dom_manipulation_task_source()
752 .queue(task!(digest_: move || {
753 let subtle = this.root();
754 let promise = trusted_promise.root();
755
756 let digest = match normalized_algorithm.digest(&data) {
763 Ok(digest) => digest,
764 Err(error) => {
765 subtle.reject_promise_with_error(promise, error);
766 return;
767 }
768 };
769
770 subtle.resolve_promise_with_data(promise, digest.into());
776 }));
777 promise
778 }
779
780 fn GenerateKey(
782 &self,
783 cx: &mut CurrentRealm,
784 algorithm: AlgorithmIdentifier,
785 extractable: bool,
786 key_usages: Vec<KeyUsage>,
787 ) -> Rc<Promise> {
788 let promise = Promise::new_in_realm(cx);
795 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
796 {
797 Ok(normalized_algorithm) => normalized_algorithm,
798 Err(error) => {
799 promise.reject_error(cx, error);
800 return promise;
801 },
802 };
803
804 let trusted_subtle = Trusted::new(self);
810 let trusted_promise = TrustedPromise::new(promise.clone());
811 self.global()
812 .task_manager()
813 .dom_manipulation_task_source()
814 .queue(task!(generate_key: move |cx| {
815 let subtle = trusted_subtle.root();
816 let promise = trusted_promise.root();
817
818 let result = match normalized_algorithm.generate_key(
825 cx,
826 &subtle.global(),
827 extractable,
828 key_usages,
829 ) {
830 Ok(result) => result,
831 Err(error) => {
832 subtle.reject_promise_with_error(promise, error);
833 return;
834 }
835 };
836
837 match &result {
845 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
846 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
847 && crpyto_key.usages().is_empty()
848 {
849 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Crypto key usages is empty".into())));
850 return;
851 }
852 },
853 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
854 if crypto_key_pair
855 .privateKey
856 .as_ref()
857 .is_none_or(|private_key| private_key.usages().is_empty())
858 {
859 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Private key usages is an empty sequence".into())));
860 return;
861 }
862 }
863 };
864
865 match result {
871 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
872 subtle.resolve_promise_with_key(promise, &key);
873 },
874 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
875 subtle.resolve_promise_with_key_pair(promise, key_pair);
876 },
877 }
878 }));
879
880 promise
881 }
882
883 fn DeriveKey(
885 &self,
886 cx: &mut CurrentRealm,
887 algorithm: AlgorithmIdentifier,
888 base_key: &CryptoKey,
889 derived_key_type: AlgorithmIdentifier,
890 extractable: bool,
891 usages: Vec<KeyUsage>,
892 ) -> Rc<Promise> {
893 let promise = Promise::new_in_realm(cx);
902 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
903 {
904 Ok(normalized_algorithm) => normalized_algorithm,
905 Err(error) => {
906 promise.reject_error(cx, error);
907 return promise;
908 },
909 };
910
911 let normalized_derived_key_algorithm_import =
916 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
917 Ok(normalized_algorithm) => normalized_algorithm,
918 Err(error) => {
919 promise.reject_error(cx, error);
920 return promise;
921 },
922 };
923
924 let normalized_derived_key_algorithm_length =
929 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
930 Ok(normalized_algorithm) => normalized_algorithm,
931 Err(error) => {
932 promise.reject_error(cx, error);
933 return promise;
934 },
935 };
936
937 let trusted_subtle = Trusted::new(self);
943 let trusted_base_key = Trusted::new(base_key);
944 let trusted_promise = TrustedPromise::new(promise.clone());
945 self.global().task_manager().dom_manipulation_task_source().queue(
946 task!(derive_key: move |cx| {
947 let subtle = trusted_subtle.root();
948 let base_key = trusted_base_key.root();
949 let promise = trusted_promise.root();
950
951 if normalized_algorithm.name() != base_key.algorithm().name() {
959 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
960 return;
961 }
962
963 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
966 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveKey' entry".into())));
967 return;
968 }
969
970 let length = match normalized_derived_key_algorithm_length.get_key_length() {
973 Ok(length) => length,
974 Err(error) => {
975 subtle.reject_promise_with_error(promise, error);
976 return;
977 }
978 };
979
980 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
983 Ok(secret) => Zeroizing::new(secret),
984 Err(error) => {
985 subtle.reject_promise_with_error(promise, error);
986 return;
987 }
988 };
989
990 let result = match normalized_derived_key_algorithm_import.import_key(
996 cx,
997 &subtle.global(),
998 KeyFormat::Raw_secret,
999 &secret,
1000 extractable,
1001 usages.clone(),
1002 ) {
1003 Ok(algorithm) => algorithm,
1004 Err(error) => {
1005 subtle.reject_promise_with_error(promise, error);
1006 return;
1007 },
1008 };
1009
1010 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1013 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1014 return;
1015 }
1016
1017 subtle.resolve_promise_with_key(promise, &result);
1028 }),
1029 );
1030 promise
1031 }
1032
1033 fn DeriveBits(
1035 &self,
1036 cx: &mut CurrentRealm,
1037 algorithm: AlgorithmIdentifier,
1038 base_key: &CryptoKey,
1039 length: Option<u32>,
1040 ) -> Rc<Promise> {
1041 let promise = Promise::new_in_realm(cx);
1049 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1050 {
1051 Ok(normalized_algorithm) => normalized_algorithm,
1052 Err(error) => {
1053 promise.reject_error(cx, error);
1054 return promise;
1055 },
1056 };
1057
1058 let trsuted_subtle = Trusted::new(self);
1064 let trusted_base_key = Trusted::new(base_key);
1065 let trusted_promise = TrustedPromise::new(promise.clone());
1066 self.global()
1067 .task_manager()
1068 .dom_manipulation_task_source()
1069 .queue(task!(import_key: move || {
1070 let subtle = trsuted_subtle.root();
1071 let base_key = trusted_base_key.root();
1072 let promise = trusted_promise.root();
1073
1074 if normalized_algorithm.name() != base_key.algorithm().name() {
1082 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
1083 return;
1084 }
1085
1086 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1089 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveBits' entry".into())));
1090 return;
1091 }
1092
1093 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1096 Ok(bits) => Zeroizing::new(bits),
1097 Err(error) => {
1098 subtle.reject_promise_with_error(promise, error);
1099 return;
1100 }
1101 };
1102
1103 subtle.resolve_promise_with_data(promise, bits);
1109 }));
1110 promise
1111 }
1112
1113 fn ImportKey(
1115 &self,
1116 cx: &mut CurrentRealm,
1117 format: KeyFormat,
1118 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1119 algorithm: AlgorithmIdentifier,
1120 extractable: bool,
1121 key_usages: Vec<KeyUsage>,
1122 ) -> Rc<Promise> {
1123 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1130 Ok(algorithm) => algorithm,
1131 Err(error) => {
1132 let promise = Promise::new_in_realm(cx);
1133 promise.reject_error(cx, error);
1134 return promise;
1135 },
1136 };
1137
1138 let key_data = match format {
1140 KeyFormat::Jwk => {
1142 match key_data {
1143 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1144 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1145 let promise = Promise::new_in_realm(cx);
1148 promise.reject_error(
1149 cx,
1150 Error::Type(c"The keyData type does not match the format".to_owned()),
1151 );
1152 return promise;
1153 },
1154
1155 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1156 match jwk.stringify(cx) {
1164 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1165 Err(error) => {
1166 let promise = Promise::new_in_realm(cx);
1167 promise.reject_error(cx, error);
1168 return promise;
1169 },
1170 }
1171 },
1172 }
1173 },
1174 _ => {
1176 match &key_data {
1177 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1180 let promise = Promise::new_in_realm(cx);
1181 promise.reject_error(
1182 cx,
1183 Error::Type(c"The keyData type does not match the format".to_owned()),
1184 );
1185 return promise;
1186 },
1187
1188 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1191 Zeroizing::new(get_buffer_source_copy(view.into()))
1192 },
1193 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1194 Zeroizing::new(get_buffer_source_copy(buffer.into()))
1195 },
1196 }
1197 },
1198 };
1199
1200 let promise = Promise::new_in_realm(cx);
1203
1204 let this = Trusted::new(self);
1206 let trusted_promise = TrustedPromise::new(promise.clone());
1207 self.global()
1208 .task_manager()
1209 .dom_manipulation_task_source()
1210 .queue(task!(import_key: move |cx| {
1211 let subtle = this.root();
1212 let promise = trusted_promise.root();
1213
1214 let result = match normalized_algorithm.import_key(
1222 cx,
1223 &subtle.global(),
1224 format,
1225 &key_data,
1226 extractable,
1227 key_usages.clone(),
1228 ) {
1229 Ok(key) => key,
1230 Err(error) => {
1231 subtle.reject_promise_with_error(promise, error);
1232 return;
1233 },
1234 };
1235
1236 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1239 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1240 return;
1241 }
1242
1243 result.set_extractable(extractable);
1245
1246 result.set_usages(cx, &key_usages);
1248
1249 subtle.resolve_promise_with_key(promise, &result);
1255 }));
1256
1257 promise
1258 }
1259
1260 fn ExportKey(&self, cx: &mut CurrentRealm, format: KeyFormat, key: &CryptoKey) -> Rc<Promise> {
1262 let promise = Promise::new_in_realm(cx);
1269
1270 let trusted_subtle = Trusted::new(self);
1272 let trusted_promise = TrustedPromise::new(promise.clone());
1273 let trusted_key = Trusted::new(key);
1274 self.global()
1275 .task_manager()
1276 .dom_manipulation_task_source()
1277 .queue(task!(export_key: move |cx| {
1278 let subtle = trusted_subtle.root();
1279 let promise = trusted_promise.root();
1280 let key = trusted_key.root();
1281
1282 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1293 cx,
1294 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1295 ) {
1296 Ok(normalized_algorithm) => normalized_algorithm,
1297 Err(error) => {
1298 subtle.reject_promise_with_error(promise, error);
1299 return;
1300 },
1301 };
1302
1303 if !key.Extractable() {
1306 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key is not extractable".into())));
1307 return;
1308 }
1309
1310 let result = match export_key_algorithm.export_key(format, &key) {
1313 Ok(exported_key) => exported_key,
1314 Err(error) => {
1315 subtle.reject_promise_with_error(promise, error);
1316 return;
1317 },
1318 };
1319
1320 match result {
1333 ExportedKey::Bytes(bytes) => {
1334 subtle.resolve_promise_with_data(promise, bytes);
1335 },
1336 ExportedKey::Jwk(jwk) => {
1337 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1338 },
1339 }
1340 }));
1341 promise
1342 }
1343
1344 fn WrapKey(
1346 &self,
1347 cx: &mut CurrentRealm,
1348 format: KeyFormat,
1349 key: &CryptoKey,
1350 wrapping_key: &CryptoKey,
1351 algorithm: AlgorithmIdentifier,
1352 ) -> Rc<Promise> {
1353 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1363 WrapKeyAlgorithm(WrapKeyAlgorithm),
1364 EncryptAlgorithm(EncryptAlgorithm),
1365 }
1366 let normalized_algorithm = if let Ok(algorithm) =
1367 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1368 {
1369 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1370 } else {
1371 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1372 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1373 Err(error) => {
1374 let promise = Promise::new_in_realm(cx);
1375 promise.reject_error(cx, error);
1376 return promise;
1377 },
1378 }
1379 };
1380
1381 let promise = Promise::new_in_realm(cx);
1384
1385 let trusted_subtle = Trusted::new(self);
1387 let trusted_key = Trusted::new(key);
1388 let trusted_wrapping_key = Trusted::new(wrapping_key);
1389 let trusted_promise = TrustedPromise::new(promise.clone());
1390 self.global()
1391 .task_manager()
1392 .dom_manipulation_task_source()
1393 .queue(task!(wrap_key: move |cx| {
1394 let subtle = trusted_subtle.root();
1395 let key = trusted_key.root();
1396 let wrapping_key = trusted_wrapping_key.root();
1397 let promise = trusted_promise.root();
1398
1399 let normalized_algorithm_name = match &normalized_algorithm {
1407 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1408 algorithm.name()
1409 },
1410 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1411 algorithm.name()
1412 },
1413 };
1414 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1415 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of wrapping key algorithm".into())));
1416 return;
1417 }
1418
1419 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1422 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Wrapping key usages does not contain 'wrapKey' entry".into())));
1423 return;
1424 }
1425
1426 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1432 cx,
1433 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1434 ) {
1435 Ok(normalized_algorithm) => normalized_algorithm,
1436 Err(error) => {
1437 subtle.reject_promise_with_error(promise, error);
1438 return;
1439 },
1440 };
1441
1442 if !key.Extractable() {
1445 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key is not extractable".into())));
1446 return;
1447 }
1448
1449 let exported_key = match export_key_algorithm.export_key(format, &key) {
1452 Ok(exported_key) => exported_key,
1453 Err(error) => {
1454 subtle.reject_promise_with_error(promise, error);
1455 return;
1456 },
1457 };
1458
1459 let bytes = match exported_key {
1471 ExportedKey::Bytes(bytes) => bytes,
1472 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1473 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.as_bytes().to_vec()),
1474 Err(error) => {
1475 subtle.reject_promise_with_error(promise, error);
1476 return;
1477 },
1478 },
1479 };
1480
1481 let result = match normalized_algorithm {
1493 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1494 algorithm.wrap_key(&wrapping_key, &bytes)
1495 },
1496 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1497 algorithm.encrypt(&wrapping_key, &bytes)
1498 },
1499 };
1500 let result = match result {
1501 Ok(result) => result,
1502 Err(error) => {
1503 subtle.reject_promise_with_error(promise, error);
1504 return;
1505 },
1506 };
1507
1508 subtle.resolve_promise_with_data(promise, result.into());
1514 }));
1515 promise
1516 }
1517
1518 fn UnwrapKey(
1520 &self,
1521 cx: &mut CurrentRealm,
1522 format: KeyFormat,
1523 wrapped_key: ArrayBufferViewOrArrayBuffer,
1524 unwrapping_key: &CryptoKey,
1525 algorithm: AlgorithmIdentifier,
1526 unwrapped_key_algorithm: AlgorithmIdentifier,
1527 extractable: bool,
1528 usages: Vec<KeyUsage>,
1529 ) -> Rc<Promise> {
1530 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1541 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1542 DecryptAlgorithm(DecryptAlgorithm),
1543 }
1544 let normalized_algorithm = if let Ok(algorithm) =
1545 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1546 {
1547 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1548 } else {
1549 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1550 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1551 Err(error) => {
1552 let promise = Promise::new_in_realm(cx);
1553 promise.reject_error(cx, error);
1554 return promise;
1555 },
1556 }
1557 };
1558
1559 let normalized_key_algorithm =
1563 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1564 Ok(algorithm) => algorithm,
1565 Err(error) => {
1566 let promise = Promise::new_in_realm(cx);
1567 promise.reject_error(cx, error);
1568 return promise;
1569 },
1570 };
1571
1572 let wrapped_key = get_buffer_source_copy((&wrapped_key).into());
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(Some("Normalized algorithm name does not equal name of unwrapping key algorithm".into())));
1607 return;
1608 }
1609
1610 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1613 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Unwrapping key usages does not contain 'unwrapKey' entry".into())));
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) => Zeroizing::new(bytes),
1638 Err(error) => {
1639 subtle.reject_promise_with_error(promise, error);
1640 return;
1641 },
1642 };
1643
1644 if format == KeyFormat::Jwk
1655 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1656 subtle.reject_promise_with_error(promise, error);
1657 return;
1658 }
1659 let key = bytes;
1660
1661 let result = match normalized_key_algorithm.import_key(
1665 cx,
1666 &subtle.global(),
1667 format,
1668 &key,
1669 extractable,
1670 usages.clone(),
1671 ) {
1672 Ok(result) => result,
1673 Err(error) => {
1674 subtle.reject_promise_with_error(promise, error);
1675 return;
1676 },
1677 };
1678
1679 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1682 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1683 return;
1684 }
1685
1686 subtle.resolve_promise_with_key(promise, &result);
1697 }),
1698 );
1699 promise
1700 }
1701
1702 fn EncapsulateKey(
1704 &self,
1705 cx: &mut CurrentRealm,
1706 encapsulation_algorithm: AlgorithmIdentifier,
1707 encapsulation_key: &CryptoKey,
1708 shared_key_algorithm: AlgorithmIdentifier,
1709 extractable: bool,
1710 usages: Vec<KeyUsage>,
1711 ) -> Rc<Promise> {
1712 let promise = Promise::new_in_realm(cx);
1722 let normalized_encapsulation_algorithm =
1723 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1724 Ok(algorithm) => algorithm,
1725 Err(error) => {
1726 promise.reject_error(cx, error);
1727 return promise;
1728 },
1729 };
1730
1731 let normalized_shared_key_algorithm =
1736 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1737 Ok(algorithm) => algorithm,
1738 Err(error) => {
1739 promise.reject_error(cx, error);
1740 return promise;
1741 },
1742 };
1743
1744 let trusted_subtle = Trusted::new(self);
1750 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1751 let trusted_promise = TrustedPromise::new(promise.clone());
1752 self.global().task_manager().dom_manipulation_task_source().queue(
1753 task!(encapsulate_keys: move |cx| {
1754 let subtle = trusted_subtle.root();
1755 let encapsulation_key = trusted_encapsulated_key.root();
1756 let promise = trusted_promise.root();
1757
1758 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1766 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1767 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1768 normalizedEncapsulationAlgorithm".to_string(),
1769 )));
1770 return;
1771 }
1772
1773 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1776 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1777 "[[usages]] internal slot of encapsulationKey does not contain an \
1778 entry that is \"encapsulateBits\"".to_string(),
1779 )));
1780 return;
1781 }
1782
1783 let encapsulated_bits_result =
1789 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1790 let encapsulated_bits = match encapsulated_bits_result {
1791 Ok(encapsulated_bits) => encapsulated_bits,
1792 Err(error) => {
1793 subtle.reject_promise_with_error(promise, error);
1794 return;
1795 },
1796 };
1797
1798 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1806 Some(shared_key) => shared_key,
1807 None => {
1808 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1809 "Shared key is missing in the result of the encapsulate operation"
1810 .to_string())));
1811 return;
1812 },
1813 };
1814 let shared_key_result = normalized_shared_key_algorithm.import_key(
1815 cx,
1816 &subtle.global(),
1817 KeyFormat::Raw_secret,
1818 encapsulated_shared_key,
1819 extractable,
1820 usages.clone(),
1821 );
1822 let shared_key = match shared_key_result {
1823 Ok(shared_key) => shared_key,
1824 Err(error) => {
1825 subtle.reject_promise_with_error(promise, error);
1826 return;
1827 },
1828 };
1829
1830 let encapsulated_key = SubtleEncapsulatedKey {
1833 shared_key: Some(Trusted::new(&shared_key)),
1834 ciphertext:encapsulated_bits.ciphertext,
1835 };
1836
1837 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1843 })
1844 );
1845 promise
1846 }
1847
1848 fn EncapsulateBits(
1850 &self,
1851 cx: &mut CurrentRealm,
1852 encapsulation_algorithm: AlgorithmIdentifier,
1853 encapsulation_key: &CryptoKey,
1854 ) -> Rc<Promise> {
1855 let promise = Promise::new_in_realm(cx);
1863 let normalized_encapsulation_algorithm =
1864 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1865 Ok(algorithm) => algorithm,
1866 Err(error) => {
1867 promise.reject_error(cx, error);
1868 return promise;
1869 },
1870 };
1871
1872 let trusted_subtle = Trusted::new(self);
1878 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1879 let trusted_promise = TrustedPromise::new(promise.clone());
1880 self.global().task_manager().dom_manipulation_task_source().queue(
1881 task!(derive_key: move || {
1882 let subtle = trusted_subtle.root();
1883 let encapsulation_key = trusted_encapsulation_key.root();
1884 let promise = trusted_promise.root();
1885
1886 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1894 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1895 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1896 normalizedEncapsulationAlgorithm".to_string(),
1897 )));
1898 return;
1899 }
1900
1901 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1904 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1905 "[[usages]] internal slot of encapsulationKey does not contain an \
1906 entry that is \"encapsulateBits\"".to_string(),
1907 )));
1908 return;
1909 }
1910
1911 let encapsulated_bits =
1917 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1918 Ok(encapsulated_bits) => encapsulated_bits,
1919 Err(error) => {
1920 subtle.reject_promise_with_error(promise, error);
1921 return;
1922 },
1923 };
1924
1925 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1931 }),
1932 );
1933 promise
1934 }
1935
1936 fn DecapsulateKey(
1938 &self,
1939 cx: &mut CurrentRealm,
1940 decapsulation_algorithm: AlgorithmIdentifier,
1941 decapsulation_key: &CryptoKey,
1942 ciphertext: ArrayBufferViewOrArrayBuffer,
1943 shared_key_algorithm: AlgorithmIdentifier,
1944 extractable: bool,
1945 usages: Vec<KeyUsage>,
1946 ) -> Rc<Promise> {
1947 let normalized_decapsulation_algorithm =
1957 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
1958 Ok(normalized_algorithm) => normalized_algorithm,
1959 Err(error) => {
1960 let promise = Promise::new_in_realm(cx);
1961 promise.reject_error(cx, error);
1962 return promise;
1963 },
1964 };
1965
1966 let normalized_shared_key_algorithm =
1971 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1972 Ok(normalized_algorithm) => normalized_algorithm,
1973 Err(error) => {
1974 let promise = Promise::new_in_realm(cx);
1975 promise.reject_error(cx, error);
1976 return promise;
1977 },
1978 };
1979
1980 let ciphertext = get_buffer_source_copy((&ciphertext).into());
1983
1984 let promise = Promise::new_in_realm(cx);
1987
1988 let trusted_subtle = Trusted::new(self);
1990 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
1991 let trusted_promise = TrustedPromise::new(promise.clone());
1992 self.global()
1993 .task_manager()
1994 .dom_manipulation_task_source()
1995 .queue(task!(decapsulate_key: move |cx| {
1996 let subtle = trusted_subtle.root();
1997 let promise = trusted_promise.root();
1998 let decapsulation_key = trusted_decapsulation_key.root();
1999
2000 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2008 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2009 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2010 normalizedDecapsulationAlgorithm".to_string()
2011 )));
2012 return;
2013 }
2014
2015 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2018 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2019 "[[usages]] internal slot of decapsulationKey does not contain an \
2020 entry that is \"decapsulateBits\"".to_string(),
2021 )));
2022 return;
2023 }
2024
2025 let decapsulated_bits_result =
2031 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2032 let decapsulated_bits = match decapsulated_bits_result {
2033 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2034 Err(error) => {
2035 subtle.reject_promise_with_error(promise, error);
2036 return;
2037 },
2038 };
2039
2040
2041 let shared_key_result = normalized_shared_key_algorithm.import_key(
2049 cx,
2050 &subtle.global(),
2051 KeyFormat::Raw_secret,
2052 &decapsulated_bits,
2053 extractable,
2054 usages.clone(),
2055 );
2056 let shared_key = match shared_key_result {
2057 Ok(shared_key) => shared_key,
2058 Err(error) => {
2059 subtle.reject_promise_with_error(promise, error);
2060 return;
2061 },
2062 };
2063
2064
2065 subtle.resolve_promise_with_key(promise, &shared_key);
2071 }));
2072 promise
2073 }
2074
2075 fn DecapsulateBits(
2077 &self,
2078 cx: &mut CurrentRealm,
2079 decapsulation_algorithm: AlgorithmIdentifier,
2080 decapsulation_key: &CryptoKey,
2081 ciphertext: ArrayBufferViewOrArrayBuffer,
2082 ) -> Rc<Promise> {
2083 let normalized_decapsulation_algorithm =
2091 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2092 Ok(normalized_algorithm) => normalized_algorithm,
2093 Err(error) => {
2094 let promise = Promise::new_in_realm(cx);
2095 promise.reject_error(cx, error);
2096 return promise;
2097 },
2098 };
2099
2100 let ciphertext = get_buffer_source_copy((&ciphertext).into());
2103
2104 let promise = Promise::new_in_realm(cx);
2107
2108 let trusted_subtle = Trusted::new(self);
2110 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2111 let trusted_promise = TrustedPromise::new(promise.clone());
2112 self.global()
2113 .task_manager()
2114 .dom_manipulation_task_source()
2115 .queue(task!(decapsulate_bits: move || {
2116 let subtle = trusted_subtle.root();
2117 let promise = trusted_promise.root();
2118 let decapsulation_key = trusted_decapsulation_key.root();
2119
2120 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2128 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2129 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2130 normalizedDecapsulationAlgorithm".to_string()
2131 )));
2132 return;
2133 }
2134
2135 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2138 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2139 "[[usages]] internal slot of decapsulationKey does not contain an \
2140 entry that is \"decapsulateBits\"".to_string(),
2141 )));
2142 return;
2143 }
2144
2145 let decapsulated_bits_result =
2151 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2152 let decapsulated_bits = match decapsulated_bits_result {
2153 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2154 Err(error) => {
2155 subtle.reject_promise_with_error(promise, error);
2156 return;
2157 },
2158 };
2159
2160 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2166 }));
2167 promise
2168 }
2169
2170 fn GetPublicKey(
2172 &self,
2173 cx: &mut CurrentRealm,
2174 key: &CryptoKey,
2175 usages: Vec<KeyUsage>,
2176 ) -> Rc<Promise> {
2177 let algorithm = key.algorithm();
2182
2183 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2190 cx,
2191 &AlgorithmIdentifier::String(DOMString::from(algorithm.name().as_str())),
2192 ) {
2193 Ok(normalized_algorithm) => normalized_algorithm,
2194 Err(error) => {
2195 let promise = Promise::new_in_realm(cx);
2196 promise.reject_error(cx, error);
2197 return promise;
2198 },
2199 };
2200
2201 let promise = Promise::new_in_realm(cx);
2204
2205 let trusted_subtle = Trusted::new(self);
2207 let trusted_promise = TrustedPromise::new(promise.clone());
2208 let trusted_key = Trusted::new(key);
2209 self.global()
2210 .task_manager()
2211 .dom_manipulation_task_source()
2212 .queue(task!(get_public_key: move |cx| {
2213 let subtle = trusted_subtle.root();
2214 let promise = trusted_promise.root();
2215 let key = trusted_key.root();
2216
2217 if key.Type() != KeyType::Private {
2224 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2225 "[[type]] internal slot of key is not \"private\"".to_string()
2226 )));
2227 return;
2228 }
2229
2230 let result = match get_public_key_algorithm.get_public_key(
2244 cx,
2245 &subtle.global(),
2246 &key,
2247 key.algorithm(),
2248 usages.clone(),
2249 ) {
2250 Ok(public_key) => public_key,
2251 Err(error) => {
2252 subtle.reject_promise_with_error(promise, error);
2253 return;
2254 },
2255 };
2256
2257 subtle.resolve_promise_with_key(promise, &result);
2263 }));
2264 promise
2265 }
2266
2267 fn Supports(
2269 cx: &mut js::context::JSContext,
2270 _global: &GlobalScope,
2271 operation: DOMString,
2272 algorithm: AlgorithmIdentifier,
2273 length: Option<u32>,
2274 ) -> bool {
2275 let operation = &*operation.str();
2280 if !matches!(
2281 operation,
2282 "encrypt" |
2283 "decrypt" |
2284 "sign" |
2285 "verify" |
2286 "digest" |
2287 "generateKey" |
2288 "deriveKey" |
2289 "deriveBits" |
2290 "importKey" |
2291 "exportKey" |
2292 "wrapKey" |
2293 "unwrapKey" |
2294 "encapsulateKey" |
2295 "encapsulateBits" |
2296 "decapsulateKey" |
2297 "decapsulateBits" |
2298 "getPublicKey"
2299 ) {
2300 return false;
2301 }
2302
2303 check_support_for_algorithm(cx, operation, &algorithm, length)
2306 }
2307
2308 fn Supports_(
2310 cx: &mut js::context::JSContext,
2311 _global: &GlobalScope,
2312 operation: DOMString,
2313 algorithm: AlgorithmIdentifier,
2314 additional_algorithm: AlgorithmIdentifier,
2315 ) -> bool {
2316 let mut operation = &*operation.str();
2321 if !matches!(
2322 operation,
2323 "encrypt" |
2324 "decrypt" |
2325 "sign" |
2326 "verify" |
2327 "digest" |
2328 "generateKey" |
2329 "deriveKey" |
2330 "deriveBits" |
2331 "importKey" |
2332 "exportKey" |
2333 "wrapKey" |
2334 "unwrapKey" |
2335 "encapsulateKey" |
2336 "encapsulateBits" |
2337 "decapsulateKey" |
2338 "decapsulateBits" |
2339 "getPublicKey"
2340 ) {
2341 return false;
2342 }
2343
2344 if matches!(
2352 operation,
2353 "deriveKey" | "unwrapKey" | "encapsulateKey" | "decapsulateKey"
2354 ) && !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2355 {
2356 return false;
2357 }
2358 if operation == "wrapKey" &&
2359 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2360 {
2361 return false;
2362 }
2363
2364 let mut length = None;
2366
2367 if operation == "deriveKey" {
2369 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2372 return false;
2373 }
2374
2375 let Ok(normalized_additional_algorithm) =
2378 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2379 else {
2380 return false;
2381 };
2382
2383 match normalized_additional_algorithm.get_key_length() {
2386 Ok(key_length) => {
2387 length = key_length;
2388 },
2389 Err(_) => return false,
2390 };
2391
2392 operation = "deriveBits";
2394 }
2395
2396 check_support_for_algorithm(cx, operation, &algorithm, length)
2399 }
2400}
2401
2402pub(crate) fn check_support_for_algorithm(
2404 cx: &mut js::context::JSContext,
2405 mut operation: &str,
2406 algorithm: &AlgorithmIdentifier,
2407 length: Option<u32>,
2408) -> bool {
2409 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2411 operation = "encapsulate";
2412 }
2413
2414 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2416 operation = "decapsulate";
2417 }
2418
2419 if operation == "getPublicKey" {
2421 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2425 else {
2426 return false;
2427 };
2428
2429 return normalize_algorithm::<GetPublicKeyOperation>(
2436 cx,
2437 &AlgorithmIdentifier::String(DOMString::from(normalized_algorithm.name().as_str())),
2438 )
2439 .is_ok();
2440 }
2441
2442 match operation {
2481 "encrypt" => {
2482 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2483 else {
2484 return false;
2485 };
2486
2487 match normalized_algorithm {
2488 EncryptAlgorithm::RsaOaep(_) => true,
2489 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2490 normalized_algorithm.counter.len() == 16 &&
2491 normalized_algorithm.length != 0 &&
2492 normalized_algorithm.length <= 128
2493 },
2494 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2495 normalized_algorithm.iv.len() == 16
2496 },
2497 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2498 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2499 normalized_algorithm.tag_length.is_none_or(|length| {
2500 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2501 })
2502 },
2503 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2504 normalized_algorithm.iv.len() <= 15 &&
2505 normalized_algorithm
2506 .tag_length
2507 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2508 },
2509 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2510 normalized_algorithm.iv.len() == 12 &&
2511 normalized_algorithm
2512 .tag_length
2513 .is_none_or(|length| length == 128)
2514 },
2515 }
2516 },
2517 "decrypt" => {
2518 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2519 else {
2520 return false;
2521 };
2522
2523 match normalized_algorithm {
2524 DecryptAlgorithm::RsaOaep(_) => true,
2525 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2526 normalized_algorithm.counter.len() == 16 &&
2527 normalized_algorithm.length != 0 &&
2528 normalized_algorithm.length <= 128
2529 },
2530 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2531 normalized_algorithm.iv.len() == 16
2532 },
2533 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2534 normalized_algorithm
2535 .tag_length
2536 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2537 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2538 normalized_algorithm
2539 .additional_data
2540 .is_none_or(|data| data.len() <= u32::MAX as usize)
2541 },
2542 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2543 normalized_algorithm.iv.len() <= 15 &&
2544 normalized_algorithm
2545 .tag_length
2546 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2547 },
2548 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2549 normalized_algorithm.iv.len() == 12 &&
2550 normalized_algorithm
2551 .tag_length
2552 .is_none_or(|length| length == 128)
2553 },
2554 }
2555 },
2556 "sign" => {
2557 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2558 else {
2559 return false;
2560 };
2561
2562 match normalized_algorithm {
2563 SignAlgorithm::RsassaPkcs1V1_5(_) |
2564 SignAlgorithm::RsaPss(_) |
2565 SignAlgorithm::Ecdsa(_) |
2566 SignAlgorithm::Ed25519(_) => true,
2567 SignAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2568 .context
2569 .is_none_or(|context| context.len() <= 255),
2570 SignAlgorithm::Hmac(_) | SignAlgorithm::MlDsa(_) | SignAlgorithm::Kmac(_) => true,
2571 }
2572 },
2573 "verify" => {
2574 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2575 else {
2576 return false;
2577 };
2578
2579 match normalized_algorithm {
2580 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2581 VerifyAlgorithm::RsaPss(_) |
2582 VerifyAlgorithm::Ecdsa(_) |
2583 VerifyAlgorithm::Ed25519(_) => true,
2584 VerifyAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2585 .context
2586 .is_none_or(|context| context.len() <= 255),
2587 VerifyAlgorithm::Hmac(_) | VerifyAlgorithm::MlDsa(_) | VerifyAlgorithm::Kmac(_) => {
2588 true
2589 },
2590 }
2591 },
2592 "digest" => {
2593 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2594 else {
2595 return false;
2596 };
2597
2598 match normalized_algorithm {
2599 DigestAlgorithm::Sha(_) |
2600 DigestAlgorithm::Sha3(_) |
2601 DigestAlgorithm::CShake(_) |
2602 DigestAlgorithm::TurboShake(_) => true,
2603 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
2604 normalized_algorithm.output_length != 0 &&
2605 normalized_algorithm.output_length.is_multiple_of(8)
2606 },
2607 }
2608 },
2609 "deriveBits" => {
2610 let Ok(normalized_algorithm) =
2611 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2612 else {
2613 return false;
2614 };
2615
2616 match normalized_algorithm {
2617 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => length.is_none_or(|length| {
2618 ecdh_operation::secret_length(&normalized_algorithm)
2619 .is_ok_and(|secret_length| secret_length * 8 >= length)
2620 }),
2621 DeriveBitsAlgorithm::X25519(_) => {
2622 length.is_none_or(|length| x25519_operation::SECRET_LENGTH as u32 * 8 >= length)
2623 },
2624 DeriveBitsAlgorithm::X448(_) => {
2625 length.is_none_or(|length| x448_operation::SECRET_LENGTH as u32 * 8 >= length)
2626 },
2627 DeriveBitsAlgorithm::Hkdf(_) => length.is_some_and(|length| length % 8 == 0),
2628 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2629 length.is_some_and(|length| length % 8 == 0) &&
2630 normalized_algorithm.iterations != 0
2631 },
2632 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2633 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2634 normalized_algorithm
2635 .version
2636 .is_none_or(|version| version == 19) &&
2637 normalized_algorithm.parallelism != 0 &&
2638 normalized_algorithm.parallelism <= 16777215 &&
2639 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2640 normalized_algorithm.passes != 0
2641 },
2642 }
2643 },
2644 "wrapKey" => {
2645 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2646 else {
2647 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2648 };
2649
2650 match normalized_algorithm {
2651 WrapKeyAlgorithm::AesKw(_) => true,
2652 }
2653 },
2654 "unwrapKey" => {
2655 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2656 else {
2657 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2658 };
2659
2660 match normalized_algorithm {
2661 UnwrapKeyAlgorithm::AesKw(_) => true,
2662 }
2663 },
2664 "generateKey" => {
2665 let Ok(normalized_algorithm) =
2666 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2667 else {
2668 return false;
2669 };
2670
2671 match normalized_algorithm {
2672 GenerateKeyAlgorithm::RsassaPkcs1V1_5(_) |
2673 GenerateKeyAlgorithm::RsaPss(_) |
2674 GenerateKeyAlgorithm::RsaOaep(_) => true,
2675 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2676 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2677 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2678 },
2679 GenerateKeyAlgorithm::Ed25519(_) |
2680 GenerateKeyAlgorithm::X25519(_) |
2681 GenerateKeyAlgorithm::Ed448(_) |
2682 GenerateKeyAlgorithm::X448(_) => true,
2683 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2684 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2685 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2686 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2687 matches!(normalized_algorithm.length, 128 | 192 | 256)
2688 },
2689 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2690 normalized_algorithm.length.is_none_or(|length| length != 0)
2691 },
2692 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2693 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2694 matches!(normalized_algorithm.length, 128 | 192 | 256)
2695 },
2696 GenerateKeyAlgorithm::ChaCha20Poly1305(_) | GenerateKeyAlgorithm::Kmac(_) => true,
2697 }
2698 },
2699 "importKey" => {
2700 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2701 else {
2702 return false;
2703 };
2704
2705 match normalized_algorithm {
2706 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2707 ImportKeyAlgorithm::RsaPss(_) |
2708 ImportKeyAlgorithm::RsaOaep(_) |
2709 ImportKeyAlgorithm::Ecdsa(_) |
2710 ImportKeyAlgorithm::Ecdh(_) |
2711 ImportKeyAlgorithm::Ed25519(_) |
2712 ImportKeyAlgorithm::X25519(_) |
2713 ImportKeyAlgorithm::Ed448(_) |
2714 ImportKeyAlgorithm::X448(_) |
2715 ImportKeyAlgorithm::AesCtr(_) |
2716 ImportKeyAlgorithm::AesCbc(_) |
2717 ImportKeyAlgorithm::AesGcm(_) |
2718 ImportKeyAlgorithm::AesKw(_) |
2719 ImportKeyAlgorithm::Hmac(_) |
2720 ImportKeyAlgorithm::Hkdf(_) |
2721 ImportKeyAlgorithm::Pbkdf2(_) |
2722 ImportKeyAlgorithm::MlKem(_) |
2723 ImportKeyAlgorithm::MlDsa(_) |
2724 ImportKeyAlgorithm::AesOcb(_) |
2725 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2726 ImportKeyAlgorithm::Kmac(_) |
2727 ImportKeyAlgorithm::Argon2(_) => true,
2728 }
2729 },
2730 "exportKey" => {
2731 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2732 else {
2733 return false;
2734 };
2735
2736 match normalized_algorithm {
2737 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2738 ExportKeyAlgorithm::RsaPss(_) |
2739 ExportKeyAlgorithm::RsaOaep(_) |
2740 ExportKeyAlgorithm::Ecdsa(_) |
2741 ExportKeyAlgorithm::Ecdh(_) |
2742 ExportKeyAlgorithm::Ed25519(_) |
2743 ExportKeyAlgorithm::X25519(_) |
2744 ExportKeyAlgorithm::Ed448(_) |
2745 ExportKeyAlgorithm::X448(_) |
2746 ExportKeyAlgorithm::AesCtr(_) |
2747 ExportKeyAlgorithm::AesCbc(_) |
2748 ExportKeyAlgorithm::AesGcm(_) |
2749 ExportKeyAlgorithm::AesKw(_) |
2750 ExportKeyAlgorithm::Hmac(_) |
2751 ExportKeyAlgorithm::MlKem(_) |
2752 ExportKeyAlgorithm::MlDsa(_) |
2753 ExportKeyAlgorithm::AesOcb(_) |
2754 ExportKeyAlgorithm::ChaCha20Poly1305(_) |
2755 ExportKeyAlgorithm::Kmac(_) => true,
2756 }
2757 },
2758 "get key length" => {
2759 let Ok(normalized_algorithm) =
2760 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2761 else {
2762 return false;
2763 };
2764
2765 match normalized_algorithm {
2766 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2767 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2768 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2769 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2770 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2771 },
2772 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2773 normalized_derived_key_algorithm
2774 .length
2775 .is_none_or(|length| length != 0)
2776 },
2777 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2778 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2779 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2780 },
2781 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) |
2782 GetKeyLengthAlgorithm::Kmac(_) |
2783 GetKeyLengthAlgorithm::Argon2(_) => true,
2784 }
2785 },
2786 "encapsulate" => {
2787 let Ok(normalized_algorithm) =
2788 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2789 else {
2790 return false;
2791 };
2792
2793 match normalized_algorithm {
2794 EncapsulateAlgorithm::MlKem(_) => true,
2795 }
2796 },
2797 "decapsulate" => {
2798 let Ok(normalized_algorithm) =
2799 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2800 else {
2801 return false;
2802 };
2803
2804 match normalized_algorithm {
2805 DecapsulateAlgorithm::MlKem(_) => true,
2806 }
2807 },
2808 _ => false,
2809 }
2810
2811 }
2815
2816trait TryFromWithCxAndName<T>: Sized {
2818 type Error;
2819
2820 fn try_from_with_cx_and_name(
2821 value: T,
2822 cx: &mut js::context::JSContext,
2823 algorithm_name: CryptoAlgorithm,
2824 ) -> Result<Self, Self::Error>;
2825}
2826
2827trait TryIntoWithCxAndName<T>: Sized {
2829 type Error;
2830
2831 fn try_into_with_cx_and_name(
2832 self,
2833 cx: &mut js::context::JSContext,
2834 algorithm_name: CryptoAlgorithm,
2835 ) -> Result<T, Self::Error>;
2836}
2837
2838impl<T, U> TryIntoWithCxAndName<U> for T
2839where
2840 U: TryFromWithCxAndName<T>,
2841{
2842 type Error = U::Error;
2843
2844 fn try_into_with_cx_and_name(
2845 self,
2846 cx: &mut js::context::JSContext,
2847 algorithm_name: CryptoAlgorithm,
2848 ) -> Result<U, Self::Error> {
2849 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2850 }
2851}
2852
2853#[derive(Clone, MallocSizeOf)]
2858struct SubtleAlgorithm {
2859 name: CryptoAlgorithm,
2861}
2862
2863impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAlgorithm {
2864 type Error = Error;
2865
2866 fn try_from_with_cx_and_name(
2867 _object: HandleObject<'a>,
2868 _cx: &mut js::context::JSContext,
2869 algorithm_name: CryptoAlgorithm,
2870 ) -> Result<Self, Self::Error> {
2871 Ok(SubtleAlgorithm {
2872 name: algorithm_name,
2873 })
2874 }
2875}
2876
2877impl TryFrom<SerializableAlgorithm> for SubtleAlgorithm {
2878 type Error = ();
2879
2880 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2881 Ok(SubtleAlgorithm {
2882 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2883 })
2884 }
2885}
2886
2887impl From<&SubtleAlgorithm> for SerializableAlgorithm {
2888 fn from(value: &SubtleAlgorithm) -> Self {
2889 SerializableAlgorithm {
2890 name: value.name.as_str().into(),
2891 }
2892 }
2893}
2894
2895#[derive(Clone, MallocSizeOf)]
2897pub(crate) struct SubtleKeyAlgorithm {
2898 name: CryptoAlgorithm,
2900}
2901
2902impl SafeToJSValConvertible for SubtleKeyAlgorithm {
2903 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
2904 let dictionary = KeyAlgorithm {
2905 name: self.name.as_str().into(),
2906 };
2907 dictionary.safe_to_jsval(cx, rval);
2908 }
2909}
2910
2911impl TryFrom<SerializableKeyAlgorithm> for SubtleKeyAlgorithm {
2912 type Error = ();
2913
2914 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2915 Ok(SubtleKeyAlgorithm {
2916 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2917 })
2918 }
2919}
2920
2921impl From<&SubtleKeyAlgorithm> for SerializableKeyAlgorithm {
2922 fn from(value: &SubtleKeyAlgorithm) -> Self {
2923 SerializableKeyAlgorithm {
2924 name: value.name.as_str().into(),
2925 }
2926 }
2927}
2928
2929#[derive(Clone, MallocSizeOf)]
2931pub(crate) struct SubtleRsaHashedKeyGenParams {
2932 name: CryptoAlgorithm,
2934
2935 modulus_length: u32,
2937
2938 public_exponent: Vec<u8>,
2940
2941 hash: DigestAlgorithm,
2943}
2944
2945impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedKeyGenParams {
2946 type Error = Error;
2947
2948 fn try_from_with_cx_and_name(
2949 object: HandleObject,
2950 cx: &mut js::context::JSContext,
2951 algorithm_name: CryptoAlgorithm,
2952 ) -> Result<Self, Self::Error> {
2953 let hash = get_required_parameter(cx, object, c"hash", ())?;
2954
2955 Ok(SubtleRsaHashedKeyGenParams {
2956 name: algorithm_name,
2957 modulus_length: get_required_parameter(
2958 cx,
2959 object,
2960 c"modulusLength",
2961 ConversionBehavior::Default,
2962 )?,
2963 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2964 cx,
2965 object,
2966 c"publicExponent",
2967 (),
2968 )?
2969 .to_vec()
2970 .unwrap_or_default(),
2971 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2972 })
2973 }
2974}
2975
2976#[derive(Clone, MallocSizeOf)]
2978pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2979 name: CryptoAlgorithm,
2981
2982 modulus_length: u32,
2984
2985 public_exponent: Vec<u8>,
2987
2988 hash: DigestAlgorithm,
2990}
2991
2992impl SafeToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2993 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
2994 rooted!(&in(cx) let mut js_object = ptr::null_mut::<JSObject>());
2995 let public_exponent =
2996 create_buffer_source(cx, &self.public_exponent, js_object.handle_mut())
2997 .expect("Fail to convert publicExponent to Uint8Array");
2998 let key_algorithm = KeyAlgorithm {
2999 name: self.name.as_str().into(),
3000 };
3001 let rsa_key_algorithm = RootedTraceableBox::new(RsaKeyAlgorithm {
3002 parent: key_algorithm,
3003 modulusLength: self.modulus_length,
3004 publicExponent: public_exponent,
3005 });
3006 let rsa_hashed_key_algorithm = RootedTraceableBox::new(RsaHashedKeyAlgorithm {
3007 parent: rsa_key_algorithm,
3008 hash: KeyAlgorithm {
3009 name: self.hash.name().as_str().into(),
3010 },
3011 });
3012 rsa_hashed_key_algorithm.safe_to_jsval(cx, rval);
3013 }
3014}
3015
3016impl TryFrom<SerializableRsaHashedKeyAlgorithm> for SubtleRsaHashedKeyAlgorithm {
3017 type Error = ();
3018
3019 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
3020 Ok(SubtleRsaHashedKeyAlgorithm {
3021 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3022 modulus_length: value.modulus_length,
3023 public_exponent: value.public_exponent,
3024 hash: value.hash.try_into()?,
3025 })
3026 }
3027}
3028
3029impl From<&SubtleRsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
3030 fn from(value: &SubtleRsaHashedKeyAlgorithm) -> Self {
3031 SerializableRsaHashedKeyAlgorithm {
3032 name: value.name.as_str().into(),
3033 modulus_length: value.modulus_length,
3034 public_exponent: value.public_exponent.clone(),
3035 hash: (&value.hash).into(),
3036 }
3037 }
3038}
3039
3040#[derive(Clone, MallocSizeOf)]
3042struct SubtleRsaHashedImportParams {
3043 name: CryptoAlgorithm,
3045
3046 hash: DigestAlgorithm,
3048}
3049
3050impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedImportParams {
3051 type Error = Error;
3052
3053 fn try_from_with_cx_and_name(
3054 object: HandleObject,
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(SubtleRsaHashedImportParams {
3061 name: algorithm_name,
3062 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3063 })
3064 }
3065}
3066
3067#[derive(Clone, MallocSizeOf)]
3069struct SubtleRsaPssParams {
3070 name: CryptoAlgorithm,
3072
3073 salt_length: u32,
3075}
3076
3077impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaPssParams {
3078 type Error = Error;
3079
3080 fn try_from_with_cx_and_name(
3081 object: HandleObject,
3082 cx: &mut js::context::JSContext,
3083 algorithm_name: CryptoAlgorithm,
3084 ) -> Result<Self, Self::Error> {
3085 Ok(SubtleRsaPssParams {
3086 name: algorithm_name,
3087 salt_length: get_required_parameter(
3088 cx,
3089 object,
3090 c"saltLength",
3091 ConversionBehavior::EnforceRange,
3092 )?,
3093 })
3094 }
3095}
3096
3097#[derive(Clone, MallocSizeOf)]
3099struct SubtleRsaOaepParams {
3100 name: CryptoAlgorithm,
3102
3103 label: Option<Vec<u8>>,
3105}
3106
3107impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaOaepParams {
3108 type Error = Error;
3109
3110 fn try_from_with_cx_and_name(
3111 object: HandleObject<'a>,
3112 cx: &mut js::context::JSContext,
3113 algorithm_name: CryptoAlgorithm,
3114 ) -> Result<Self, Self::Error> {
3115 Ok(SubtleRsaOaepParams {
3116 name: algorithm_name,
3117 label: get_optional_buffer_source(cx, object, c"label")?,
3118 })
3119 }
3120}
3121
3122#[derive(Clone, MallocSizeOf)]
3124struct SubtleEcdsaParams {
3125 name: CryptoAlgorithm,
3127
3128 hash: DigestAlgorithm,
3130}
3131
3132impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdsaParams {
3133 type Error = Error;
3134
3135 fn try_from_with_cx_and_name(
3136 object: HandleObject<'a>,
3137 cx: &mut js::context::JSContext,
3138 algorithm_name: CryptoAlgorithm,
3139 ) -> Result<Self, Self::Error> {
3140 let hash = get_required_parameter(cx, object, c"hash", ())?;
3141
3142 Ok(SubtleEcdsaParams {
3143 name: algorithm_name,
3144 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3145 })
3146 }
3147}
3148
3149#[derive(Clone, MallocSizeOf)]
3151struct SubtleEcKeyGenParams {
3152 name: CryptoAlgorithm,
3154
3155 named_curve: String,
3157}
3158
3159impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyGenParams {
3160 type Error = Error;
3161
3162 fn try_from_with_cx_and_name(
3163 object: HandleObject<'a>,
3164 cx: &mut js::context::JSContext,
3165 algorithm_name: CryptoAlgorithm,
3166 ) -> Result<Self, Self::Error> {
3167 Ok(SubtleEcKeyGenParams {
3168 name: algorithm_name,
3169 named_curve: String::from(get_required_parameter::<DOMString>(
3170 cx,
3171 object,
3172 c"namedCurve",
3173 StringificationBehavior::Default,
3174 )?),
3175 })
3176 }
3177}
3178
3179#[derive(Clone, MallocSizeOf)]
3181pub(crate) struct SubtleEcKeyAlgorithm {
3182 name: CryptoAlgorithm,
3184
3185 named_curve: String,
3187}
3188
3189impl SafeToJSValConvertible for SubtleEcKeyAlgorithm {
3190 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3191 let parent = KeyAlgorithm {
3192 name: self.name.as_str().into(),
3193 };
3194 let dictionary = EcKeyAlgorithm {
3195 parent,
3196 namedCurve: self.named_curve.clone().into(),
3197 };
3198 dictionary.safe_to_jsval(cx, rval);
3199 }
3200}
3201
3202impl TryFrom<SerializableEcKeyAlgorithm> for SubtleEcKeyAlgorithm {
3203 type Error = ();
3204
3205 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3206 Ok(SubtleEcKeyAlgorithm {
3207 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3208 named_curve: value.named_curve,
3209 })
3210 }
3211}
3212
3213impl From<&SubtleEcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3214 fn from(value: &SubtleEcKeyAlgorithm) -> Self {
3215 SerializableEcKeyAlgorithm {
3216 name: value.name.as_str().into(),
3217 named_curve: value.named_curve.clone(),
3218 }
3219 }
3220}
3221
3222#[derive(Clone, MallocSizeOf)]
3224struct SubtleEcKeyImportParams {
3225 name: CryptoAlgorithm,
3227
3228 named_curve: String,
3230}
3231
3232impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyImportParams {
3233 type Error = Error;
3234
3235 fn try_from_with_cx_and_name(
3236 object: HandleObject<'a>,
3237 cx: &mut js::context::JSContext,
3238 algorithm_name: CryptoAlgorithm,
3239 ) -> Result<Self, Self::Error> {
3240 Ok(SubtleEcKeyImportParams {
3241 name: algorithm_name,
3242 named_curve: String::from(get_required_parameter::<DOMString>(
3243 cx,
3244 object,
3245 c"namedCurve",
3246 StringificationBehavior::Default,
3247 )?),
3248 })
3249 }
3250}
3251
3252#[derive(Clone, MallocSizeOf)]
3254struct SubtleEcdhKeyDeriveParams {
3255 name: CryptoAlgorithm,
3257
3258 public: Trusted<CryptoKey>,
3260}
3261
3262impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdhKeyDeriveParams {
3263 type Error = Error;
3264
3265 fn try_from_with_cx_and_name(
3266 object: HandleObject<'a>,
3267 cx: &mut js::context::JSContext,
3268 algorithm_name: CryptoAlgorithm,
3269 ) -> Result<Self, Self::Error> {
3270 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3271
3272 Ok(SubtleEcdhKeyDeriveParams {
3273 name: algorithm_name,
3274 public: Trusted::new(&public),
3275 })
3276 }
3277}
3278
3279#[derive(Clone, MallocSizeOf)]
3281struct SubtleAesCtrParams {
3282 name: CryptoAlgorithm,
3284
3285 counter: Vec<u8>,
3287
3288 length: u8,
3290}
3291
3292impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCtrParams {
3293 type Error = Error;
3294
3295 fn try_from_with_cx_and_name(
3296 object: HandleObject<'a>,
3297 cx: &mut js::context::JSContext,
3298 algorithm_name: CryptoAlgorithm,
3299 ) -> Result<Self, Self::Error> {
3300 Ok(SubtleAesCtrParams {
3301 name: algorithm_name,
3302 counter: get_required_buffer_source(cx, object, c"counter")?,
3303 length: get_required_parameter(
3304 cx,
3305 object,
3306 c"length",
3307 ConversionBehavior::EnforceRange,
3308 )?,
3309 })
3310 }
3311}
3312
3313#[derive(Clone, MallocSizeOf)]
3315pub(crate) struct SubtleAesKeyAlgorithm {
3316 name: CryptoAlgorithm,
3318
3319 length: u16,
3321}
3322
3323impl SafeToJSValConvertible for SubtleAesKeyAlgorithm {
3324 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3325 let parent = KeyAlgorithm {
3326 name: self.name.as_str().into(),
3327 };
3328 let dictionary = AesKeyAlgorithm {
3329 parent,
3330 length: self.length,
3331 };
3332 dictionary.safe_to_jsval(cx, rval);
3333 }
3334}
3335
3336impl TryFrom<SerializableAesKeyAlgorithm> for SubtleAesKeyAlgorithm {
3337 type Error = ();
3338
3339 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3340 Ok(SubtleAesKeyAlgorithm {
3341 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3342 length: value.length,
3343 })
3344 }
3345}
3346
3347impl From<&SubtleAesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3348 fn from(value: &SubtleAesKeyAlgorithm) -> Self {
3349 SerializableAesKeyAlgorithm {
3350 name: value.name.as_str().into(),
3351 length: value.length,
3352 }
3353 }
3354}
3355
3356#[derive(Clone, MallocSizeOf)]
3358struct SubtleAesKeyGenParams {
3359 name: CryptoAlgorithm,
3361
3362 length: u16,
3364}
3365
3366impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesKeyGenParams {
3367 type Error = Error;
3368
3369 fn try_from_with_cx_and_name(
3370 object: HandleObject<'a>,
3371 cx: &mut js::context::JSContext,
3372 algorithm_name: CryptoAlgorithm,
3373 ) -> Result<Self, Self::Error> {
3374 Ok(SubtleAesKeyGenParams {
3375 name: algorithm_name,
3376 length: get_required_parameter(
3377 cx,
3378 object,
3379 c"length",
3380 ConversionBehavior::EnforceRange,
3381 )?,
3382 })
3383 }
3384}
3385
3386#[derive(Clone, MallocSizeOf)]
3388struct SubtleAesDerivedKeyParams {
3389 name: CryptoAlgorithm,
3391
3392 length: u16,
3394}
3395
3396impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesDerivedKeyParams {
3397 type Error = Error;
3398
3399 fn try_from_with_cx_and_name(
3400 object: HandleObject<'a>,
3401 cx: &mut js::context::JSContext,
3402 algorithm_name: CryptoAlgorithm,
3403 ) -> Result<Self, Self::Error> {
3404 Ok(SubtleAesDerivedKeyParams {
3405 name: algorithm_name,
3406 length: get_required_parameter(
3407 cx,
3408 object,
3409 c"length",
3410 ConversionBehavior::EnforceRange,
3411 )?,
3412 })
3413 }
3414}
3415
3416#[derive(Clone, MallocSizeOf)]
3418struct SubtleAesCbcParams {
3419 name: CryptoAlgorithm,
3421
3422 iv: Vec<u8>,
3424}
3425
3426impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCbcParams {
3427 type Error = Error;
3428
3429 fn try_from_with_cx_and_name(
3430 object: HandleObject<'a>,
3431 cx: &mut js::context::JSContext,
3432 algorithm_name: CryptoAlgorithm,
3433 ) -> Result<Self, Self::Error> {
3434 Ok(SubtleAesCbcParams {
3435 name: algorithm_name,
3436 iv: get_required_buffer_source(cx, object, c"iv")?,
3437 })
3438 }
3439}
3440
3441#[derive(Clone, MallocSizeOf)]
3443struct SubtleAesGcmParams {
3444 name: CryptoAlgorithm,
3446
3447 iv: Vec<u8>,
3449
3450 additional_data: Option<Vec<u8>>,
3452
3453 tag_length: Option<u8>,
3455}
3456
3457impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesGcmParams {
3458 type Error = Error;
3459
3460 fn try_from_with_cx_and_name(
3461 object: HandleObject<'a>,
3462 cx: &mut js::context::JSContext,
3463 algorithm_name: CryptoAlgorithm,
3464 ) -> Result<Self, Self::Error> {
3465 Ok(SubtleAesGcmParams {
3466 name: algorithm_name,
3467 iv: get_required_buffer_source(cx, object, c"iv")?,
3468 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3469 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3470 })
3471 }
3472}
3473
3474#[derive(Clone, MallocSizeOf)]
3476struct SubtleHmacImportParams {
3477 name: CryptoAlgorithm,
3479
3480 hash: DigestAlgorithm,
3482
3483 length: Option<u32>,
3485}
3486
3487impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacImportParams {
3488 type Error = Error;
3489
3490 fn try_from_with_cx_and_name(
3491 object: HandleObject<'a>,
3492 cx: &mut js::context::JSContext,
3493 algorithm_name: CryptoAlgorithm,
3494 ) -> Result<Self, Self::Error> {
3495 let hash = get_required_parameter(cx, object, c"hash", ())?;
3496
3497 Ok(SubtleHmacImportParams {
3498 name: algorithm_name,
3499 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3500 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3501 })
3502 }
3503}
3504
3505#[derive(Clone, MallocSizeOf)]
3507pub(crate) struct SubtleHmacKeyAlgorithm {
3508 name: CryptoAlgorithm,
3510
3511 hash: DigestAlgorithm,
3513
3514 length: u32,
3516}
3517
3518impl SafeToJSValConvertible for SubtleHmacKeyAlgorithm {
3519 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3520 let parent = KeyAlgorithm {
3521 name: self.name.as_str().into(),
3522 };
3523 let hash = KeyAlgorithm {
3524 name: self.hash.name().as_str().into(),
3525 };
3526 let dictionary = HmacKeyAlgorithm {
3527 parent,
3528 hash,
3529 length: self.length,
3530 };
3531 dictionary.safe_to_jsval(cx, rval);
3532 }
3533}
3534
3535impl TryFrom<SerializableHmacKeyAlgorithm> for SubtleHmacKeyAlgorithm {
3536 type Error = ();
3537
3538 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3539 Ok(SubtleHmacKeyAlgorithm {
3540 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3541 hash: value.hash.try_into()?,
3542 length: value.length,
3543 })
3544 }
3545}
3546
3547impl From<&SubtleHmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3548 fn from(value: &SubtleHmacKeyAlgorithm) -> Self {
3549 SerializableHmacKeyAlgorithm {
3550 name: value.name.as_str().into(),
3551 hash: (&value.hash).into(),
3552 length: value.length,
3553 }
3554 }
3555}
3556
3557#[derive(Clone, MallocSizeOf)]
3559struct SubtleHmacKeyGenParams {
3560 name: CryptoAlgorithm,
3562
3563 hash: DigestAlgorithm,
3565
3566 length: Option<u32>,
3568}
3569
3570impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacKeyGenParams {
3571 type Error = Error;
3572
3573 fn try_from_with_cx_and_name(
3574 object: HandleObject<'a>,
3575 cx: &mut js::context::JSContext,
3576 algorithm_name: CryptoAlgorithm,
3577 ) -> Result<Self, Self::Error> {
3578 let hash = get_required_parameter(cx, object, c"hash", ())?;
3579
3580 Ok(SubtleHmacKeyGenParams {
3581 name: algorithm_name,
3582 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3583 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3584 })
3585 }
3586}
3587
3588#[derive(Clone, MallocSizeOf)]
3590pub(crate) struct SubtleHkdfParams {
3591 name: CryptoAlgorithm,
3593
3594 hash: DigestAlgorithm,
3596
3597 salt: Vec<u8>,
3599
3600 info: Vec<u8>,
3602}
3603
3604impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHkdfParams {
3605 type Error = Error;
3606
3607 fn try_from_with_cx_and_name(
3608 object: HandleObject<'a>,
3609 cx: &mut js::context::JSContext,
3610 algorithm_name: CryptoAlgorithm,
3611 ) -> Result<Self, Self::Error> {
3612 let hash = get_required_parameter(cx, object, c"hash", ())?;
3613
3614 Ok(SubtleHkdfParams {
3615 name: algorithm_name,
3616 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3617 salt: get_required_buffer_source(cx, object, c"salt")?,
3618 info: get_required_buffer_source(cx, object, c"info")?,
3619 })
3620 }
3621}
3622
3623#[derive(Clone, MallocSizeOf)]
3625pub(crate) struct SubtlePbkdf2Params {
3626 name: CryptoAlgorithm,
3628
3629 salt: Vec<u8>,
3631
3632 iterations: u32,
3634
3635 hash: DigestAlgorithm,
3637}
3638
3639impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtlePbkdf2Params {
3640 type Error = Error;
3641
3642 fn try_from_with_cx_and_name(
3643 object: HandleObject<'a>,
3644 cx: &mut js::context::JSContext,
3645 algorithm_name: CryptoAlgorithm,
3646 ) -> Result<Self, Self::Error> {
3647 let hash = get_required_parameter(cx, object, c"hash", ())?;
3648
3649 Ok(SubtlePbkdf2Params {
3650 name: algorithm_name,
3651 salt: get_required_buffer_source(cx, object, c"salt")?,
3652 iterations: get_required_parameter(
3653 cx,
3654 object,
3655 c"iterations",
3656 ConversionBehavior::EnforceRange,
3657 )?,
3658 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3659 })
3660 }
3661}
3662
3663#[derive(Clone, MallocSizeOf)]
3665struct SubtleContextParams {
3666 name: CryptoAlgorithm,
3668
3669 context: Option<Vec<u8>>,
3671}
3672
3673impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleContextParams {
3674 type Error = Error;
3675
3676 fn try_from_with_cx_and_name(
3677 object: HandleObject<'a>,
3678 cx: &mut js::context::JSContext,
3679 algorithm_name: CryptoAlgorithm,
3680 ) -> Result<Self, Self::Error> {
3681 Ok(SubtleContextParams {
3682 name: algorithm_name,
3683 context: get_optional_buffer_source(cx, object, c"context")?,
3684 })
3685 }
3686}
3687
3688#[derive(Clone, MallocSizeOf)]
3690struct SubtleAeadParams {
3691 name: CryptoAlgorithm,
3693
3694 iv: Vec<u8>,
3696
3697 additional_data: Option<Vec<u8>>,
3699
3700 tag_length: Option<u8>,
3702}
3703
3704impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAeadParams {
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(SubtleAeadParams {
3713 name: algorithm_name,
3714 iv: get_required_buffer_source(cx, object, c"iv")?,
3715 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3716 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3717 })
3718 }
3719}
3720
3721#[derive(Clone, MallocSizeOf)]
3723struct SubtleCShakeParams {
3724 name: CryptoAlgorithm,
3726
3727 output_length: u32,
3729
3730 function_name: Option<Vec<u8>>,
3732
3733 customization: Option<Vec<u8>>,
3735}
3736
3737impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleCShakeParams {
3738 type Error = Error;
3739
3740 fn try_from_with_cx_and_name(
3741 object: HandleObject<'a>,
3742 cx: &mut js::context::JSContext,
3743 algorithm_name: CryptoAlgorithm,
3744 ) -> Result<Self, Self::Error> {
3745 Ok(SubtleCShakeParams {
3746 name: algorithm_name,
3747 output_length: get_required_parameter(
3748 cx,
3749 object,
3750 c"outputLength",
3751 ConversionBehavior::EnforceRange,
3752 )?,
3753 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3754 customization: get_optional_buffer_source(cx, object, c"customization")?,
3755 })
3756 }
3757}
3758
3759impl TryFrom<SerializableCShakeParams> for SubtleCShakeParams {
3760 type Error = ();
3761
3762 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3763 Ok(SubtleCShakeParams {
3764 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3765 output_length: value.output_length,
3766 function_name: value.function_name,
3767 customization: value.customization,
3768 })
3769 }
3770}
3771
3772impl From<&SubtleCShakeParams> for SerializableCShakeParams {
3773 fn from(value: &SubtleCShakeParams) -> Self {
3774 SerializableCShakeParams {
3775 name: value.name.as_str().into(),
3776 output_length: value.output_length,
3777 function_name: value.function_name.clone(),
3778 customization: value.customization.clone(),
3779 }
3780 }
3781}
3782
3783#[derive(Clone, MallocSizeOf)]
3785struct SubtleTurboShakeParams {
3786 name: CryptoAlgorithm,
3788
3789 output_length: u32,
3791
3792 domain_separation: Option<u8>,
3794}
3795
3796impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleTurboShakeParams {
3797 type Error = Error;
3798
3799 fn try_from_with_cx_and_name(
3800 object: HandleObject<'a>,
3801 cx: &mut js::context::JSContext,
3802 algorithm_name: CryptoAlgorithm,
3803 ) -> Result<Self, Self::Error> {
3804 Ok(SubtleTurboShakeParams {
3805 name: algorithm_name,
3806 output_length: get_required_parameter(
3807 cx,
3808 object,
3809 c"outputLength",
3810 ConversionBehavior::EnforceRange,
3811 )?,
3812 domain_separation: get_property(
3813 cx,
3814 object,
3815 c"domainSeparation",
3816 ConversionBehavior::EnforceRange,
3817 )?,
3818 })
3819 }
3820}
3821
3822impl TryFrom<SerializableTurboShakeParams> for SubtleTurboShakeParams {
3823 type Error = ();
3824
3825 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3826 Ok(SubtleTurboShakeParams {
3827 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3828 output_length: value.output_length,
3829 domain_separation: value.domain_separation,
3830 })
3831 }
3832}
3833
3834impl From<&SubtleTurboShakeParams> for SerializableTurboShakeParams {
3835 fn from(value: &SubtleTurboShakeParams) -> Self {
3836 SerializableTurboShakeParams {
3837 name: value.name.as_str().into(),
3838 output_length: value.output_length,
3839 domain_separation: value.domain_separation,
3840 }
3841 }
3842}
3843
3844#[derive(Clone, MallocSizeOf)]
3846struct SubtleKangarooTwelveParams {
3847 name: CryptoAlgorithm,
3849
3850 output_length: u32,
3852
3853 customization: Option<Vec<u8>>,
3855}
3856
3857impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKangarooTwelveParams {
3858 type Error = Error;
3859
3860 fn try_from_with_cx_and_name(
3861 object: HandleObject<'a>,
3862 cx: &mut js::context::JSContext,
3863 algorithm_name: CryptoAlgorithm,
3864 ) -> Result<Self, Self::Error> {
3865 Ok(SubtleKangarooTwelveParams {
3866 name: algorithm_name,
3867 output_length: get_required_parameter(
3868 cx,
3869 object,
3870 c"outputLength",
3871 ConversionBehavior::EnforceRange,
3872 )?,
3873 customization: get_optional_buffer_source(cx, object, c"customization")?,
3874 })
3875 }
3876}
3877
3878impl TryFrom<SerializableKangarooTwelveParams> for SubtleKangarooTwelveParams {
3879 type Error = ();
3880
3881 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
3882 Ok(SubtleKangarooTwelveParams {
3883 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3884 output_length: value.output_length,
3885 customization: value.customization,
3886 })
3887 }
3888}
3889
3890impl From<&SubtleKangarooTwelveParams> for SerializableKangarooTwelveParams {
3891 fn from(value: &SubtleKangarooTwelveParams) -> Self {
3892 SerializableKangarooTwelveParams {
3893 name: value.name.as_str().into(),
3894 output_length: value.output_length,
3895 customization: value.customization.clone(),
3896 }
3897 }
3898}
3899
3900#[derive(Clone, MallocSizeOf)]
3902struct SubtleKmacKeyGenParams {
3903 name: CryptoAlgorithm,
3905
3906 length: Option<u32>,
3908}
3909
3910impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacKeyGenParams {
3911 type Error = Error;
3912
3913 fn try_from_with_cx_and_name(
3914 object: HandleObject,
3915 cx: &mut js::context::JSContext,
3916 algorithm_name: CryptoAlgorithm,
3917 ) -> Result<Self, Self::Error> {
3918 Ok(SubtleKmacKeyGenParams {
3919 name: algorithm_name,
3920 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3921 })
3922 }
3923}
3924
3925#[derive(Clone, MallocSizeOf)]
3927struct SubtleKmacImportParams {
3928 name: CryptoAlgorithm,
3930
3931 length: Option<u32>,
3933}
3934
3935impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacImportParams {
3936 type Error = Error;
3937
3938 fn try_from_with_cx_and_name(
3939 object: HandleObject,
3940 cx: &mut js::context::JSContext,
3941 algorithm_name: CryptoAlgorithm,
3942 ) -> Result<Self, Self::Error> {
3943 Ok(SubtleKmacImportParams {
3944 name: algorithm_name,
3945 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3946 })
3947 }
3948}
3949
3950#[derive(Clone, MallocSizeOf)]
3952pub(crate) struct SubtleKmacKeyAlgorithm {
3953 name: CryptoAlgorithm,
3955
3956 length: u32,
3958}
3959
3960impl SafeToJSValConvertible for SubtleKmacKeyAlgorithm {
3961 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
3962 let parent = KeyAlgorithm {
3963 name: self.name.as_str().into(),
3964 };
3965 let dictionary = KmacKeyAlgorithm {
3966 parent,
3967 length: self.length,
3968 };
3969 dictionary.safe_to_jsval(cx, rval);
3970 }
3971}
3972
3973impl TryFrom<SerializableKmacKeyAlgorithm> for SubtleKmacKeyAlgorithm {
3974 type Error = ();
3975
3976 fn try_from(value: SerializableKmacKeyAlgorithm) -> Result<Self, Self::Error> {
3977 Ok(SubtleKmacKeyAlgorithm {
3978 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3979 length: value.length,
3980 })
3981 }
3982}
3983
3984impl From<&SubtleKmacKeyAlgorithm> for SerializableKmacKeyAlgorithm {
3985 fn from(value: &SubtleKmacKeyAlgorithm) -> Self {
3986 SerializableKmacKeyAlgorithm {
3987 name: value.name.as_str().into(),
3988 length: value.length,
3989 }
3990 }
3991}
3992
3993struct SubtleKmacParams {
3995 name: CryptoAlgorithm,
3997
3998 output_length: u32,
4000
4001 customization: Option<Vec<u8>>,
4003}
4004
4005impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacParams {
4006 type Error = Error;
4007
4008 fn try_from_with_cx_and_name(
4009 object: HandleObject<'a>,
4010 cx: &mut js::context::JSContext,
4011 algorithm_name: CryptoAlgorithm,
4012 ) -> Result<Self, Self::Error> {
4013 Ok(SubtleKmacParams {
4014 name: algorithm_name,
4015 output_length: get_required_parameter(
4016 cx,
4017 object,
4018 c"outputLength",
4019 ConversionBehavior::EnforceRange,
4020 )?,
4021 customization: get_optional_buffer_source(cx, object, c"customization")?,
4022 })
4023 }
4024}
4025
4026#[derive(Clone, MallocSizeOf)]
4028struct SubtleArgon2Params {
4029 name: CryptoAlgorithm,
4031
4032 nonce: Vec<u8>,
4034
4035 parallelism: u32,
4037
4038 memory: u32,
4040
4041 passes: u32,
4043
4044 version: Option<u8>,
4046
4047 secret_value: Option<Vec<u8>>,
4049
4050 associated_data: Option<Vec<u8>>,
4052}
4053
4054impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleArgon2Params {
4055 type Error = Error;
4056
4057 fn try_from_with_cx_and_name(
4058 object: HandleObject<'a>,
4059 cx: &mut js::context::JSContext,
4060 algorithm_name: CryptoAlgorithm,
4061 ) -> Result<Self, Self::Error> {
4062 Ok(SubtleArgon2Params {
4063 name: algorithm_name,
4064 nonce: get_required_buffer_source(cx, object, c"nonce")?,
4065 parallelism: get_required_parameter(
4066 cx,
4067 object,
4068 c"parallelism",
4069 ConversionBehavior::EnforceRange,
4070 )?,
4071 memory: get_required_parameter(
4072 cx,
4073 object,
4074 c"memory",
4075 ConversionBehavior::EnforceRange,
4076 )?,
4077 passes: get_required_parameter(
4078 cx,
4079 object,
4080 c"passes",
4081 ConversionBehavior::EnforceRange,
4082 )?,
4083 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
4084 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
4085 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
4086 })
4087 }
4088}
4089
4090struct SubtleEncapsulatedKey {
4092 shared_key: Option<Trusted<CryptoKey>>,
4094
4095 ciphertext: Option<Vec<u8>>,
4097}
4098
4099impl SafeToJSValConvertible for SubtleEncapsulatedKey {
4100 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4101 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
4102 let ciphertext = self.ciphertext.as_ref().map(|data| {
4103 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
4104 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
4105 .expect("Failed to convert ciphertext to ArrayBufferU8")
4106 });
4107 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
4108 sharedKey: shared_key,
4109 ciphertext,
4110 });
4111 encapsulated_key.safe_to_jsval(cx, rval);
4112 }
4113}
4114
4115struct SubtleEncapsulatedBits {
4117 shared_key: Option<Zeroizing<Vec<u8>>>,
4119
4120 ciphertext: Option<Vec<u8>>,
4122}
4123
4124impl SafeToJSValConvertible for SubtleEncapsulatedBits {
4125 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4126 let shared_key = self.shared_key.as_ref().map(|data| {
4127 rooted!(&in(cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
4128 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut())
4129 .expect("Failed to convert shared key to ArrayBufferU8")
4130 });
4131 let ciphertext = self.ciphertext.as_ref().map(|data| {
4132 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
4133 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
4134 .expect("Failed to convert ciphertext to ArrayBufferU8")
4135 });
4136 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
4137 sharedKey: shared_key,
4138 ciphertext,
4139 });
4140 encapsulated_bits.safe_to_jsval(cx, rval);
4141 }
4142}
4143
4144#[derive(Clone, MallocSizeOf)]
4146struct SubtleEd448Params {
4147 name: CryptoAlgorithm,
4149
4150 context: Option<Vec<u8>>,
4152}
4153
4154impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEd448Params {
4155 type Error = Error;
4156
4157 fn try_from_with_cx_and_name(
4158 object: HandleObject<'a>,
4159 cx: &mut js::context::JSContext,
4160 algorithm_name: CryptoAlgorithm,
4161 ) -> Result<Self, Self::Error> {
4162 Ok(SubtleEd448Params {
4163 name: algorithm_name,
4164 context: get_optional_buffer_source(cx, object, c"context")?,
4165 })
4166 }
4167}
4168
4169fn get_required_parameter<T: FromJSValConvertible>(
4171 cx: &mut js::context::JSContext,
4172 object: HandleObject,
4173 parameter: &std::ffi::CStr,
4174 option: T::Config,
4175) -> Fallible<T> {
4176 get_property::<T>(cx, object, parameter, option)?
4177 .ok_or(Error::Type(c"Missing required parameter".into()))
4178}
4179
4180fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4182 cx: &mut js::context::JSContext,
4183 object: HandleObject,
4184 parameter: &std::ffi::CStr,
4185 option: T::Config,
4186) -> Fallible<RootedTraceableBox<T>> {
4187 get_property::<T>(cx, object, parameter, option)?
4188 .map(RootedTraceableBox::new)
4189 .ok_or(Error::Type(c"Missing required parameter".into()))
4190}
4191
4192fn get_optional_buffer_source(
4196 cx: &mut js::context::JSContext,
4197 object: HandleObject,
4198 parameter: &std::ffi::CStr,
4199) -> Fallible<Option<Vec<u8>>> {
4200 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4201 Ok(buffer_source
4202 .as_ref()
4203 .map(|buffer| get_buffer_source_copy(buffer.into())))
4204}
4205
4206fn get_required_buffer_source(
4210 cx: &mut js::context::JSContext,
4211 object: HandleObject,
4212 parameter: &std::ffi::CStr,
4213) -> Fallible<Vec<u8>> {
4214 get_optional_buffer_source(cx, object, parameter)?
4215 .ok_or(Error::Type(c"Missing required parameter".into()))
4216}
4217
4218enum ExportedKey {
4222 Bytes(Zeroizing<Vec<u8>>),
4223 Jwk(Box<JsonWebKey>),
4224}
4225
4226impl ExportedKey {
4227 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4228 ExportedKey::Bytes(Zeroizing::new(bytes))
4229 }
4230
4231 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4232 ExportedKey::Jwk(Box::new(jwk))
4233 }
4234}
4235
4236#[derive(Clone, MallocSizeOf)]
4240#[expect(clippy::enum_variant_names)]
4241pub(crate) enum KeyAlgorithmAndDerivatives {
4242 KeyAlgorithm(SubtleKeyAlgorithm),
4243 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
4244 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
4245 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
4246 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
4247 KmacKeyAlgorithm(SubtleKmacKeyAlgorithm),
4248}
4249
4250impl KeyAlgorithmAndDerivatives {
4251 fn name(&self) -> CryptoAlgorithm {
4252 match self {
4253 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4254 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4255 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4256 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4257 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4258 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => algorithm.name,
4259 }
4260 }
4261}
4262
4263impl SafeToJSValConvertible for KeyAlgorithmAndDerivatives {
4264 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4265 match self {
4266 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4267 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4268 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4269 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4270 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4271 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4272 }
4273 }
4274}
4275
4276impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4277 type Error = ();
4278
4279 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4280 match value {
4281 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4282 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4283 ),
4284 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4285 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4286 ),
4287 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4288 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4289 ),
4290 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4291 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4292 ),
4293 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4294 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4295 ),
4296 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => Ok(
4297 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.try_into()?),
4298 ),
4299 }
4300 }
4301}
4302
4303impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4304 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4305 match value {
4306 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4307 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4308 },
4309 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4310 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4311 },
4312 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4313 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4314 },
4315 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4316 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4317 },
4318 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4319 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4320 },
4321 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => {
4322 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.into())
4323 },
4324 }
4325 }
4326}
4327
4328#[derive(Clone, Copy)]
4329enum JwkStringField {
4330 X,
4331 Y,
4332 D,
4333 N,
4334 E,
4335 P,
4336 Q,
4337 DP,
4338 DQ,
4339 QI,
4340 K,
4341 Priv,
4342 Pub,
4343}
4344
4345impl Display for JwkStringField {
4346 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4347 let field_name = match self {
4348 JwkStringField::X => "x",
4349 JwkStringField::Y => "y",
4350 JwkStringField::D => "d",
4351 JwkStringField::N => "n",
4352 JwkStringField::E => "e",
4353 JwkStringField::P => "q",
4354 JwkStringField::Q => "q",
4355 JwkStringField::DP => "dp",
4356 JwkStringField::DQ => "dq",
4357 JwkStringField::QI => "qi",
4358 JwkStringField::K => "k",
4359 JwkStringField::Priv => "priv",
4360 JwkStringField::Pub => "pub",
4361 };
4362 write!(f, "{}", field_name)
4363 }
4364}
4365
4366trait JsonWebKeyExt {
4367 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4368 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4369 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4370 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4371 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4372 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4373 fn decode_optional_string_field(
4374 &self,
4375 field: JwkStringField,
4376 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4377 fn decode_required_string_field(
4378 &self,
4379 field: JwkStringField,
4380 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4381 fn decode_primes_from_oth_field(
4382 &self,
4383 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4384 ) -> Result<(), Error>;
4385}
4386
4387impl JsonWebKeyExt for JsonWebKey {
4388 #[expect(unsafe_code)]
4390 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4391 let json = String::from_utf8_lossy(data);
4396
4397 let json: Vec<_> = json.encode_utf16().collect();
4399
4400 rooted!(&in(cx) let mut result = UndefinedValue());
4404 unsafe {
4405 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4406 return Err(Error::JSFailed);
4407 }
4408 }
4409
4410 let key = match JsonWebKey::new(cx, result.handle()) {
4412 Ok(ConversionResult::Success(key)) => key,
4413 Ok(ConversionResult::Failure(error)) => {
4414 return Err(Error::Type(error.into_owned()));
4415 },
4416 Err(()) => {
4417 return Err(Error::JSFailed);
4418 },
4419 };
4420
4421 if key.kty.is_none() {
4423 return Err(Error::Data(Some(
4424 "'kty' field of key is not defined".into(),
4425 )));
4426 }
4427
4428 Ok(key)
4430 }
4431
4432 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4438 rooted!(&in(cx) let mut data = UndefinedValue());
4439 self.safe_to_jsval(cx, data.handle_mut());
4440 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4441 }
4442
4443 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4444 let mut usages = vec![];
4445 for op in self.key_ops.as_ref().ok_or(Error::Data(Some(
4446 "'key_ops' member is not present in the JSON Web Key".into(),
4447 )))? {
4448 usages.push(
4449 KeyUsage::from_str(&op.str())
4450 .map_err(|_| Error::Data(Some("Unknown key usage".into())))?,
4451 );
4452 }
4453 Ok(usages)
4454 }
4455
4456 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4460 if let Some(ref key_ops) = self.key_ops {
4462 if key_ops
4465 .iter()
4466 .collect::<std::collections::HashSet<_>>()
4467 .len() <
4468 key_ops.len()
4469 {
4470 return Err(Error::Data(Some(
4471 "Duplicate key operation values are present in array".into(),
4472 )));
4473 }
4474 if let Some(ref use_) = self.use_ &&
4477 key_ops.iter().any(|op| op != use_)
4478 {
4479 return Err(Error::Data(Some(
4480 "Key operations are not consistent with intended use for Json Web Key".into(),
4481 )));
4482 }
4483
4484 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4486 if !specified_usages
4487 .iter()
4488 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4489 {
4490 return Err(Error::Data(Some(
4491 "Key operations do not contain all of the specified usage values".into(),
4492 )));
4493 }
4494 }
4495
4496 Ok(())
4497 }
4498
4499 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4501 self.key_ops = Some(
4502 usages
4503 .iter()
4504 .map(|usage| DOMString::from(usage.as_str()))
4505 .collect(),
4506 );
4507 }
4508
4509 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4512 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4513 match field {
4514 JwkStringField::X => self.x = Some(encoded_data),
4515 JwkStringField::Y => self.y = Some(encoded_data),
4516 JwkStringField::D => self.d = Some(encoded_data),
4517 JwkStringField::N => self.n = Some(encoded_data),
4518 JwkStringField::E => self.e = Some(encoded_data),
4519 JwkStringField::P => self.p = Some(encoded_data),
4520 JwkStringField::Q => self.q = Some(encoded_data),
4521 JwkStringField::DP => self.dp = Some(encoded_data),
4522 JwkStringField::DQ => self.dq = Some(encoded_data),
4523 JwkStringField::QI => self.qi = Some(encoded_data),
4524 JwkStringField::K => self.k = Some(encoded_data),
4525 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4526 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4527 }
4528 }
4529
4530 fn decode_optional_string_field(
4533 &self,
4534 field: JwkStringField,
4535 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4536 let field_string = match field {
4537 JwkStringField::X => &self.x,
4538 JwkStringField::Y => &self.y,
4539 JwkStringField::D => &self.d,
4540 JwkStringField::N => &self.n,
4541 JwkStringField::E => &self.e,
4542 JwkStringField::P => &self.p,
4543 JwkStringField::Q => &self.q,
4544 JwkStringField::DP => &self.dp,
4545 JwkStringField::DQ => &self.dq,
4546 JwkStringField::QI => &self.qi,
4547 JwkStringField::K => &self.k,
4548 JwkStringField::Priv => &self.priv_,
4549 JwkStringField::Pub => &self.pub_,
4550 };
4551
4552 field_string
4553 .as_ref()
4554 .map(|field_string| {
4555 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4556 })
4557 .transpose()
4558 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4559 }
4560
4561 fn decode_required_string_field(
4564 &self,
4565 field: JwkStringField,
4566 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4567 self.decode_optional_string_field(field)?
4568 .ok_or(Error::Data(Some(format!(
4569 "The {} field is not present in jwk",
4570 field
4571 ))))
4572 }
4573
4574 fn decode_primes_from_oth_field(
4583 &self,
4584 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4585 ) -> Result<(), Error> {
4586 if self.oth.is_some() &&
4587 (self.p.is_none() ||
4588 self.q.is_none() ||
4589 self.dp.is_none() ||
4590 self.dq.is_none() ||
4591 self.qi.is_none())
4592 {
4593 return Err(Error::Data(Some(
4594 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4595 )));
4596 }
4597
4598 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4599 let r = Base64UrlUnpadded::decode_vec(
4600 &rsa_other_prime_info
4601 .r
4602 .as_ref()
4603 .ok_or(Error::Data(Some(
4604 "The r field is not present in one of the entry of oth field in jwk"
4605 .to_string(),
4606 )))?
4607 .str(),
4608 )
4609 .map_err(|_| {
4610 Error::Data(Some(
4611 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4612 ))
4613 })?;
4614 primes.push(Zeroizing::new(r));
4615
4616 let _d = Base64UrlUnpadded::decode_vec(
4617 &rsa_other_prime_info
4618 .d
4619 .as_ref()
4620 .ok_or(Error::Data(Some(
4621 "The d field is not present in one of the entry of oth field in jwk"
4622 .to_string(),
4623 )))?
4624 .str(),
4625 )
4626 .map_err(|_| {
4627 Error::Data(Some(
4628 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4629 ))
4630 })?;
4631
4632 let _t = Base64UrlUnpadded::decode_vec(
4633 &rsa_other_prime_info
4634 .t
4635 .as_ref()
4636 .ok_or(Error::Data(Some(
4637 "The t field is not present in one of the entry of oth field in jwk"
4638 .to_string(),
4639 )))?
4640 .str(),
4641 )
4642 .map_err(|_| {
4643 Error::Data(Some(
4644 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4645 ))
4646 })?;
4647 }
4648
4649 Ok(())
4650 }
4651}
4652
4653fn normalize_algorithm<Op: Operation>(
4655 cx: &mut js::context::JSContext,
4656 algorithm: &AlgorithmIdentifier,
4657) -> Result<Op::RegisteredAlgorithm, Error> {
4658 match algorithm {
4659 ObjectOrString::String(name) => {
4661 let algorithm = Algorithm {
4665 name: name.to_owned(),
4666 };
4667 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4668 algorithm.safe_to_jsval(cx, algorithm_value.handle_mut());
4669 let algorithm_object = RootedTraceableBox::new(Heap::default());
4670 algorithm_object.set(algorithm_value.to_object());
4671 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
4672 },
4673 ObjectOrString::Object(object) => {
4675 let algorithm_name = get_required_parameter::<DOMString>(
4683 cx,
4684 object.handle(),
4685 c"name",
4686 StringificationBehavior::Default,
4687 )?;
4688
4689 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4730 let normalized_algorithm =
4731 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4732
4733 Ok(normalized_algorithm)
4735 },
4736 }
4737}
4738
4739trait Operation {
4794 type RegisteredAlgorithm: NormalizedAlgorithm;
4795}
4796
4797trait NormalizedAlgorithm: Sized {
4798 fn from_object(
4800 cx: &mut js::context::JSContext,
4801 algorithm_name: CryptoAlgorithm,
4802 object: HandleObject,
4803 ) -> Fallible<Self>;
4804 fn name(&self) -> CryptoAlgorithm;
4805}
4806
4807struct EncryptOperation {}
4809
4810impl Operation for EncryptOperation {
4811 type RegisteredAlgorithm = EncryptAlgorithm;
4812}
4813
4814enum EncryptAlgorithm {
4817 RsaOaep(SubtleRsaOaepParams),
4818 AesCtr(SubtleAesCtrParams),
4819 AesCbc(SubtleAesCbcParams),
4820 AesGcm(SubtleAesGcmParams),
4821 AesOcb(SubtleAeadParams),
4822 ChaCha20Poly1305(SubtleAeadParams),
4823}
4824
4825impl NormalizedAlgorithm for EncryptAlgorithm {
4826 fn from_object(
4827 cx: &mut js::context::JSContext,
4828 algorithm_name: CryptoAlgorithm,
4829 object: HandleObject,
4830 ) -> Fallible<Self> {
4831 match algorithm_name {
4832 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4833 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4834 )),
4835 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4836 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4837 )),
4838 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4839 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4840 )),
4841 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4842 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4843 )),
4844 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4845 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4846 )),
4847 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4848 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4849 )),
4850 _ => Err(Error::NotSupported(Some(format!(
4851 "{} does not support \"encrypt\" operation",
4852 algorithm_name.as_str()
4853 )))),
4854 }
4855 }
4856
4857 fn name(&self) -> CryptoAlgorithm {
4858 match self {
4859 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4860 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4861 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4862 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4863 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4864 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4865 }
4866 }
4867}
4868
4869impl EncryptAlgorithm {
4870 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4871 match self {
4872 EncryptAlgorithm::RsaOaep(algorithm) => {
4873 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4874 },
4875 EncryptAlgorithm::AesCtr(algorithm) => {
4876 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4877 },
4878 EncryptAlgorithm::AesCbc(algorithm) => {
4879 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4880 },
4881 EncryptAlgorithm::AesGcm(algorithm) => {
4882 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4883 },
4884 EncryptAlgorithm::AesOcb(algorithm) => {
4885 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4886 },
4887 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4888 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4889 },
4890 }
4891 }
4892}
4893
4894struct DecryptOperation {}
4896
4897impl Operation for DecryptOperation {
4898 type RegisteredAlgorithm = DecryptAlgorithm;
4899}
4900
4901enum DecryptAlgorithm {
4904 RsaOaep(SubtleRsaOaepParams),
4905 AesCtr(SubtleAesCtrParams),
4906 AesCbc(SubtleAesCbcParams),
4907 AesGcm(SubtleAesGcmParams),
4908 AesOcb(SubtleAeadParams),
4909 ChaCha20Poly1305(SubtleAeadParams),
4910}
4911
4912impl NormalizedAlgorithm for DecryptAlgorithm {
4913 fn from_object(
4914 cx: &mut js::context::JSContext,
4915 algorithm_name: CryptoAlgorithm,
4916 object: HandleObject,
4917 ) -> Fallible<Self> {
4918 match algorithm_name {
4919 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4920 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4921 )),
4922 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4923 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4924 )),
4925 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4926 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4927 )),
4928 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4929 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4930 )),
4931 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4932 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4933 )),
4934 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
4935 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4936 )),
4937 _ => Err(Error::NotSupported(Some(format!(
4938 "{} does not support \"decrypt\" operation",
4939 algorithm_name.as_str()
4940 )))),
4941 }
4942 }
4943
4944 fn name(&self) -> CryptoAlgorithm {
4945 match self {
4946 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4947 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4948 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4949 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4950 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4951 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4952 }
4953 }
4954}
4955
4956impl DecryptAlgorithm {
4957 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
4958 match self {
4959 DecryptAlgorithm::RsaOaep(algorithm) => {
4960 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
4961 },
4962 DecryptAlgorithm::AesCtr(algorithm) => {
4963 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
4964 },
4965 DecryptAlgorithm::AesCbc(algorithm) => {
4966 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
4967 },
4968 DecryptAlgorithm::AesGcm(algorithm) => {
4969 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
4970 },
4971 DecryptAlgorithm::AesOcb(algorithm) => {
4972 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
4973 },
4974 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4975 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
4976 },
4977 }
4978 }
4979}
4980
4981struct SignOperation {}
4983
4984impl Operation for SignOperation {
4985 type RegisteredAlgorithm = SignAlgorithm;
4986}
4987
4988enum SignAlgorithm {
4991 RsassaPkcs1V1_5(SubtleAlgorithm),
4992 RsaPss(SubtleRsaPssParams),
4993 Ecdsa(SubtleEcdsaParams),
4994 Ed25519(SubtleAlgorithm),
4995 Ed448(SubtleEd448Params),
4996 Hmac(SubtleAlgorithm),
4997 MlDsa(SubtleContextParams),
4998 Kmac(SubtleKmacParams),
4999}
5000
5001impl NormalizedAlgorithm for SignAlgorithm {
5002 fn from_object(
5003 cx: &mut js::context::JSContext,
5004 algorithm_name: CryptoAlgorithm,
5005 object: HandleObject,
5006 ) -> Fallible<Self> {
5007 match algorithm_name {
5008 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
5009 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5010 )),
5011 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
5012 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5013 )),
5014 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
5015 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5016 )),
5017 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
5018 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5019 )),
5020 CryptoAlgorithm::Ed448 => Ok(SignAlgorithm::Ed448(
5021 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5022 )),
5023 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
5024 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5025 )),
5026 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5027 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5028 ),
5029 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(SignAlgorithm::Kmac(
5030 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5031 )),
5032 _ => Err(Error::NotSupported(Some(format!(
5033 "{} does not support \"sign\" operation",
5034 algorithm_name.as_str()
5035 )))),
5036 }
5037 }
5038
5039 fn name(&self) -> CryptoAlgorithm {
5040 match self {
5041 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5042 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
5043 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
5044 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
5045 SignAlgorithm::Ed448(algorithm) => algorithm.name,
5046 SignAlgorithm::Hmac(algorithm) => algorithm.name,
5047 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
5048 SignAlgorithm::Kmac(algorithm) => algorithm.name,
5049 }
5050 }
5051}
5052
5053impl SignAlgorithm {
5054 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
5055 match self {
5056 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5057 rsassa_pkcs1_v1_5_operation::sign(key, message)
5058 },
5059 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
5060 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
5061 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
5062 SignAlgorithm::Ed448(algorithm) => ed448_operation::sign(algorithm, key, message),
5063 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
5064 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
5065 SignAlgorithm::Kmac(algorithm) => kmac_operation::sign(algorithm, key, message),
5066 }
5067 }
5068}
5069
5070struct VerifyOperation {}
5072
5073impl Operation for VerifyOperation {
5074 type RegisteredAlgorithm = VerifyAlgorithm;
5075}
5076
5077enum VerifyAlgorithm {
5080 RsassaPkcs1V1_5(SubtleAlgorithm),
5081 RsaPss(SubtleRsaPssParams),
5082 Ecdsa(SubtleEcdsaParams),
5083 Ed25519(SubtleAlgorithm),
5084 Ed448(SubtleEd448Params),
5085 Hmac(SubtleAlgorithm),
5086 MlDsa(SubtleContextParams),
5087 Kmac(SubtleKmacParams),
5088}
5089
5090impl NormalizedAlgorithm for VerifyAlgorithm {
5091 fn from_object(
5092 cx: &mut js::context::JSContext,
5093 algorithm_name: CryptoAlgorithm,
5094 object: HandleObject,
5095 ) -> Fallible<Self> {
5096 match algorithm_name {
5097 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
5098 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5099 )),
5100 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
5101 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5102 )),
5103 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
5104 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5105 )),
5106 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
5107 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5108 )),
5109 CryptoAlgorithm::Ed448 => Ok(VerifyAlgorithm::Ed448(
5110 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5111 )),
5112 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
5113 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5114 )),
5115 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5116 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5117 ),
5118 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(VerifyAlgorithm::Kmac(
5119 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5120 )),
5121 _ => Err(Error::NotSupported(Some(format!(
5122 "{} does not support \"verify\" operation",
5123 algorithm_name.as_str()
5124 )))),
5125 }
5126 }
5127
5128 fn name(&self) -> CryptoAlgorithm {
5129 match self {
5130 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5131 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
5132 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5133 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
5134 VerifyAlgorithm::Ed448(algorithm) => algorithm.name,
5135 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
5136 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
5137 VerifyAlgorithm::Kmac(algorithm) => algorithm.name,
5138 }
5139 }
5140}
5141
5142impl VerifyAlgorithm {
5143 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
5144 match self {
5145 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5146 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
5147 },
5148 VerifyAlgorithm::RsaPss(algorithm) => {
5149 rsa_pss_operation::verify(algorithm, key, message, signature)
5150 },
5151 VerifyAlgorithm::Ecdsa(algorithm) => {
5152 ecdsa_operation::verify(algorithm, key, message, signature)
5153 },
5154 VerifyAlgorithm::Ed25519(_algorithm) => {
5155 ed25519_operation::verify(key, message, signature)
5156 },
5157 VerifyAlgorithm::Ed448(algorithm) => {
5158 ed448_operation::verify(algorithm, key, message, signature)
5159 },
5160 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
5161 VerifyAlgorithm::MlDsa(algorithm) => {
5162 ml_dsa_operation::verify(algorithm, key, message, signature)
5163 },
5164 VerifyAlgorithm::Kmac(algorithm) => {
5165 kmac_operation::verify(algorithm, key, message, signature)
5166 },
5167 }
5168 }
5169}
5170
5171struct DigestOperation {}
5173
5174impl Operation for DigestOperation {
5175 type RegisteredAlgorithm = DigestAlgorithm;
5176}
5177
5178#[derive(Clone, MallocSizeOf)]
5181enum DigestAlgorithm {
5182 Sha(SubtleAlgorithm),
5183 Sha3(SubtleAlgorithm),
5184 CShake(SubtleCShakeParams),
5185 TurboShake(SubtleTurboShakeParams),
5186 KangarooTwelve(SubtleKangarooTwelveParams),
5187}
5188
5189impl NormalizedAlgorithm for DigestAlgorithm {
5190 fn from_object(
5191 cx: &mut js::context::JSContext,
5192 algorithm_name: CryptoAlgorithm,
5193 object: HandleObject,
5194 ) -> Fallible<Self> {
5195 match algorithm_name {
5196 CryptoAlgorithm::Sha1 |
5197 CryptoAlgorithm::Sha256 |
5198 CryptoAlgorithm::Sha384 |
5199 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
5200 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5201 )),
5202 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5203 Ok(DigestAlgorithm::Sha3(
5204 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5205 ))
5206 },
5207 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5208 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5209 )),
5210 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5211 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5212 ),
5213 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5214 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5215 )),
5216 _ => Err(Error::NotSupported(Some(format!(
5217 "{} does not support \"digest\" operation",
5218 algorithm_name.as_str()
5219 )))),
5220 }
5221 }
5222
5223 fn name(&self) -> CryptoAlgorithm {
5224 match self {
5225 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5226 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5227 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5228 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5229 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5230 }
5231 }
5232}
5233
5234impl DigestAlgorithm {
5235 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5236 match self {
5237 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5238 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5239 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5240 DigestAlgorithm::TurboShake(algorithm) => {
5241 turboshake_operation::digest(algorithm, message)
5242 },
5243 DigestAlgorithm::KangarooTwelve(algorithm) => {
5244 kangarootwelve_operation::digest(algorithm, message)
5245 },
5246 }
5247 }
5248}
5249
5250impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5251 type Error = ();
5252
5253 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5254 match value {
5255 SerializableDigestAlgorithm::Sha(algorithm) => {
5256 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5257 },
5258 SerializableDigestAlgorithm::Sha3(algorithm) => {
5259 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5260 },
5261 SerializableDigestAlgorithm::CShake(algorithm) => {
5262 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5263 },
5264 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5265 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5266 },
5267 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5268 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5269 },
5270 }
5271 }
5272}
5273
5274impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5275 fn from(value: &DigestAlgorithm) -> Self {
5276 match value {
5277 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5278 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5279 DigestAlgorithm::CShake(algorithm) => {
5280 SerializableDigestAlgorithm::CShake(algorithm.into())
5281 },
5282 DigestAlgorithm::TurboShake(algorithm) => {
5283 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5284 },
5285 DigestAlgorithm::KangarooTwelve(algorithm) => {
5286 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5287 },
5288 }
5289 }
5290}
5291
5292struct DeriveBitsOperation {}
5294
5295impl Operation for DeriveBitsOperation {
5296 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5297}
5298
5299enum DeriveBitsAlgorithm {
5302 Ecdh(SubtleEcdhKeyDeriveParams),
5303 X25519(SubtleEcdhKeyDeriveParams),
5304 X448(SubtleEcdhKeyDeriveParams),
5305 Hkdf(SubtleHkdfParams),
5306 Pbkdf2(SubtlePbkdf2Params),
5307 Argon2(SubtleArgon2Params),
5308}
5309
5310impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5311 fn from_object(
5312 cx: &mut js::context::JSContext,
5313 algorithm_name: CryptoAlgorithm,
5314 object: HandleObject,
5315 ) -> Fallible<Self> {
5316 match algorithm_name {
5317 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5318 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5319 )),
5320 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5321 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5322 )),
5323 CryptoAlgorithm::X448 => Ok(DeriveBitsAlgorithm::X448(
5324 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5325 )),
5326 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5327 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5328 )),
5329 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5330 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5331 )),
5332 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5333 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5334 ),
5335 _ => Err(Error::NotSupported(Some(format!(
5336 "{} does not support \"deriveBits\" operation",
5337 algorithm_name.as_str()
5338 )))),
5339 }
5340 }
5341
5342 fn name(&self) -> CryptoAlgorithm {
5343 match self {
5344 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5345 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5346 DeriveBitsAlgorithm::X448(algorithm) => algorithm.name,
5347 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5348 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5349 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5350 }
5351 }
5352}
5353
5354impl DeriveBitsAlgorithm {
5355 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5356 match self {
5357 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5358 ecdh_operation::derive_bits(algorithm, key, length)
5359 },
5360 DeriveBitsAlgorithm::X25519(algorithm) => {
5361 x25519_operation::derive_bits(algorithm, key, length)
5362 },
5363 DeriveBitsAlgorithm::X448(algorithm) => {
5364 x448_operation::derive_bits(algorithm, key, length)
5365 },
5366 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5367 hkdf_operation::derive_bits(algorithm, key, length)
5368 },
5369 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5370 pbkdf2_operation::derive_bits(algorithm, key, length)
5371 },
5372 DeriveBitsAlgorithm::Argon2(algorithm) => {
5373 argon2_operation::derive_bits(algorithm, key, length)
5374 },
5375 }
5376 }
5377}
5378
5379struct WrapKeyOperation {}
5381
5382impl Operation for WrapKeyOperation {
5383 type RegisteredAlgorithm = WrapKeyAlgorithm;
5384}
5385
5386enum WrapKeyAlgorithm {
5389 AesKw(SubtleAlgorithm),
5390}
5391
5392impl NormalizedAlgorithm for WrapKeyAlgorithm {
5393 fn from_object(
5394 cx: &mut js::context::JSContext,
5395 algorithm_name: CryptoAlgorithm,
5396 object: HandleObject,
5397 ) -> Fallible<Self> {
5398 match algorithm_name {
5399 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5400 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5401 )),
5402 _ => Err(Error::NotSupported(Some(format!(
5403 "{} does not support \"wrapKey\" operation",
5404 algorithm_name.as_str()
5405 )))),
5406 }
5407 }
5408
5409 fn name(&self) -> CryptoAlgorithm {
5410 match self {
5411 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5412 }
5413 }
5414}
5415
5416impl WrapKeyAlgorithm {
5417 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5418 match self {
5419 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5420 }
5421 }
5422}
5423
5424struct UnwrapKeyOperation {}
5426
5427impl Operation for UnwrapKeyOperation {
5428 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5429}
5430
5431enum UnwrapKeyAlgorithm {
5434 AesKw(SubtleAlgorithm),
5435}
5436
5437impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5438 fn from_object(
5439 cx: &mut js::context::JSContext,
5440 algorithm_name: CryptoAlgorithm,
5441 object: HandleObject,
5442 ) -> Fallible<Self> {
5443 match algorithm_name {
5444 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5445 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5446 )),
5447 _ => Err(Error::NotSupported(Some(format!(
5448 "{} does not support \"unwrapKey\" operation",
5449 algorithm_name.as_str()
5450 )))),
5451 }
5452 }
5453
5454 fn name(&self) -> CryptoAlgorithm {
5455 match self {
5456 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5457 }
5458 }
5459}
5460
5461impl UnwrapKeyAlgorithm {
5462 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5463 match self {
5464 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5465 }
5466 }
5467}
5468
5469struct GenerateKeyOperation {}
5471
5472impl Operation for GenerateKeyOperation {
5473 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5474}
5475
5476enum GenerateKeyAlgorithm {
5479 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
5480 RsaPss(SubtleRsaHashedKeyGenParams),
5481 RsaOaep(SubtleRsaHashedKeyGenParams),
5482 Ecdsa(SubtleEcKeyGenParams),
5483 Ecdh(SubtleEcKeyGenParams),
5484 Ed25519(SubtleAlgorithm),
5485 X25519(SubtleAlgorithm),
5486 Ed448(SubtleAlgorithm),
5487 X448(SubtleAlgorithm),
5488 AesCtr(SubtleAesKeyGenParams),
5489 AesCbc(SubtleAesKeyGenParams),
5490 AesGcm(SubtleAesKeyGenParams),
5491 AesKw(SubtleAesKeyGenParams),
5492 Hmac(SubtleHmacKeyGenParams),
5493 MlKem(SubtleAlgorithm),
5494 MlDsa(SubtleAlgorithm),
5495 AesOcb(SubtleAesKeyGenParams),
5496 ChaCha20Poly1305(SubtleAlgorithm),
5497 Kmac(SubtleKmacKeyGenParams),
5498}
5499
5500impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5501 fn from_object(
5502 cx: &mut js::context::JSContext,
5503 algorithm_name: CryptoAlgorithm,
5504 object: HandleObject,
5505 ) -> Fallible<Self> {
5506 match algorithm_name {
5507 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5508 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5509 )),
5510 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5511 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5512 )),
5513 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5514 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5515 )),
5516 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5517 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5518 )),
5519 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5520 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5521 )),
5522 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5523 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5524 )),
5525 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5526 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5527 )),
5528 CryptoAlgorithm::Ed448 => Ok(GenerateKeyAlgorithm::Ed448(
5529 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5530 )),
5531 CryptoAlgorithm::X448 => Ok(GenerateKeyAlgorithm::X448(
5532 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5533 )),
5534 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5535 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5536 )),
5537 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5538 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5539 )),
5540 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5541 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5542 )),
5543 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5544 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5545 )),
5546 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5547 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5548 )),
5549 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5550 Ok(GenerateKeyAlgorithm::MlKem(
5551 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5552 ))
5553 },
5554 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5555 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5556 ),
5557 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5558 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5559 )),
5560 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5561 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5562 )),
5563 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GenerateKeyAlgorithm::Kmac(
5564 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5565 )),
5566 _ => Err(Error::NotSupported(Some(format!(
5567 "{} does not support \"generateKey\" operation",
5568 algorithm_name.as_str()
5569 )))),
5570 }
5571 }
5572
5573 fn name(&self) -> CryptoAlgorithm {
5574 match self {
5575 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5576 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5577 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5578 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5579 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5580 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5581 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5582 GenerateKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5583 GenerateKeyAlgorithm::X448(algorithm) => algorithm.name,
5584 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5585 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5586 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5587 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5588 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5589 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5590 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5591 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5592 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5593 GenerateKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5594 }
5595 }
5596}
5597
5598impl GenerateKeyAlgorithm {
5599 fn generate_key(
5600 &self,
5601 cx: &mut js::context::JSContext,
5602 global: &GlobalScope,
5603 extractable: bool,
5604 usages: Vec<KeyUsage>,
5605 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5606 match self {
5607 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5608 rsassa_pkcs1_v1_5_operation::generate_key(
5609 cx,
5610 global,
5611 algorithm,
5612 extractable,
5613 usages,
5614 )
5615 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5616 },
5617 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5618 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5619 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5620 },
5621 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5622 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5623 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5624 },
5625 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5626 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5627 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5628 },
5629 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5630 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5631 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5632 },
5633 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5634 ed25519_operation::generate_key(cx, global, extractable, usages)
5635 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5636 },
5637 GenerateKeyAlgorithm::X25519(_algorithm) => {
5638 x25519_operation::generate_key(cx, global, extractable, usages)
5639 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5640 },
5641 GenerateKeyAlgorithm::Ed448(_algorithm) => {
5642 ed448_operation::generate_key(cx, global, extractable, usages)
5643 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5644 },
5645 GenerateKeyAlgorithm::X448(_algorithm) => {
5646 x448_operation::generate_key(cx, global, extractable, usages)
5647 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5648 },
5649 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5650 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5651 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5652 },
5653 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5654 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5655 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5656 },
5657 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5658 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5659 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5660 },
5661 GenerateKeyAlgorithm::AesKw(algorithm) => {
5662 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5663 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5664 },
5665 GenerateKeyAlgorithm::Hmac(algorithm) => {
5666 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5667 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5668 },
5669 GenerateKeyAlgorithm::MlKem(algorithm) => {
5670 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5671 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5672 },
5673 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5674 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5675 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5676 },
5677 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5678 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5679 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5680 },
5681 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5682 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5683 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5684 },
5685 GenerateKeyAlgorithm::Kmac(algorithm) => {
5686 kmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5687 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5688 },
5689 }
5690 }
5691}
5692
5693struct ImportKeyOperation {}
5695
5696impl Operation for ImportKeyOperation {
5697 type RegisteredAlgorithm = ImportKeyAlgorithm;
5698}
5699
5700enum ImportKeyAlgorithm {
5703 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
5704 RsaPss(SubtleRsaHashedImportParams),
5705 RsaOaep(SubtleRsaHashedImportParams),
5706 Ecdsa(SubtleEcKeyImportParams),
5707 Ecdh(SubtleEcKeyImportParams),
5708 Ed25519(SubtleAlgorithm),
5709 X25519(SubtleAlgorithm),
5710 Ed448(SubtleAlgorithm),
5711 X448(SubtleAlgorithm),
5712 AesCtr(SubtleAlgorithm),
5713 AesCbc(SubtleAlgorithm),
5714 AesGcm(SubtleAlgorithm),
5715 AesKw(SubtleAlgorithm),
5716 Hmac(SubtleHmacImportParams),
5717 Hkdf(SubtleAlgorithm),
5718 Pbkdf2(SubtleAlgorithm),
5719 MlKem(SubtleAlgorithm),
5720 MlDsa(SubtleAlgorithm),
5721 AesOcb(SubtleAlgorithm),
5722 ChaCha20Poly1305(SubtleAlgorithm),
5723 Kmac(SubtleKmacImportParams),
5724 Argon2(SubtleAlgorithm),
5725}
5726
5727impl NormalizedAlgorithm for ImportKeyAlgorithm {
5728 fn from_object(
5729 cx: &mut js::context::JSContext,
5730 algorithm_name: CryptoAlgorithm,
5731 object: HandleObject,
5732 ) -> Fallible<Self> {
5733 match algorithm_name {
5734 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5735 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5736 )),
5737 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5738 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5739 )),
5740 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5741 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5742 )),
5743 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5744 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5745 )),
5746 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5747 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5748 )),
5749 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5750 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5751 )),
5752 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5753 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5754 )),
5755 CryptoAlgorithm::Ed448 => Ok(ImportKeyAlgorithm::Ed448(
5756 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5757 )),
5758 CryptoAlgorithm::X448 => Ok(ImportKeyAlgorithm::X448(
5759 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5760 )),
5761 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5762 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5763 )),
5764 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5765 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5766 )),
5767 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5768 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5769 )),
5770 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5771 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5772 )),
5773 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5774 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5775 )),
5776 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5777 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5778 )),
5779 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5780 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5781 )),
5782 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5783 Ok(ImportKeyAlgorithm::MlKem(
5784 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5785 ))
5786 },
5787 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5788 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5789 ),
5790 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5791 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5792 )),
5793 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5794 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5795 )),
5796 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ImportKeyAlgorithm::Kmac(
5797 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5798 )),
5799 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5800 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5801 ),
5802 _ => Err(Error::NotSupported(Some(format!(
5803 "{} does not support \"importKey\" operation",
5804 algorithm_name.as_str()
5805 )))),
5806 }
5807 }
5808
5809 fn name(&self) -> CryptoAlgorithm {
5810 match self {
5811 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5812 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5813 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5814 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5815 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5816 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5817 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5818 ImportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5819 ImportKeyAlgorithm::X448(algorithm) => algorithm.name,
5820 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5821 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5822 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5823 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5824 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5825 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
5826 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5827 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5828 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5829 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5830 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5831 ImportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5832 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
5833 }
5834 }
5835}
5836
5837impl ImportKeyAlgorithm {
5838 fn import_key(
5839 &self,
5840 cx: &mut js::context::JSContext,
5841 global: &GlobalScope,
5842 format: KeyFormat,
5843 key_data: &[u8],
5844 extractable: bool,
5845 usages: Vec<KeyUsage>,
5846 ) -> Result<DomRoot<CryptoKey>, Error> {
5847 match self {
5848 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5849 rsassa_pkcs1_v1_5_operation::import_key(
5850 cx,
5851 global,
5852 algorithm,
5853 format,
5854 key_data,
5855 extractable,
5856 usages,
5857 )
5858 },
5859 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
5860 cx,
5861 global,
5862 algorithm,
5863 format,
5864 key_data,
5865 extractable,
5866 usages,
5867 ),
5868 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
5869 cx,
5870 global,
5871 algorithm,
5872 format,
5873 key_data,
5874 extractable,
5875 usages,
5876 ),
5877 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
5878 cx,
5879 global,
5880 algorithm,
5881 format,
5882 key_data,
5883 extractable,
5884 usages,
5885 ),
5886 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
5887 cx,
5888 global,
5889 algorithm,
5890 format,
5891 key_data,
5892 extractable,
5893 usages,
5894 ),
5895 ImportKeyAlgorithm::Ed25519(_algorithm) => {
5896 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5897 },
5898 ImportKeyAlgorithm::X25519(_algorithm) => {
5899 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5900 },
5901 ImportKeyAlgorithm::Ed448(_algorithm) => {
5902 ed448_operation::import_key(cx, global, format, key_data, extractable, usages)
5903 },
5904 ImportKeyAlgorithm::X448(_algorithm) => {
5905 x448_operation::import_key(cx, global, format, key_data, extractable, usages)
5906 },
5907 ImportKeyAlgorithm::AesCtr(_algorithm) => {
5908 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
5909 },
5910 ImportKeyAlgorithm::AesCbc(_algorithm) => {
5911 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
5912 },
5913 ImportKeyAlgorithm::AesGcm(_algorithm) => {
5914 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
5915 },
5916 ImportKeyAlgorithm::AesKw(_algorithm) => {
5917 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
5918 },
5919 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
5920 cx,
5921 global,
5922 algorithm,
5923 format,
5924 key_data,
5925 extractable,
5926 usages,
5927 ),
5928 ImportKeyAlgorithm::Hkdf(_algorithm) => {
5929 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
5930 },
5931 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
5932 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
5933 },
5934 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
5935 cx,
5936 global,
5937 algorithm,
5938 format,
5939 key_data,
5940 extractable,
5941 usages,
5942 ),
5943 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
5944 cx,
5945 global,
5946 algorithm,
5947 format,
5948 key_data,
5949 extractable,
5950 usages,
5951 ),
5952 ImportKeyAlgorithm::AesOcb(_algorithm) => {
5953 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
5954 },
5955 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5956 chacha20_poly1305_operation::import_key(
5957 cx,
5958 global,
5959 format,
5960 key_data,
5961 extractable,
5962 usages,
5963 )
5964 },
5965 ImportKeyAlgorithm::Kmac(algorithm) => kmac_operation::import_key(
5966 cx,
5967 global,
5968 algorithm,
5969 format,
5970 key_data,
5971 extractable,
5972 usages,
5973 ),
5974 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
5975 cx,
5976 global,
5977 algorithm,
5978 format,
5979 key_data,
5980 extractable,
5981 usages,
5982 ),
5983 }
5984 }
5985}
5986
5987struct ExportKeyOperation {}
5989
5990impl Operation for ExportKeyOperation {
5991 type RegisteredAlgorithm = ExportKeyAlgorithm;
5992}
5993
5994enum ExportKeyAlgorithm {
5997 RsassaPkcs1V1_5(SubtleAlgorithm),
5998 RsaPss(SubtleAlgorithm),
5999 RsaOaep(SubtleAlgorithm),
6000 Ecdsa(SubtleAlgorithm),
6001 Ecdh(SubtleAlgorithm),
6002 Ed25519(SubtleAlgorithm),
6003 X25519(SubtleAlgorithm),
6004 Ed448(SubtleAlgorithm),
6005 X448(SubtleAlgorithm),
6006 AesCtr(SubtleAlgorithm),
6007 AesCbc(SubtleAlgorithm),
6008 AesGcm(SubtleAlgorithm),
6009 AesKw(SubtleAlgorithm),
6010 Hmac(SubtleAlgorithm),
6011 MlKem(SubtleAlgorithm),
6012 MlDsa(SubtleAlgorithm),
6013 AesOcb(SubtleAlgorithm),
6014 ChaCha20Poly1305(SubtleAlgorithm),
6015 Kmac(SubtleAlgorithm),
6016}
6017
6018impl NormalizedAlgorithm for ExportKeyAlgorithm {
6019 fn from_object(
6020 cx: &mut js::context::JSContext,
6021 algorithm_name: CryptoAlgorithm,
6022 object: HandleObject,
6023 ) -> Fallible<Self> {
6024 match algorithm_name {
6025 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
6026 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6027 )),
6028 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
6029 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6030 )),
6031 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
6032 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6033 )),
6034 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
6035 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6036 )),
6037 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
6038 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6039 )),
6040 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
6041 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6042 )),
6043 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
6044 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6045 )),
6046 CryptoAlgorithm::Ed448 => Ok(ExportKeyAlgorithm::Ed448(
6047 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6048 )),
6049 CryptoAlgorithm::X448 => Ok(ExportKeyAlgorithm::X448(
6050 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6051 )),
6052 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
6053 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6054 )),
6055 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
6056 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6057 )),
6058 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
6059 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6060 )),
6061 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
6062 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6063 )),
6064 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
6065 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6066 )),
6067 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6068 Ok(ExportKeyAlgorithm::MlKem(
6069 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6070 ))
6071 },
6072 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6073 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6074 ),
6075 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
6076 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6077 )),
6078 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
6079 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6080 )),
6081 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ExportKeyAlgorithm::Kmac(
6082 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6083 )),
6084 _ => Err(Error::NotSupported(Some(format!(
6085 "{} does not support \"exportKey\" operation",
6086 algorithm_name.as_str()
6087 )))),
6088 }
6089 }
6090
6091 fn name(&self) -> CryptoAlgorithm {
6092 match self {
6093 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6094 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6095 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6096 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6097 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6098 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6099 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6100 ExportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6101 ExportKeyAlgorithm::X448(algorithm) => algorithm.name,
6102 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6103 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6104 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6105 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6106 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6107 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6108 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6109 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6110 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6111 ExportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6112 }
6113 }
6114}
6115
6116impl ExportKeyAlgorithm {
6117 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
6118 match self {
6119 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
6120 rsassa_pkcs1_v1_5_operation::export_key(format, key)
6121 },
6122 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
6123 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
6124 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
6125 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
6126 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
6127 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
6128 ExportKeyAlgorithm::Ed448(_algorithm) => ed448_operation::export_key(format, key),
6129 ExportKeyAlgorithm::X448(_algorithm) => x448_operation::export_key(format, key),
6130 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
6131 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
6132 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
6133 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
6134 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
6135 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
6136 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
6137 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
6138 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6139 chacha20_poly1305_operation::export_key(format, key)
6140 },
6141 ExportKeyAlgorithm::Kmac(_algorithm) => kmac_operation::export_key(format, key),
6142 }
6143 }
6144}
6145
6146struct GetKeyLengthOperation {}
6148
6149impl Operation for GetKeyLengthOperation {
6150 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
6151}
6152
6153enum GetKeyLengthAlgorithm {
6156 AesCtr(SubtleAesDerivedKeyParams),
6157 AesCbc(SubtleAesDerivedKeyParams),
6158 AesGcm(SubtleAesDerivedKeyParams),
6159 AesKw(SubtleAesDerivedKeyParams),
6160 Hmac(SubtleHmacImportParams),
6161 Hkdf(SubtleAlgorithm),
6162 Pbkdf2(SubtleAlgorithm),
6163 AesOcb(SubtleAesDerivedKeyParams),
6164 ChaCha20Poly1305(SubtleAlgorithm),
6165 Kmac(SubtleKmacImportParams),
6166 Argon2(SubtleAlgorithm),
6167}
6168
6169impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
6170 fn from_object(
6171 cx: &mut js::context::JSContext,
6172 algorithm_name: CryptoAlgorithm,
6173 object: HandleObject,
6174 ) -> Fallible<Self> {
6175 match algorithm_name {
6176 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
6177 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6178 )),
6179 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
6180 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6181 )),
6182 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
6183 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6184 )),
6185 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
6186 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6187 )),
6188 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
6189 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6190 )),
6191 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
6192 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6193 )),
6194 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
6195 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6196 )),
6197 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
6198 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6199 )),
6200 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
6201 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6202 )),
6203 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GetKeyLengthAlgorithm::Kmac(
6204 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6205 )),
6206 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
6207 Ok(GetKeyLengthAlgorithm::Argon2(
6208 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6209 ))
6210 },
6211 _ => Err(Error::NotSupported(Some(format!(
6212 "{} does not support \"get key length\" operation",
6213 algorithm_name.as_str()
6214 )))),
6215 }
6216 }
6217
6218 fn name(&self) -> CryptoAlgorithm {
6219 match self {
6220 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
6221 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
6222 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
6223 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
6224 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
6225 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
6226 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6227 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
6228 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6229 GetKeyLengthAlgorithm::Kmac(algorithm) => algorithm.name,
6230 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
6231 }
6232 }
6233}
6234
6235impl GetKeyLengthAlgorithm {
6236 fn get_key_length(&self) -> Result<Option<u32>, Error> {
6237 match self {
6238 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
6239 aes_ctr_operation::get_key_length(algorithm)
6240 },
6241 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
6242 aes_cbc_operation::get_key_length(algorithm)
6243 },
6244 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
6245 aes_gcm_operation::get_key_length(algorithm)
6246 },
6247 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
6248 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
6249 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
6250 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
6251 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
6252 aes_ocb_operation::get_key_length(algorithm)
6253 },
6254 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
6255 chacha20_poly1305_operation::get_key_length()
6256 },
6257 GetKeyLengthAlgorithm::Kmac(algorithm) => kmac_operation::get_key_length(algorithm),
6258 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
6259 }
6260 }
6261}
6262
6263struct EncapsulateOperation {}
6265
6266impl Operation for EncapsulateOperation {
6267 type RegisteredAlgorithm = EncapsulateAlgorithm;
6268}
6269
6270enum EncapsulateAlgorithm {
6273 MlKem(SubtleAlgorithm),
6274}
6275
6276impl NormalizedAlgorithm for EncapsulateAlgorithm {
6277 fn from_object(
6278 cx: &mut js::context::JSContext,
6279 algorithm_name: CryptoAlgorithm,
6280 object: HandleObject,
6281 ) -> Fallible<Self> {
6282 match algorithm_name {
6283 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6284 Ok(EncapsulateAlgorithm::MlKem(
6285 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6286 ))
6287 },
6288 _ => Err(Error::NotSupported(Some(format!(
6289 "{} does not support \"encapsulate\" operation",
6290 algorithm_name.as_str()
6291 )))),
6292 }
6293 }
6294
6295 fn name(&self) -> CryptoAlgorithm {
6296 match self {
6297 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6298 }
6299 }
6300}
6301
6302impl EncapsulateAlgorithm {
6303 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
6304 match self {
6305 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6306 }
6307 }
6308}
6309
6310struct DecapsulateOperation {}
6312
6313impl Operation for DecapsulateOperation {
6314 type RegisteredAlgorithm = DecapsulateAlgorithm;
6315}
6316
6317enum DecapsulateAlgorithm {
6320 MlKem(SubtleAlgorithm),
6321}
6322
6323impl NormalizedAlgorithm for DecapsulateAlgorithm {
6324 fn from_object(
6325 cx: &mut js::context::JSContext,
6326 algorithm_name: CryptoAlgorithm,
6327 object: HandleObject,
6328 ) -> Fallible<Self> {
6329 match algorithm_name {
6330 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6331 Ok(DecapsulateAlgorithm::MlKem(
6332 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6333 ))
6334 },
6335 _ => Err(Error::NotSupported(Some(format!(
6336 "{} does not support \"decapsulate\" operation",
6337 algorithm_name.as_str()
6338 )))),
6339 }
6340 }
6341
6342 fn name(&self) -> CryptoAlgorithm {
6343 match self {
6344 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6345 }
6346 }
6347}
6348
6349impl DecapsulateAlgorithm {
6350 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
6351 match self {
6352 DecapsulateAlgorithm::MlKem(algorithm) => {
6353 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6354 },
6355 }
6356 }
6357}
6358
6359struct GetPublicKeyOperation {}
6361
6362impl Operation for GetPublicKeyOperation {
6363 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6364}
6365
6366enum GetPublicKeyAlgorithm {
6369 RsassaPkcs1v1_5(SubtleAlgorithm),
6370 RsaPss(SubtleAlgorithm),
6371 RsaOaep(SubtleAlgorithm),
6372 Ecdsa(SubtleAlgorithm),
6373 Ecdh(SubtleAlgorithm),
6374 Ed25519(SubtleAlgorithm),
6375 X25519(SubtleAlgorithm),
6376 Ed448(SubtleAlgorithm),
6377 X448(SubtleAlgorithm),
6378 MlKem(SubtleAlgorithm),
6379 MlDsa(SubtleAlgorithm),
6380}
6381
6382impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6383 fn from_object(
6384 cx: &mut js::context::JSContext,
6385 algorithm_name: CryptoAlgorithm,
6386 object: HandleObject,
6387 ) -> Fallible<Self> {
6388 match algorithm_name {
6389 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6390 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6391 )),
6392 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6393 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6394 )),
6395 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6396 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6397 )),
6398 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6399 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6400 )),
6401 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6402 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6403 )),
6404 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6405 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6406 )),
6407 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6408 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6409 )),
6410 CryptoAlgorithm::Ed448 => Ok(GetPublicKeyAlgorithm::Ed448(
6411 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6412 )),
6413 CryptoAlgorithm::X448 => Ok(GetPublicKeyAlgorithm::X448(
6414 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6415 )),
6416 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6417 Ok(GetPublicKeyAlgorithm::MlKem(
6418 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6419 ))
6420 },
6421 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6422 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6423 ),
6424 _ => Err(Error::NotSupported(Some(format!(
6425 "{} does not support \"getPublicKey\" operation",
6426 algorithm_name.as_str()
6427 )))),
6428 }
6429 }
6430
6431 fn name(&self) -> CryptoAlgorithm {
6432 match self {
6433 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6434 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6435 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6436 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6437 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6438 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6439 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6440 GetPublicKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6441 GetPublicKeyAlgorithm::X448(algorithm) => algorithm.name,
6442 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6443 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6444 }
6445 }
6446}
6447
6448impl GetPublicKeyAlgorithm {
6449 fn get_public_key(
6450 &self,
6451 cx: &mut js::context::JSContext,
6452 global: &GlobalScope,
6453 key: &CryptoKey,
6454 algorithm: &KeyAlgorithmAndDerivatives,
6455 usages: Vec<KeyUsage>,
6456 ) -> Result<DomRoot<CryptoKey>, Error> {
6457 match self {
6458 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6459 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6460 },
6461 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6462 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6463 },
6464 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6465 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6466 },
6467 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6468 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6469 },
6470 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6471 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6472 },
6473 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6474 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6475 },
6476 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6477 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6478 },
6479 GetPublicKeyAlgorithm::Ed448(_algorithm) => {
6480 ed448_operation::get_public_key(cx, global, key, algorithm, usages)
6481 },
6482 GetPublicKeyAlgorithm::X448(_algorithm) => {
6483 x448_operation::get_public_key(cx, global, key, algorithm, usages)
6484 },
6485 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6486 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6487 },
6488 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6489 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6490 },
6491 }
6492 }
6493}