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::{ObjectOrNullValue, UndefinedValue};
46use js::realm::CurrentRealm;
47use js::rust::wrappers2::{JS_NewObject, 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 Algorithm, AlgorithmIdentifier, EncapsulatedBits, EncapsulatedKey, JsonWebKey, KeyFormat,
67 SubtleCryptoMethods,
68};
69use crate::dom::bindings::codegen::UnionTypes::{
70 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey, ObjectOrString,
71};
72use crate::dom::bindings::conversions::{
73 StringificationBehavior, ToJSValConvertible, get_property,
74};
75use crate::dom::bindings::error::{Error, Fallible};
76use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
77use crate::dom::bindings::reflector::DomGlobal;
78use crate::dom::bindings::root::DomRoot;
79use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
80use crate::dom::bindings::trace::RootedTraceableBox;
81use crate::dom::bindings::utils::set_dictionary_property;
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]
200pub(crate) struct SubtleCrypto {
201 reflector_: Reflector,
202}
203
204impl SubtleCrypto {
205 fn new_inherited() -> SubtleCrypto {
206 SubtleCrypto {
207 reflector_: Reflector::new(),
208 }
209 }
210
211 pub(crate) fn new(
212 cx: &mut js::context::JSContext,
213 global: &GlobalScope,
214 ) -> DomRoot<SubtleCrypto> {
215 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
216 }
217
218 fn resolve_promise_with_data(&self, promise: Rc<Promise>, data: Zeroizing<Vec<u8>>) {
222 let trusted_promise = TrustedPromise::new(promise);
223 self.global()
224 .task_manager()
225 .crypto_task_source()
226 .queue(task!(resolve_data: move |cx| {
227 let promise = trusted_promise.root();
228
229 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
230 match create_buffer_source::<ArrayBufferU8>(cx,
231 &data,
232 array_buffer_ptr.handle_mut(),
233 ) {
234 Ok(_) => promise.resolve_native(cx, &*array_buffer_ptr),
235 Err(_) => promise.reject_error(cx, Error::JSFailed),
236 }
237 }));
238 }
239
240 fn resolve_promise_with_jwk(
244 &self,
245 cx: &mut js::context::JSContext,
246 promise: Rc<Promise>,
247 jwk: Box<JsonWebKey>,
248 ) {
249 let stringified_jwk = match jwk.stringify(cx) {
252 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
253 Err(error) => {
254 self.reject_promise_with_error(promise, error);
255 return;
256 },
257 };
258
259 let trusted_subtle = Trusted::new(self);
260 let trusted_promise = TrustedPromise::new(promise);
261 self.global()
262 .task_manager()
263 .crypto_task_source()
264 .queue(task!(resolve_jwk: move |cx| {
265 let subtle = trusted_subtle.root();
266 let promise = trusted_promise.root();
267
268 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
269 Ok(jwk) => {
270 rooted!(&in(cx) let mut rval = UndefinedValue());
271 jwk.safe_to_jsval(cx, rval.handle_mut());
272 rooted!(&in(cx) let mut object = rval.to_object());
273 promise.resolve_native(cx, &*object);
274 },
275 Err(error) => {
276 subtle.reject_promise_with_error(promise, error);
277 return;
278 },
279 }
280 }));
281 }
282
283 fn resolve_promise_with_key(&self, promise: Rc<Promise>, key: &CryptoKey) {
286 let trusted_key = Trusted::new(key);
287 let trusted_promise = TrustedPromise::new(promise);
288 self.global()
289 .task_manager()
290 .crypto_task_source()
291 .queue(task!(resolve_key: move |cx| {
292 let key = trusted_key.root();
293 let promise = trusted_promise.root();
294 promise.resolve_native(cx, &key);
295 }));
296 }
297
298 fn resolve_promise_with_key_pair(&self, promise: Rc<Promise>, key_pair: CryptoKeyPair) {
301 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
302 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
303 let trusted_promise = TrustedPromise::new(promise);
304 self.global()
305 .task_manager()
306 .crypto_task_source()
307 .queue(task!(resolve_key: move |cx| {
308 let key_pair = CryptoKeyPair {
309 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
310 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
311 };
312 let promise = trusted_promise.root();
313 promise.resolve_native(cx, &key_pair);
314 }));
315 }
316
317 fn resolve_promise_with_bool(&self, promise: Rc<Promise>, result: bool) {
320 let trusted_promise = TrustedPromise::new(promise);
321 self.global()
322 .task_manager()
323 .crypto_task_source()
324 .queue(task!(resolve_bool: move |cx| {
325 let promise = trusted_promise.root();
326 promise.resolve_native(cx, &result);
327 }));
328 }
329
330 fn reject_promise_with_error(&self, promise: Rc<Promise>, error: Error) {
333 let trusted_promise = TrustedPromise::new(promise);
334 self.global()
335 .task_manager()
336 .crypto_task_source()
337 .queue(task!(reject_error: move |cx| {
338 let promise = trusted_promise.root();
339 promise.reject_error(cx, error);
340 }));
341 }
342
343 fn resolve_promise_with_encapsulated_key(
347 &self,
348 promise: Rc<Promise>,
349 encapsulated_key: SubtleEncapsulatedKey,
350 ) {
351 let trusted_promise = TrustedPromise::new(promise);
352 self.global().task_manager().crypto_task_source().queue(
353 task!(resolve_encapsulated_key: move |cx| {
354 let promise = trusted_promise.root();
355 promise.resolve_native(cx, &encapsulated_key);
356 }),
357 );
358 }
359
360 fn resolve_promise_with_encapsulated_bits(
364 &self,
365 promise: Rc<Promise>,
366 encapsulated_bits: SubtleEncapsulatedBits,
367 ) {
368 let trusted_promise = TrustedPromise::new(promise);
369 self.global().task_manager().crypto_task_source().queue(
370 task!(resolve_encapsulated_bits: move |cx| {
371 let promise = trusted_promise.root();
372 promise.resolve_native(cx, &encapsulated_bits);
373 }),
374 );
375 }
376}
377
378impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
379 fn Encrypt(
381 &self,
382 cx: &mut CurrentRealm,
383 algorithm: AlgorithmIdentifier,
384 key: &CryptoKey,
385 data: ArrayBufferViewOrArrayBuffer,
386 ) -> Rc<Promise> {
387 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
395 Ok(normalized_algorithm) => normalized_algorithm,
396 Err(error) => {
397 let promise = Promise::new_in_realm(cx);
398 promise.reject_error(cx, error);
399 return promise;
400 },
401 };
402
403 let data = Zeroizing::new(get_buffer_source_copy((&data).into()));
406
407 let promise = Promise::new_in_realm(cx);
410
411 let this = Trusted::new(self);
413 let trusted_promise = TrustedPromise::new(promise.clone());
414 let trusted_key = Trusted::new(key);
415 self.global()
416 .task_manager()
417 .dom_manipulation_task_source()
418 .queue(task!(encrypt: move || {
419 let subtle = this.root();
420 let promise = trusted_promise.root();
421 let key = trusted_key.root();
422
423 if normalized_algorithm.name() != key.algorithm().name() {
431 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Algorithm's name does not equal key algorithm name".into())));
432 return;
433 }
434
435 if !key.usages().contains(&KeyUsage::Encrypt) {
438 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'encrypt' entry".into())));
439 return;
440 }
441
442 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
446 Ok(ciphertext) => ciphertext,
447 Err(error) => {
448 subtle.reject_promise_with_error(promise, error);
449 return;
450 },
451 };
452
453 subtle.resolve_promise_with_data(promise, ciphertext.into());
459 }));
460 promise
461 }
462
463 fn Decrypt(
465 &self,
466 cx: &mut CurrentRealm,
467 algorithm: AlgorithmIdentifier,
468 key: &CryptoKey,
469 data: ArrayBufferViewOrArrayBuffer,
470 ) -> Rc<Promise> {
471 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
479 Ok(normalized_algorithm) => normalized_algorithm,
480 Err(error) => {
481 let promise = Promise::new_in_realm(cx);
482 promise.reject_error(cx, error);
483 return promise;
484 },
485 };
486
487 let data = get_buffer_source_copy((&data).into());
490
491 let promise = Promise::new_in_realm(cx);
494
495 let this = Trusted::new(self);
497 let trusted_promise = TrustedPromise::new(promise.clone());
498 let trusted_key = Trusted::new(key);
499 self.global()
500 .task_manager()
501 .dom_manipulation_task_source()
502 .queue(task!(decrypt: move || {
503 let subtle = this.root();
504 let promise = trusted_promise.root();
505 let key = trusted_key.root();
506
507 if normalized_algorithm.name() != key.algorithm().name() {
515 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
516 return;
517 }
518
519 if !key.usages().contains(&KeyUsage::Decrypt) {
522 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'decrypt' entry".into())));
523 return;
524 }
525
526 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
530 Ok(plaintext) => Zeroizing::new(plaintext),
531 Err(error) => {
532 subtle.reject_promise_with_error(promise, error);
533 return;
534 },
535 };
536
537 subtle.resolve_promise_with_data(promise, plaintext);
543 }));
544 promise
545 }
546
547 fn Sign(
549 &self,
550 cx: &mut CurrentRealm,
551 algorithm: AlgorithmIdentifier,
552 key: &CryptoKey,
553 data: ArrayBufferViewOrArrayBuffer,
554 ) -> Rc<Promise> {
555 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
563 Ok(normalized_algorithm) => normalized_algorithm,
564 Err(error) => {
565 let promise = Promise::new_in_realm(cx);
566 promise.reject_error(cx, error);
567 return promise;
568 },
569 };
570
571 let data = get_buffer_source_copy((&data).into());
574
575 let promise = Promise::new_in_realm(cx);
578
579 let this = Trusted::new(self);
581 let trusted_promise = TrustedPromise::new(promise.clone());
582 let trusted_key = Trusted::new(key);
583 self.global()
584 .task_manager()
585 .dom_manipulation_task_source()
586 .queue(task!(sign: move || {
587 let subtle = this.root();
588 let promise = trusted_promise.root();
589 let key = trusted_key.root();
590
591 if normalized_algorithm.name() != key.algorithm().name() {
599 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
600 return;
601 }
602
603 if !key.usages().contains(&KeyUsage::Sign) {
606 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'sign' entry".into())));
607 return;
608 }
609
610 let signature = match normalized_algorithm.sign(&key, &data) {
613 Ok(signature) => signature,
614 Err(error) => {
615 subtle.reject_promise_with_error(promise, error);
616 return;
617 },
618 };
619
620 subtle.resolve_promise_with_data(promise, signature.into());
626 }));
627 promise
628 }
629
630 fn Verify(
632 &self,
633 cx: &mut CurrentRealm,
634 algorithm: AlgorithmIdentifier,
635 key: &CryptoKey,
636 signature: ArrayBufferViewOrArrayBuffer,
637 data: ArrayBufferViewOrArrayBuffer,
638 ) -> Rc<Promise> {
639 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
647 Ok(algorithm) => algorithm,
648 Err(error) => {
649 let promise = Promise::new_in_realm(cx);
650 promise.reject_error(cx, error);
651 return promise;
652 },
653 };
654
655 let signature = get_buffer_source_copy((&signature).into());
658
659 let data = get_buffer_source_copy((&data).into());
662
663 let promise = Promise::new_in_realm(cx);
666
667 let this = Trusted::new(self);
669 let trusted_promise = TrustedPromise::new(promise.clone());
670 let trusted_key = Trusted::new(key);
671 self.global()
672 .task_manager()
673 .dom_manipulation_task_source()
674 .queue(task!(sign: move || {
675 let subtle = this.root();
676 let promise = trusted_promise.root();
677 let key = trusted_key.root();
678
679 if normalized_algorithm.name() != key.algorithm().name() {
687 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
688 return;
689 }
690
691 if !key.usages().contains(&KeyUsage::Verify) {
694 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'verify' entry".into())));
695 return;
696 }
697
698 let result = match normalized_algorithm.verify(&key, &data, &signature) {
702 Ok(result) => result,
703 Err(error) => {
704 subtle.reject_promise_with_error(promise, error);
705 return;
706 },
707 };
708
709 subtle.resolve_promise_with_bool(promise, result);
713 }));
714 promise
715 }
716
717 fn Digest(
719 &self,
720 cx: &mut CurrentRealm,
721 algorithm: AlgorithmIdentifier,
722 data: ArrayBufferViewOrArrayBuffer,
723 ) -> Rc<Promise> {
724 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
731 Ok(normalized_algorithm) => normalized_algorithm,
732 Err(error) => {
733 let promise = Promise::new_in_realm(cx);
734 promise.reject_error(cx, error);
735 return promise;
736 },
737 };
738
739 let data = get_buffer_source_copy((&data).into());
742
743 let promise = Promise::new_in_realm(cx);
746
747 let this = Trusted::new(self);
749 let trusted_promise = TrustedPromise::new(promise.clone());
750 self.global()
751 .task_manager()
752 .dom_manipulation_task_source()
753 .queue(task!(digest_: move || {
754 let subtle = this.root();
755 let promise = trusted_promise.root();
756
757 let digest = match normalized_algorithm.digest(&data) {
764 Ok(digest) => digest,
765 Err(error) => {
766 subtle.reject_promise_with_error(promise, error);
767 return;
768 }
769 };
770
771 subtle.resolve_promise_with_data(promise, digest.into());
777 }));
778 promise
779 }
780
781 fn GenerateKey(
783 &self,
784 cx: &mut CurrentRealm,
785 algorithm: AlgorithmIdentifier,
786 extractable: bool,
787 key_usages: Vec<KeyUsage>,
788 ) -> Rc<Promise> {
789 let promise = Promise::new_in_realm(cx);
796 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
797 {
798 Ok(normalized_algorithm) => normalized_algorithm,
799 Err(error) => {
800 promise.reject_error(cx, error);
801 return promise;
802 },
803 };
804
805 let trusted_subtle = Trusted::new(self);
811 let trusted_promise = TrustedPromise::new(promise.clone());
812 self.global()
813 .task_manager()
814 .dom_manipulation_task_source()
815 .queue(task!(generate_key: move |cx| {
816 let subtle = trusted_subtle.root();
817 let promise = trusted_promise.root();
818
819 let result = match normalized_algorithm.generate_key(
826 cx,
827 &subtle.global(),
828 extractable,
829 key_usages,
830 ) {
831 Ok(result) => result,
832 Err(error) => {
833 subtle.reject_promise_with_error(promise, error);
834 return;
835 }
836 };
837
838 match &result {
846 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
847 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
848 && crpyto_key.usages().is_empty()
849 {
850 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Crypto key usages is empty".into())));
851 return;
852 }
853 },
854 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
855 if crypto_key_pair
856 .privateKey
857 .as_ref()
858 .is_none_or(|private_key| private_key.usages().is_empty())
859 {
860 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Private key usages is an empty sequence".into())));
861 return;
862 }
863 }
864 };
865
866 match result {
872 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
873 subtle.resolve_promise_with_key(promise, &key);
874 },
875 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
876 subtle.resolve_promise_with_key_pair(promise, key_pair);
877 },
878 }
879 }));
880
881 promise
882 }
883
884 fn DeriveKey(
886 &self,
887 cx: &mut CurrentRealm,
888 algorithm: AlgorithmIdentifier,
889 base_key: &CryptoKey,
890 derived_key_type: AlgorithmIdentifier,
891 extractable: bool,
892 usages: Vec<KeyUsage>,
893 ) -> Rc<Promise> {
894 let promise = Promise::new_in_realm(cx);
903 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
904 {
905 Ok(normalized_algorithm) => normalized_algorithm,
906 Err(error) => {
907 promise.reject_error(cx, error);
908 return promise;
909 },
910 };
911
912 let normalized_derived_key_algorithm_import =
917 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
918 Ok(normalized_algorithm) => normalized_algorithm,
919 Err(error) => {
920 promise.reject_error(cx, error);
921 return promise;
922 },
923 };
924
925 let normalized_derived_key_algorithm_length =
930 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
931 Ok(normalized_algorithm) => normalized_algorithm,
932 Err(error) => {
933 promise.reject_error(cx, error);
934 return promise;
935 },
936 };
937
938 let trusted_subtle = Trusted::new(self);
944 let trusted_base_key = Trusted::new(base_key);
945 let trusted_promise = TrustedPromise::new(promise.clone());
946 self.global().task_manager().dom_manipulation_task_source().queue(
947 task!(derive_key: move |cx| {
948 let subtle = trusted_subtle.root();
949 let base_key = trusted_base_key.root();
950 let promise = trusted_promise.root();
951
952 if normalized_algorithm.name() != base_key.algorithm().name() {
960 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
961 return;
962 }
963
964 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
967 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveKey' entry".into())));
968 return;
969 }
970
971 let length = match normalized_derived_key_algorithm_length.get_key_length() {
974 Ok(length) => length,
975 Err(error) => {
976 subtle.reject_promise_with_error(promise, error);
977 return;
978 }
979 };
980
981 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
984 Ok(secret) => Zeroizing::new(secret),
985 Err(error) => {
986 subtle.reject_promise_with_error(promise, error);
987 return;
988 }
989 };
990
991 let result = match normalized_derived_key_algorithm_import.import_key(
997 cx,
998 &subtle.global(),
999 KeyFormat::Raw_secret,
1000 &secret,
1001 extractable,
1002 usages.clone(),
1003 ) {
1004 Ok(algorithm) => algorithm,
1005 Err(error) => {
1006 subtle.reject_promise_with_error(promise, error);
1007 return;
1008 },
1009 };
1010
1011 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1014 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1015 return;
1016 }
1017
1018 subtle.resolve_promise_with_key(promise, &result);
1029 }),
1030 );
1031 promise
1032 }
1033
1034 fn DeriveBits(
1036 &self,
1037 cx: &mut CurrentRealm,
1038 algorithm: AlgorithmIdentifier,
1039 base_key: &CryptoKey,
1040 length: Option<u32>,
1041 ) -> Rc<Promise> {
1042 let promise = Promise::new_in_realm(cx);
1050 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1051 {
1052 Ok(normalized_algorithm) => normalized_algorithm,
1053 Err(error) => {
1054 promise.reject_error(cx, error);
1055 return promise;
1056 },
1057 };
1058
1059 let trsuted_subtle = Trusted::new(self);
1065 let trusted_base_key = Trusted::new(base_key);
1066 let trusted_promise = TrustedPromise::new(promise.clone());
1067 self.global()
1068 .task_manager()
1069 .dom_manipulation_task_source()
1070 .queue(task!(import_key: move || {
1071 let subtle = trsuted_subtle.root();
1072 let base_key = trusted_base_key.root();
1073 let promise = trusted_promise.root();
1074
1075 if normalized_algorithm.name() != base_key.algorithm().name() {
1083 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
1084 return;
1085 }
1086
1087 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1090 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveBits' entry".into())));
1091 return;
1092 }
1093
1094 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1097 Ok(bits) => Zeroizing::new(bits),
1098 Err(error) => {
1099 subtle.reject_promise_with_error(promise, error);
1100 return;
1101 }
1102 };
1103
1104 subtle.resolve_promise_with_data(promise, bits);
1110 }));
1111 promise
1112 }
1113
1114 fn ImportKey(
1116 &self,
1117 cx: &mut CurrentRealm,
1118 format: KeyFormat,
1119 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1120 algorithm: AlgorithmIdentifier,
1121 extractable: bool,
1122 key_usages: Vec<KeyUsage>,
1123 ) -> Rc<Promise> {
1124 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1131 Ok(algorithm) => algorithm,
1132 Err(error) => {
1133 let promise = Promise::new_in_realm(cx);
1134 promise.reject_error(cx, error);
1135 return promise;
1136 },
1137 };
1138
1139 let key_data = match format {
1141 KeyFormat::Jwk => {
1143 match key_data {
1144 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1145 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1146 let promise = Promise::new_in_realm(cx);
1149 promise.reject_error(
1150 cx,
1151 Error::Type(c"The keyData type does not match the format".to_owned()),
1152 );
1153 return promise;
1154 },
1155
1156 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1157 match jwk.stringify(cx) {
1165 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1166 Err(error) => {
1167 let promise = Promise::new_in_realm(cx);
1168 promise.reject_error(cx, error);
1169 return promise;
1170 },
1171 }
1172 },
1173 }
1174 },
1175 _ => {
1177 match &key_data {
1178 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1181 let promise = Promise::new_in_realm(cx);
1182 promise.reject_error(
1183 cx,
1184 Error::Type(c"The keyData type does not match the format".to_owned()),
1185 );
1186 return promise;
1187 },
1188
1189 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1192 Zeroizing::new(get_buffer_source_copy(view.into()))
1193 },
1194 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1195 Zeroizing::new(get_buffer_source_copy(buffer.into()))
1196 },
1197 }
1198 },
1199 };
1200
1201 let promise = Promise::new_in_realm(cx);
1204
1205 let this = Trusted::new(self);
1207 let trusted_promise = TrustedPromise::new(promise.clone());
1208 self.global()
1209 .task_manager()
1210 .dom_manipulation_task_source()
1211 .queue(task!(import_key: move |cx| {
1212 let subtle = this.root();
1213 let promise = trusted_promise.root();
1214
1215 let result = match normalized_algorithm.import_key(
1223 cx,
1224 &subtle.global(),
1225 format,
1226 &key_data,
1227 extractable,
1228 key_usages.clone(),
1229 ) {
1230 Ok(key) => key,
1231 Err(error) => {
1232 subtle.reject_promise_with_error(promise, error);
1233 return;
1234 },
1235 };
1236
1237 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1240 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1241 return;
1242 }
1243
1244 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 {
1807 Some(shared_key) => shared_key,
1808 None => {
1809 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1810 "Shared key is missing in the result of the encapsulate operation"
1811 .to_string())));
1812 return;
1813 },
1814 };
1815 let shared_key_result = normalized_shared_key_algorithm.import_key(
1816 cx,
1817 &subtle.global(),
1818 KeyFormat::Raw_secret,
1819 encapsulated_shared_key,
1820 extractable,
1821 usages.clone(),
1822 );
1823 let shared_key = match shared_key_result {
1824 Ok(shared_key) => shared_key,
1825 Err(error) => {
1826 subtle.reject_promise_with_error(promise, error);
1827 return;
1828 },
1829 };
1830
1831 let encapsulated_key = SubtleEncapsulatedKey {
1834 shared_key: Some(Trusted::new(&shared_key)),
1835 ciphertext:encapsulated_bits.ciphertext,
1836 };
1837
1838 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1844 })
1845 );
1846 promise
1847 }
1848
1849 fn EncapsulateBits(
1851 &self,
1852 cx: &mut CurrentRealm,
1853 encapsulation_algorithm: AlgorithmIdentifier,
1854 encapsulation_key: &CryptoKey,
1855 ) -> Rc<Promise> {
1856 let promise = Promise::new_in_realm(cx);
1864 let normalized_encapsulation_algorithm =
1865 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1866 Ok(algorithm) => algorithm,
1867 Err(error) => {
1868 promise.reject_error(cx, error);
1869 return promise;
1870 },
1871 };
1872
1873 let trusted_subtle = Trusted::new(self);
1879 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1880 let trusted_promise = TrustedPromise::new(promise.clone());
1881 self.global().task_manager().dom_manipulation_task_source().queue(
1882 task!(derive_key: move || {
1883 let subtle = trusted_subtle.root();
1884 let encapsulation_key = trusted_encapsulation_key.root();
1885 let promise = trusted_promise.root();
1886
1887 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1895 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1896 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1897 normalizedEncapsulationAlgorithm".to_string(),
1898 )));
1899 return;
1900 }
1901
1902 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1905 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1906 "[[usages]] internal slot of encapsulationKey does not contain an \
1907 entry that is \"encapsulateBits\"".to_string(),
1908 )));
1909 return;
1910 }
1911
1912 let encapsulated_bits =
1918 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1919 Ok(encapsulated_bits) => encapsulated_bits,
1920 Err(error) => {
1921 subtle.reject_promise_with_error(promise, error);
1922 return;
1923 },
1924 };
1925
1926 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1932 }),
1933 );
1934 promise
1935 }
1936
1937 fn DecapsulateKey(
1939 &self,
1940 cx: &mut CurrentRealm,
1941 decapsulation_algorithm: AlgorithmIdentifier,
1942 decapsulation_key: &CryptoKey,
1943 ciphertext: ArrayBufferViewOrArrayBuffer,
1944 shared_key_algorithm: AlgorithmIdentifier,
1945 extractable: bool,
1946 usages: Vec<KeyUsage>,
1947 ) -> Rc<Promise> {
1948 let normalized_decapsulation_algorithm =
1958 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
1959 Ok(normalized_algorithm) => normalized_algorithm,
1960 Err(error) => {
1961 let promise = Promise::new_in_realm(cx);
1962 promise.reject_error(cx, error);
1963 return promise;
1964 },
1965 };
1966
1967 let normalized_shared_key_algorithm =
1972 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1973 Ok(normalized_algorithm) => normalized_algorithm,
1974 Err(error) => {
1975 let promise = Promise::new_in_realm(cx);
1976 promise.reject_error(cx, error);
1977 return promise;
1978 },
1979 };
1980
1981 let ciphertext = get_buffer_source_copy((&ciphertext).into());
1984
1985 let promise = Promise::new_in_realm(cx);
1988
1989 let trusted_subtle = Trusted::new(self);
1991 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
1992 let trusted_promise = TrustedPromise::new(promise.clone());
1993 self.global()
1994 .task_manager()
1995 .dom_manipulation_task_source()
1996 .queue(task!(decapsulate_key: move |cx| {
1997 let subtle = trusted_subtle.root();
1998 let promise = trusted_promise.root();
1999 let decapsulation_key = trusted_decapsulation_key.root();
2000
2001 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2009 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2010 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2011 normalizedDecapsulationAlgorithm".to_string()
2012 )));
2013 return;
2014 }
2015
2016 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2019 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2020 "[[usages]] internal slot of decapsulationKey does not contain an \
2021 entry that is \"decapsulateBits\"".to_string(),
2022 )));
2023 return;
2024 }
2025
2026 let decapsulated_bits_result =
2032 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2033 let decapsulated_bits = match decapsulated_bits_result {
2034 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2035 Err(error) => {
2036 subtle.reject_promise_with_error(promise, error);
2037 return;
2038 },
2039 };
2040
2041
2042 let shared_key_result = normalized_shared_key_algorithm.import_key(
2051 cx,
2052 &subtle.global(),
2053 KeyFormat::Raw_secret,
2054 &decapsulated_bits,
2055 extractable,
2056 usages.clone(),
2057 );
2058 let shared_key = match shared_key_result {
2059 Ok(shared_key) => shared_key,
2060 Err(error) => {
2061 subtle.reject_promise_with_error(promise, error);
2062 return;
2063 },
2064 };
2065
2066 subtle.resolve_promise_with_key(promise, &shared_key);
2072 }));
2073 promise
2074 }
2075
2076 fn DecapsulateBits(
2078 &self,
2079 cx: &mut CurrentRealm,
2080 decapsulation_algorithm: AlgorithmIdentifier,
2081 decapsulation_key: &CryptoKey,
2082 ciphertext: ArrayBufferViewOrArrayBuffer,
2083 ) -> Rc<Promise> {
2084 let normalized_decapsulation_algorithm =
2092 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2093 Ok(normalized_algorithm) => normalized_algorithm,
2094 Err(error) => {
2095 let promise = Promise::new_in_realm(cx);
2096 promise.reject_error(cx, error);
2097 return promise;
2098 },
2099 };
2100
2101 let ciphertext = get_buffer_source_copy((&ciphertext).into());
2104
2105 let promise = Promise::new_in_realm(cx);
2108
2109 let trusted_subtle = Trusted::new(self);
2111 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2112 let trusted_promise = TrustedPromise::new(promise.clone());
2113 self.global()
2114 .task_manager()
2115 .dom_manipulation_task_source()
2116 .queue(task!(decapsulate_bits: move || {
2117 let subtle = trusted_subtle.root();
2118 let promise = trusted_promise.root();
2119 let decapsulation_key = trusted_decapsulation_key.root();
2120
2121 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2129 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2130 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2131 normalizedDecapsulationAlgorithm".to_string()
2132 )));
2133 return;
2134 }
2135
2136 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2139 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2140 "[[usages]] internal slot of decapsulationKey does not contain an \
2141 entry that is \"decapsulateBits\"".to_string(),
2142 )));
2143 return;
2144 }
2145
2146 let decapsulated_bits_result =
2152 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2153 let decapsulated_bits = match decapsulated_bits_result {
2154 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2155 Err(error) => {
2156 subtle.reject_promise_with_error(promise, error);
2157 return;
2158 },
2159 };
2160
2161 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2167 }));
2168 promise
2169 }
2170
2171 fn GetPublicKey(
2173 &self,
2174 cx: &mut CurrentRealm,
2175 key: &CryptoKey,
2176 usages: Vec<KeyUsage>,
2177 ) -> Rc<Promise> {
2178 let algorithm = key.algorithm();
2183
2184 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2191 cx,
2192 &AlgorithmIdentifier::String(DOMString::from(algorithm.name().as_str())),
2193 ) {
2194 Ok(normalized_algorithm) => normalized_algorithm,
2195 Err(error) => {
2196 let promise = Promise::new_in_realm(cx);
2197 promise.reject_error(cx, error);
2198 return promise;
2199 },
2200 };
2201
2202 let promise = Promise::new_in_realm(cx);
2205
2206 let trusted_subtle = Trusted::new(self);
2208 let trusted_promise = TrustedPromise::new(promise.clone());
2209 let trusted_key = Trusted::new(key);
2210 self.global()
2211 .task_manager()
2212 .dom_manipulation_task_source()
2213 .queue(task!(get_public_key: move |cx| {
2214 let subtle = trusted_subtle.root();
2215 let promise = trusted_promise.root();
2216 let key = trusted_key.root();
2217
2218 if key.Type() != KeyType::Private {
2225 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2226 "[[type]] internal slot of key is not \"private\"".to_string()
2227 )));
2228 return;
2229 }
2230
2231 let result = match get_public_key_algorithm.get_public_key(
2245 cx,
2246 &subtle.global(),
2247 &key,
2248 key.algorithm(),
2249 usages.clone(),
2250 ) {
2251 Ok(public_key) => public_key,
2252 Err(error) => {
2253 subtle.reject_promise_with_error(promise, error);
2254 return;
2255 },
2256 };
2257
2258 subtle.resolve_promise_with_key(promise, &result);
2264 }));
2265 promise
2266 }
2267
2268 fn Supports(
2270 cx: &mut js::context::JSContext,
2271 _global: &GlobalScope,
2272 operation: DOMString,
2273 algorithm: AlgorithmIdentifier,
2274 length: Option<u32>,
2275 ) -> bool {
2276 let operation = &*operation.str();
2281 if !matches!(
2282 operation,
2283 "encrypt" |
2284 "decrypt" |
2285 "sign" |
2286 "verify" |
2287 "digest" |
2288 "generateKey" |
2289 "deriveKey" |
2290 "deriveBits" |
2291 "importKey" |
2292 "exportKey" |
2293 "wrapKey" |
2294 "unwrapKey" |
2295 "encapsulateKey" |
2296 "encapsulateBits" |
2297 "decapsulateKey" |
2298 "decapsulateBits" |
2299 "getPublicKey"
2300 ) {
2301 return false;
2302 }
2303
2304 check_support_for_algorithm(cx, operation, &algorithm, length)
2307 }
2308
2309 fn Supports_(
2311 cx: &mut js::context::JSContext,
2312 _global: &GlobalScope,
2313 operation: DOMString,
2314 algorithm: AlgorithmIdentifier,
2315 additional_algorithm: AlgorithmIdentifier,
2316 ) -> bool {
2317 let mut operation = &*operation.str();
2322 if !matches!(
2323 operation,
2324 "encrypt" |
2325 "decrypt" |
2326 "sign" |
2327 "verify" |
2328 "digest" |
2329 "generateKey" |
2330 "deriveKey" |
2331 "deriveBits" |
2332 "importKey" |
2333 "exportKey" |
2334 "wrapKey" |
2335 "unwrapKey" |
2336 "encapsulateKey" |
2337 "encapsulateBits" |
2338 "decapsulateKey" |
2339 "decapsulateBits" |
2340 "getPublicKey"
2341 ) {
2342 return false;
2343 }
2344
2345 if matches!(
2353 operation,
2354 "deriveKey" | "unwrapKey" | "encapsulateKey" | "decapsulateKey"
2355 ) && !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2356 {
2357 return false;
2358 }
2359 if operation == "wrapKey" &&
2360 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2361 {
2362 return false;
2363 }
2364
2365 let mut length = None;
2367
2368 if operation == "deriveKey" {
2370 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2373 return false;
2374 }
2375
2376 let Ok(normalized_additional_algorithm) =
2379 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2380 else {
2381 return false;
2382 };
2383
2384 match normalized_additional_algorithm.get_key_length() {
2387 Ok(key_length) => {
2388 length = key_length;
2389 },
2390 Err(_) => return false,
2391 };
2392
2393 operation = "deriveBits";
2395 }
2396
2397 check_support_for_algorithm(cx, operation, &algorithm, length)
2400 }
2401}
2402
2403pub(crate) fn check_support_for_algorithm(
2405 cx: &mut js::context::JSContext,
2406 mut operation: &str,
2407 algorithm: &AlgorithmIdentifier,
2408 length: Option<u32>,
2409) -> bool {
2410 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2412 operation = "encapsulate";
2413 }
2414
2415 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2417 operation = "decapsulate";
2418 }
2419
2420 if operation == "getPublicKey" {
2422 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2426 else {
2427 return false;
2428 };
2429
2430 return normalize_algorithm::<GetPublicKeyOperation>(
2437 cx,
2438 &AlgorithmIdentifier::String(DOMString::from(normalized_algorithm.name().as_str())),
2439 )
2440 .is_ok();
2441 }
2442
2443 match operation {
2482 "encrypt" => {
2483 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2484 else {
2485 return false;
2486 };
2487
2488 match normalized_algorithm {
2489 EncryptAlgorithm::RsaOaep(_) => true,
2490 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2491 normalized_algorithm.counter.len() == 16 &&
2492 normalized_algorithm.length != 0 &&
2493 normalized_algorithm.length <= 128
2494 },
2495 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2496 normalized_algorithm.iv.len() == 16
2497 },
2498 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2499 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2500 normalized_algorithm.tag_length.is_none_or(|length| {
2501 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2502 })
2503 },
2504 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2505 normalized_algorithm.iv.len() <= 15 &&
2506 normalized_algorithm
2507 .tag_length
2508 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2509 },
2510 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2511 normalized_algorithm.iv.len() == 12 &&
2512 normalized_algorithm
2513 .tag_length
2514 .is_none_or(|length| length == 128)
2515 },
2516 }
2517 },
2518 "decrypt" => {
2519 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2520 else {
2521 return false;
2522 };
2523
2524 match normalized_algorithm {
2525 DecryptAlgorithm::RsaOaep(_) => true,
2526 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2527 normalized_algorithm.counter.len() == 16 &&
2528 normalized_algorithm.length != 0 &&
2529 normalized_algorithm.length <= 128
2530 },
2531 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2532 normalized_algorithm.iv.len() == 16
2533 },
2534 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2535 normalized_algorithm
2536 .tag_length
2537 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2538 normalized_algorithm.iv.len() <= u32::MAX as usize &&
2539 normalized_algorithm
2540 .additional_data
2541 .is_none_or(|data| data.len() <= u32::MAX as usize)
2542 },
2543 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2544 normalized_algorithm.iv.len() <= 15 &&
2545 normalized_algorithm
2546 .tag_length
2547 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2548 },
2549 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2550 normalized_algorithm.iv.len() == 12 &&
2551 normalized_algorithm
2552 .tag_length
2553 .is_none_or(|length| length == 128)
2554 },
2555 }
2556 },
2557 "sign" => {
2558 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2559 else {
2560 return false;
2561 };
2562
2563 match normalized_algorithm {
2564 SignAlgorithm::RsassaPkcs1V1_5(_) |
2565 SignAlgorithm::RsaPss(_) |
2566 SignAlgorithm::Ecdsa(_) |
2567 SignAlgorithm::Ed25519(_) => true,
2568 SignAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2569 .context
2570 .is_none_or(|context| context.len() <= 255),
2571 SignAlgorithm::Hmac(_) | SignAlgorithm::MlDsa(_) | SignAlgorithm::Kmac(_) => true,
2572 }
2573 },
2574 "verify" => {
2575 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2576 else {
2577 return false;
2578 };
2579
2580 match normalized_algorithm {
2581 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2582 VerifyAlgorithm::RsaPss(_) |
2583 VerifyAlgorithm::Ecdsa(_) |
2584 VerifyAlgorithm::Ed25519(_) => true,
2585 VerifyAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2586 .context
2587 .is_none_or(|context| context.len() <= 255),
2588 VerifyAlgorithm::Hmac(_) | VerifyAlgorithm::MlDsa(_) | VerifyAlgorithm::Kmac(_) => {
2589 true
2590 },
2591 }
2592 },
2593 "digest" => {
2594 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2595 else {
2596 return false;
2597 };
2598
2599 match normalized_algorithm {
2600 DigestAlgorithm::Sha(_) |
2601 DigestAlgorithm::Sha3(_) |
2602 DigestAlgorithm::CShake(_) |
2603 DigestAlgorithm::TurboShake(_) => true,
2604 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
2605 normalized_algorithm.output_length != 0 &&
2606 normalized_algorithm.output_length.is_multiple_of(8)
2607 },
2608 }
2609 },
2610 "deriveBits" => {
2611 let Ok(normalized_algorithm) =
2612 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2613 else {
2614 return false;
2615 };
2616
2617 match normalized_algorithm {
2618 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => length.is_none_or(|length| {
2619 ecdh_operation::secret_length(&normalized_algorithm)
2620 .is_ok_and(|secret_length| secret_length * 8 >= length)
2621 }),
2622 DeriveBitsAlgorithm::X25519(_) => {
2623 length.is_none_or(|length| x25519_operation::SECRET_LENGTH as u32 * 8 >= length)
2624 },
2625 DeriveBitsAlgorithm::X448(_) => {
2626 length.is_none_or(|length| x448_operation::SECRET_LENGTH as u32 * 8 >= length)
2627 },
2628 DeriveBitsAlgorithm::Hkdf(_) => length.is_some_and(|length| length % 8 == 0),
2629 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2630 length.is_some_and(|length| length % 8 == 0) &&
2631 normalized_algorithm.iterations != 0
2632 },
2633 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2634 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2635 normalized_algorithm
2636 .version
2637 .is_none_or(|version| version == 19) &&
2638 normalized_algorithm.parallelism != 0 &&
2639 normalized_algorithm.parallelism <= 16777215 &&
2640 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2641 normalized_algorithm.passes != 0
2642 },
2643 }
2644 },
2645 "wrapKey" => {
2646 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2647 else {
2648 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2649 };
2650
2651 match normalized_algorithm {
2652 WrapKeyAlgorithm::AesKw(_) => true,
2653 }
2654 },
2655 "unwrapKey" => {
2656 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2657 else {
2658 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2659 };
2660
2661 match normalized_algorithm {
2662 UnwrapKeyAlgorithm::AesKw(_) => true,
2663 }
2664 },
2665 "generateKey" => {
2666 let Ok(normalized_algorithm) =
2667 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2668 else {
2669 return false;
2670 };
2671
2672 match normalized_algorithm {
2673 GenerateKeyAlgorithm::RsassaPkcs1V1_5(_) |
2674 GenerateKeyAlgorithm::RsaPss(_) |
2675 GenerateKeyAlgorithm::RsaOaep(_) => true,
2676 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2677 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2678 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2679 },
2680 GenerateKeyAlgorithm::Ed25519(_) |
2681 GenerateKeyAlgorithm::X25519(_) |
2682 GenerateKeyAlgorithm::Ed448(_) |
2683 GenerateKeyAlgorithm::X448(_) => true,
2684 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2685 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2686 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2687 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2688 matches!(normalized_algorithm.length, 128 | 192 | 256)
2689 },
2690 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2691 normalized_algorithm.length.is_none_or(|length| length != 0)
2692 },
2693 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2694 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2695 matches!(normalized_algorithm.length, 128 | 192 | 256)
2696 },
2697 GenerateKeyAlgorithm::ChaCha20Poly1305(_) | GenerateKeyAlgorithm::Kmac(_) => true,
2698 }
2699 },
2700 "importKey" => {
2701 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2702 else {
2703 return false;
2704 };
2705
2706 match normalized_algorithm {
2707 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2708 ImportKeyAlgorithm::RsaPss(_) |
2709 ImportKeyAlgorithm::RsaOaep(_) |
2710 ImportKeyAlgorithm::Ecdsa(_) |
2711 ImportKeyAlgorithm::Ecdh(_) |
2712 ImportKeyAlgorithm::Ed25519(_) |
2713 ImportKeyAlgorithm::X25519(_) |
2714 ImportKeyAlgorithm::Ed448(_) |
2715 ImportKeyAlgorithm::X448(_) |
2716 ImportKeyAlgorithm::AesCtr(_) |
2717 ImportKeyAlgorithm::AesCbc(_) |
2718 ImportKeyAlgorithm::AesGcm(_) |
2719 ImportKeyAlgorithm::AesKw(_) |
2720 ImportKeyAlgorithm::Hmac(_) |
2721 ImportKeyAlgorithm::Hkdf(_) |
2722 ImportKeyAlgorithm::Pbkdf2(_) |
2723 ImportKeyAlgorithm::MlKem(_) |
2724 ImportKeyAlgorithm::MlDsa(_) |
2725 ImportKeyAlgorithm::AesOcb(_) |
2726 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2727 ImportKeyAlgorithm::Kmac(_) |
2728 ImportKeyAlgorithm::Argon2(_) => true,
2729 }
2730 },
2731 "exportKey" => {
2732 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2733 else {
2734 return false;
2735 };
2736
2737 match normalized_algorithm {
2738 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2739 ExportKeyAlgorithm::RsaPss(_) |
2740 ExportKeyAlgorithm::RsaOaep(_) |
2741 ExportKeyAlgorithm::Ecdsa(_) |
2742 ExportKeyAlgorithm::Ecdh(_) |
2743 ExportKeyAlgorithm::Ed25519(_) |
2744 ExportKeyAlgorithm::X25519(_) |
2745 ExportKeyAlgorithm::Ed448(_) |
2746 ExportKeyAlgorithm::X448(_) |
2747 ExportKeyAlgorithm::AesCtr(_) |
2748 ExportKeyAlgorithm::AesCbc(_) |
2749 ExportKeyAlgorithm::AesGcm(_) |
2750 ExportKeyAlgorithm::AesKw(_) |
2751 ExportKeyAlgorithm::Hmac(_) |
2752 ExportKeyAlgorithm::MlKem(_) |
2753 ExportKeyAlgorithm::MlDsa(_) |
2754 ExportKeyAlgorithm::AesOcb(_) |
2755 ExportKeyAlgorithm::ChaCha20Poly1305(_) |
2756 ExportKeyAlgorithm::Kmac(_) => true,
2757 }
2758 },
2759 "get key length" => {
2760 let Ok(normalized_algorithm) =
2761 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2762 else {
2763 return false;
2764 };
2765
2766 match normalized_algorithm {
2767 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2768 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2769 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2770 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2771 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2772 },
2773 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2774 normalized_derived_key_algorithm
2775 .length
2776 .is_none_or(|length| length != 0)
2777 },
2778 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2779 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2780 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2781 },
2782 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) |
2783 GetKeyLengthAlgorithm::Kmac(_) |
2784 GetKeyLengthAlgorithm::Argon2(_) => true,
2785 }
2786 },
2787 "encapsulate" => {
2788 let Ok(normalized_algorithm) =
2789 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2790 else {
2791 return false;
2792 };
2793
2794 match normalized_algorithm {
2795 EncapsulateAlgorithm::MlKem(_) => true,
2796 }
2797 },
2798 "decapsulate" => {
2799 let Ok(normalized_algorithm) =
2800 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2801 else {
2802 return false;
2803 };
2804
2805 match normalized_algorithm {
2806 DecapsulateAlgorithm::MlKem(_) => true,
2807 }
2808 },
2809 _ => false,
2810 }
2811
2812 }
2816
2817trait TryFromWithCxAndName<T>: Sized {
2819 type Error;
2820
2821 fn try_from_with_cx_and_name(
2822 value: T,
2823 cx: &mut js::context::JSContext,
2824 algorithm_name: CryptoAlgorithm,
2825 ) -> Result<Self, Self::Error>;
2826}
2827
2828trait TryIntoWithCxAndName<T>: Sized {
2830 type Error;
2831
2832 fn try_into_with_cx_and_name(
2833 self,
2834 cx: &mut js::context::JSContext,
2835 algorithm_name: CryptoAlgorithm,
2836 ) -> Result<T, Self::Error>;
2837}
2838
2839impl<T, U> TryIntoWithCxAndName<U> for T
2840where
2841 U: TryFromWithCxAndName<T>,
2842{
2843 type Error = U::Error;
2844
2845 fn try_into_with_cx_and_name(
2846 self,
2847 cx: &mut js::context::JSContext,
2848 algorithm_name: CryptoAlgorithm,
2849 ) -> Result<U, Self::Error> {
2850 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2851 }
2852}
2853
2854#[derive(Clone, MallocSizeOf)]
2859struct SubtleAlgorithm {
2860 name: CryptoAlgorithm,
2862}
2863
2864impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAlgorithm {
2865 type Error = Error;
2866
2867 fn try_from_with_cx_and_name(
2868 _object: HandleObject<'a>,
2869 _cx: &mut js::context::JSContext,
2870 algorithm_name: CryptoAlgorithm,
2871 ) -> Result<Self, Self::Error> {
2872 Ok(SubtleAlgorithm {
2873 name: algorithm_name,
2874 })
2875 }
2876}
2877
2878impl TryFrom<SerializableAlgorithm> for SubtleAlgorithm {
2879 type Error = ();
2880
2881 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2882 Ok(SubtleAlgorithm {
2883 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2884 })
2885 }
2886}
2887
2888impl From<&SubtleAlgorithm> for SerializableAlgorithm {
2889 fn from(value: &SubtleAlgorithm) -> Self {
2890 SerializableAlgorithm {
2891 name: value.name.as_str().into(),
2892 }
2893 }
2894}
2895
2896#[derive(Clone, MallocSizeOf)]
2898pub(crate) struct SubtleKeyAlgorithm {
2899 name: CryptoAlgorithm,
2901}
2902
2903impl ToJSValConvertible for SubtleKeyAlgorithm {
2904 #[expect(unsafe_code)]
2905 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
2906 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2907
2908 rooted!(&in(cx) let mut name_js = UndefinedValue());
2909 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
2910 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2911 .expect("Failed to set name property of KeyAlgorithm");
2912
2913 rval.set(ObjectOrNullValue(object.get()));
2914 }
2915}
2916
2917impl TryFrom<SerializableKeyAlgorithm> for SubtleKeyAlgorithm {
2918 type Error = ();
2919
2920 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2921 Ok(SubtleKeyAlgorithm {
2922 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2923 })
2924 }
2925}
2926
2927impl From<&SubtleKeyAlgorithm> for SerializableKeyAlgorithm {
2928 fn from(value: &SubtleKeyAlgorithm) -> Self {
2929 SerializableKeyAlgorithm {
2930 name: value.name.as_str().into(),
2931 }
2932 }
2933}
2934
2935#[derive(Clone, MallocSizeOf)]
2937pub(crate) struct SubtleRsaHashedKeyGenParams {
2938 name: CryptoAlgorithm,
2940
2941 modulus_length: u32,
2943
2944 public_exponent: Vec<u8>,
2946
2947 hash: DigestAlgorithm,
2949}
2950
2951impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedKeyGenParams {
2952 type Error = Error;
2953
2954 fn try_from_with_cx_and_name(
2955 object: HandleObject,
2956 cx: &mut js::context::JSContext,
2957 algorithm_name: CryptoAlgorithm,
2958 ) -> Result<Self, Self::Error> {
2959 let hash = get_required_parameter(cx, object, c"hash", ())?;
2960
2961 Ok(SubtleRsaHashedKeyGenParams {
2962 name: algorithm_name,
2963 modulus_length: get_required_parameter(
2964 cx,
2965 object,
2966 c"modulusLength",
2967 ConversionBehavior::Default,
2968 )?,
2969 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2970 cx,
2971 object,
2972 c"publicExponent",
2973 (),
2974 )?
2975 .to_vec()
2976 .unwrap_or_default(),
2977 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2978 })
2979 }
2980}
2981
2982#[derive(Clone, MallocSizeOf)]
2984pub(crate) struct SubtleRsaHashedKeyAlgorithm {
2985 name: CryptoAlgorithm,
2987
2988 modulus_length: u32,
2990
2991 public_exponent: Vec<u8>,
2993
2994 hash: DigestAlgorithm,
2996}
2997
2998impl ToJSValConvertible for SubtleRsaHashedKeyAlgorithm {
2999 #[expect(unsafe_code)]
3000 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3001 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3002
3003 rooted!(&in(cx) let mut name_js = UndefinedValue());
3004 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
3005 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3006 .expect("Failed to set name property of RsaHashedKeyAlgorithm");
3007
3008 rooted!(&in(cx) let mut modulus_length_js = UndefinedValue());
3009 self.modulus_length
3010 .safe_to_jsval(cx, modulus_length_js.handle_mut());
3011 set_dictionary_property(
3012 cx,
3013 object.handle(),
3014 c"modulusLength",
3015 modulus_length_js.handle(),
3016 )
3017 .expect("Failed to set modulusLength property of RsaHashedKeyAlgorithm");
3018
3019 rooted!(&in(cx) let mut public_exponent_js = UndefinedValue());
3020 rooted!(&in(cx) let mut public_exponent_js_object = ptr::null_mut::<JSObject>());
3021 let public_exponent = create_buffer_source::<ArrayBufferU8>(
3022 cx,
3023 &self.public_exponent,
3024 public_exponent_js_object.handle_mut(),
3025 )
3026 .expect("Failed to convert publicExponent to Uint8Array");
3027 public_exponent.safe_to_jsval(cx, public_exponent_js.handle_mut());
3028 set_dictionary_property(
3029 cx,
3030 object.handle(),
3031 c"publicExponent",
3032 public_exponent_js.handle(),
3033 )
3034 .expect("Failed to set publicExponent property of RsaHashedKeyAlgorithm");
3035
3036 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3037 let hash = SubtleKeyAlgorithm {
3038 name: self.hash.name(),
3039 };
3040 hash.safe_to_jsval(cx, hash_js.handle_mut());
3041 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3042 .expect("Failed to set hash property of RsaHashedKeyAlgorithm");
3043
3044 rval.set(ObjectOrNullValue(object.get()));
3045 }
3046}
3047
3048impl TryFrom<SerializableRsaHashedKeyAlgorithm> for SubtleRsaHashedKeyAlgorithm {
3049 type Error = ();
3050
3051 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
3052 Ok(SubtleRsaHashedKeyAlgorithm {
3053 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3054 modulus_length: value.modulus_length,
3055 public_exponent: value.public_exponent,
3056 hash: value.hash.try_into()?,
3057 })
3058 }
3059}
3060
3061impl From<&SubtleRsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
3062 fn from(value: &SubtleRsaHashedKeyAlgorithm) -> Self {
3063 SerializableRsaHashedKeyAlgorithm {
3064 name: value.name.as_str().into(),
3065 modulus_length: value.modulus_length,
3066 public_exponent: value.public_exponent.clone(),
3067 hash: (&value.hash).into(),
3068 }
3069 }
3070}
3071
3072#[derive(Clone, MallocSizeOf)]
3074struct SubtleRsaHashedImportParams {
3075 name: CryptoAlgorithm,
3077
3078 hash: DigestAlgorithm,
3080}
3081
3082impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaHashedImportParams {
3083 type Error = Error;
3084
3085 fn try_from_with_cx_and_name(
3086 object: HandleObject,
3087 cx: &mut js::context::JSContext,
3088 algorithm_name: CryptoAlgorithm,
3089 ) -> Result<Self, Self::Error> {
3090 let hash = get_required_parameter(cx, object, c"hash", ())?;
3091
3092 Ok(SubtleRsaHashedImportParams {
3093 name: algorithm_name,
3094 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3095 })
3096 }
3097}
3098
3099#[derive(Clone, MallocSizeOf)]
3101struct SubtleRsaPssParams {
3102 name: CryptoAlgorithm,
3104
3105 salt_length: u32,
3107}
3108
3109impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaPssParams {
3110 type Error = Error;
3111
3112 fn try_from_with_cx_and_name(
3113 object: HandleObject,
3114 cx: &mut js::context::JSContext,
3115 algorithm_name: CryptoAlgorithm,
3116 ) -> Result<Self, Self::Error> {
3117 Ok(SubtleRsaPssParams {
3118 name: algorithm_name,
3119 salt_length: get_required_parameter(
3120 cx,
3121 object,
3122 c"saltLength",
3123 ConversionBehavior::EnforceRange,
3124 )?,
3125 })
3126 }
3127}
3128
3129#[derive(Clone, MallocSizeOf)]
3131struct SubtleRsaOaepParams {
3132 name: CryptoAlgorithm,
3134
3135 label: Option<Vec<u8>>,
3137}
3138
3139impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleRsaOaepParams {
3140 type Error = Error;
3141
3142 fn try_from_with_cx_and_name(
3143 object: HandleObject<'a>,
3144 cx: &mut js::context::JSContext,
3145 algorithm_name: CryptoAlgorithm,
3146 ) -> Result<Self, Self::Error> {
3147 Ok(SubtleRsaOaepParams {
3148 name: algorithm_name,
3149 label: get_optional_buffer_source(cx, object, c"label")?,
3150 })
3151 }
3152}
3153
3154#[derive(Clone, MallocSizeOf)]
3156struct SubtleEcdsaParams {
3157 name: CryptoAlgorithm,
3159
3160 hash: DigestAlgorithm,
3162}
3163
3164impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdsaParams {
3165 type Error = Error;
3166
3167 fn try_from_with_cx_and_name(
3168 object: HandleObject<'a>,
3169 cx: &mut js::context::JSContext,
3170 algorithm_name: CryptoAlgorithm,
3171 ) -> Result<Self, Self::Error> {
3172 let hash = get_required_parameter(cx, object, c"hash", ())?;
3173
3174 Ok(SubtleEcdsaParams {
3175 name: algorithm_name,
3176 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3177 })
3178 }
3179}
3180
3181#[derive(Clone, MallocSizeOf)]
3183struct SubtleEcKeyGenParams {
3184 name: CryptoAlgorithm,
3186
3187 named_curve: String,
3189}
3190
3191impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyGenParams {
3192 type Error = Error;
3193
3194 fn try_from_with_cx_and_name(
3195 object: HandleObject<'a>,
3196 cx: &mut js::context::JSContext,
3197 algorithm_name: CryptoAlgorithm,
3198 ) -> Result<Self, Self::Error> {
3199 Ok(SubtleEcKeyGenParams {
3200 name: algorithm_name,
3201 named_curve: String::from(get_required_parameter::<DOMString>(
3202 cx,
3203 object,
3204 c"namedCurve",
3205 StringificationBehavior::Default,
3206 )?),
3207 })
3208 }
3209}
3210
3211#[derive(Clone, MallocSizeOf)]
3213pub(crate) struct SubtleEcKeyAlgorithm {
3214 name: CryptoAlgorithm,
3216
3217 named_curve: String,
3219}
3220
3221impl ToJSValConvertible for SubtleEcKeyAlgorithm {
3222 #[expect(unsafe_code)]
3223 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3224 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3225
3226 rooted!(&in(cx) let mut name_js = UndefinedValue());
3227 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
3228 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3229 .expect("Failed to set name property of EcKeyAlgorithm");
3230
3231 rooted!(&in(cx) let mut named_curve_js = UndefinedValue());
3232 self.named_curve
3233 .safe_to_jsval(cx, named_curve_js.handle_mut());
3234 set_dictionary_property(cx, object.handle(), c"namedCurve", named_curve_js.handle())
3235 .expect("Failed to set namedCurve property of EcKeyAlgorithm");
3236
3237 rval.set(ObjectOrNullValue(object.get()));
3238 }
3239}
3240
3241impl TryFrom<SerializableEcKeyAlgorithm> for SubtleEcKeyAlgorithm {
3242 type Error = ();
3243
3244 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3245 Ok(SubtleEcKeyAlgorithm {
3246 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3247 named_curve: value.named_curve,
3248 })
3249 }
3250}
3251
3252impl From<&SubtleEcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3253 fn from(value: &SubtleEcKeyAlgorithm) -> Self {
3254 SerializableEcKeyAlgorithm {
3255 name: value.name.as_str().into(),
3256 named_curve: value.named_curve.clone(),
3257 }
3258 }
3259}
3260
3261#[derive(Clone, MallocSizeOf)]
3263struct SubtleEcKeyImportParams {
3264 name: CryptoAlgorithm,
3266
3267 named_curve: String,
3269}
3270
3271impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcKeyImportParams {
3272 type Error = Error;
3273
3274 fn try_from_with_cx_and_name(
3275 object: HandleObject<'a>,
3276 cx: &mut js::context::JSContext,
3277 algorithm_name: CryptoAlgorithm,
3278 ) -> Result<Self, Self::Error> {
3279 Ok(SubtleEcKeyImportParams {
3280 name: algorithm_name,
3281 named_curve: String::from(get_required_parameter::<DOMString>(
3282 cx,
3283 object,
3284 c"namedCurve",
3285 StringificationBehavior::Default,
3286 )?),
3287 })
3288 }
3289}
3290
3291#[derive(Clone, MallocSizeOf)]
3293struct SubtleEcdhKeyDeriveParams {
3294 name: CryptoAlgorithm,
3296
3297 public: Trusted<CryptoKey>,
3299}
3300
3301impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEcdhKeyDeriveParams {
3302 type Error = Error;
3303
3304 fn try_from_with_cx_and_name(
3305 object: HandleObject<'a>,
3306 cx: &mut js::context::JSContext,
3307 algorithm_name: CryptoAlgorithm,
3308 ) -> Result<Self, Self::Error> {
3309 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3310
3311 Ok(SubtleEcdhKeyDeriveParams {
3312 name: algorithm_name,
3313 public: Trusted::new(&public),
3314 })
3315 }
3316}
3317
3318#[derive(Clone, MallocSizeOf)]
3320struct SubtleAesCtrParams {
3321 name: CryptoAlgorithm,
3323
3324 counter: Vec<u8>,
3326
3327 length: u8,
3329}
3330
3331impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCtrParams {
3332 type Error = Error;
3333
3334 fn try_from_with_cx_and_name(
3335 object: HandleObject<'a>,
3336 cx: &mut js::context::JSContext,
3337 algorithm_name: CryptoAlgorithm,
3338 ) -> Result<Self, Self::Error> {
3339 Ok(SubtleAesCtrParams {
3340 name: algorithm_name,
3341 counter: get_required_buffer_source(cx, object, c"counter")?,
3342 length: get_required_parameter(
3343 cx,
3344 object,
3345 c"length",
3346 ConversionBehavior::EnforceRange,
3347 )?,
3348 })
3349 }
3350}
3351
3352#[derive(Clone, MallocSizeOf)]
3354pub(crate) struct SubtleAesKeyAlgorithm {
3355 name: CryptoAlgorithm,
3357
3358 length: u16,
3360}
3361
3362impl ToJSValConvertible for SubtleAesKeyAlgorithm {
3363 #[expect(unsafe_code)]
3364 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3365 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3366
3367 rooted!(&in(cx) let mut name_js = UndefinedValue());
3368 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
3369 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3370 .expect("Failed to set name property of AesKeyAlgorithm");
3371
3372 rooted!(&in(cx) let mut length_js = UndefinedValue());
3373 self.length.safe_to_jsval(cx, length_js.handle_mut());
3374 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3375 .expect("Failed to set length property of AesKeyAlgorithm");
3376
3377 rval.set(ObjectOrNullValue(object.get()));
3378 }
3379}
3380
3381impl TryFrom<SerializableAesKeyAlgorithm> for SubtleAesKeyAlgorithm {
3382 type Error = ();
3383
3384 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3385 Ok(SubtleAesKeyAlgorithm {
3386 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3387 length: value.length,
3388 })
3389 }
3390}
3391
3392impl From<&SubtleAesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3393 fn from(value: &SubtleAesKeyAlgorithm) -> Self {
3394 SerializableAesKeyAlgorithm {
3395 name: value.name.as_str().into(),
3396 length: value.length,
3397 }
3398 }
3399}
3400
3401#[derive(Clone, MallocSizeOf)]
3403struct SubtleAesKeyGenParams {
3404 name: CryptoAlgorithm,
3406
3407 length: u16,
3409}
3410
3411impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesKeyGenParams {
3412 type Error = Error;
3413
3414 fn try_from_with_cx_and_name(
3415 object: HandleObject<'a>,
3416 cx: &mut js::context::JSContext,
3417 algorithm_name: CryptoAlgorithm,
3418 ) -> Result<Self, Self::Error> {
3419 Ok(SubtleAesKeyGenParams {
3420 name: algorithm_name,
3421 length: get_required_parameter(
3422 cx,
3423 object,
3424 c"length",
3425 ConversionBehavior::EnforceRange,
3426 )?,
3427 })
3428 }
3429}
3430
3431#[derive(Clone, MallocSizeOf)]
3433struct SubtleAesDerivedKeyParams {
3434 name: CryptoAlgorithm,
3436
3437 length: u16,
3439}
3440
3441impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesDerivedKeyParams {
3442 type Error = Error;
3443
3444 fn try_from_with_cx_and_name(
3445 object: HandleObject<'a>,
3446 cx: &mut js::context::JSContext,
3447 algorithm_name: CryptoAlgorithm,
3448 ) -> Result<Self, Self::Error> {
3449 Ok(SubtleAesDerivedKeyParams {
3450 name: algorithm_name,
3451 length: get_required_parameter(
3452 cx,
3453 object,
3454 c"length",
3455 ConversionBehavior::EnforceRange,
3456 )?,
3457 })
3458 }
3459}
3460
3461#[derive(Clone, MallocSizeOf)]
3463struct SubtleAesCbcParams {
3464 name: CryptoAlgorithm,
3466
3467 iv: Vec<u8>,
3469}
3470
3471impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesCbcParams {
3472 type Error = Error;
3473
3474 fn try_from_with_cx_and_name(
3475 object: HandleObject<'a>,
3476 cx: &mut js::context::JSContext,
3477 algorithm_name: CryptoAlgorithm,
3478 ) -> Result<Self, Self::Error> {
3479 Ok(SubtleAesCbcParams {
3480 name: algorithm_name,
3481 iv: get_required_buffer_source(cx, object, c"iv")?,
3482 })
3483 }
3484}
3485
3486#[derive(Clone, MallocSizeOf)]
3488struct SubtleAesGcmParams {
3489 name: CryptoAlgorithm,
3491
3492 iv: Vec<u8>,
3494
3495 additional_data: Option<Vec<u8>>,
3497
3498 tag_length: Option<u8>,
3500}
3501
3502impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAesGcmParams {
3503 type Error = Error;
3504
3505 fn try_from_with_cx_and_name(
3506 object: HandleObject<'a>,
3507 cx: &mut js::context::JSContext,
3508 algorithm_name: CryptoAlgorithm,
3509 ) -> Result<Self, Self::Error> {
3510 Ok(SubtleAesGcmParams {
3511 name: algorithm_name,
3512 iv: get_required_buffer_source(cx, object, c"iv")?,
3513 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3514 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3515 })
3516 }
3517}
3518
3519#[derive(Clone, MallocSizeOf)]
3521struct SubtleHmacImportParams {
3522 name: CryptoAlgorithm,
3524
3525 hash: DigestAlgorithm,
3527
3528 length: Option<u32>,
3530}
3531
3532impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacImportParams {
3533 type Error = Error;
3534
3535 fn try_from_with_cx_and_name(
3536 object: HandleObject<'a>,
3537 cx: &mut js::context::JSContext,
3538 algorithm_name: CryptoAlgorithm,
3539 ) -> Result<Self, Self::Error> {
3540 let hash = get_required_parameter(cx, object, c"hash", ())?;
3541
3542 Ok(SubtleHmacImportParams {
3543 name: algorithm_name,
3544 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3545 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3546 })
3547 }
3548}
3549
3550#[derive(Clone, MallocSizeOf)]
3552pub(crate) struct SubtleHmacKeyAlgorithm {
3553 name: CryptoAlgorithm,
3555
3556 hash: DigestAlgorithm,
3558
3559 length: u32,
3561}
3562
3563impl ToJSValConvertible for SubtleHmacKeyAlgorithm {
3564 #[expect(unsafe_code)]
3565 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3566 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3567
3568 rooted!(&in(cx) let mut name_js = UndefinedValue());
3569 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
3570 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3571 .expect("Failed to set name property of HmacKeyAlgorithm");
3572
3573 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3574 let hash = SubtleKeyAlgorithm {
3575 name: self.hash.name(),
3576 };
3577 hash.safe_to_jsval(cx, hash_js.handle_mut());
3578 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3579 .expect("Failed to set hash property of HmacKeyAlgorithm");
3580
3581 rooted!(&in(cx) let mut length_js = UndefinedValue());
3582 self.length.safe_to_jsval(cx, length_js.handle_mut());
3583 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3584 .expect("Failed to set length property of HmacKeyAlgorithm");
3585
3586 rval.set(ObjectOrNullValue(object.get()));
3587 }
3588}
3589
3590impl TryFrom<SerializableHmacKeyAlgorithm> for SubtleHmacKeyAlgorithm {
3591 type Error = ();
3592
3593 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3594 Ok(SubtleHmacKeyAlgorithm {
3595 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3596 hash: value.hash.try_into()?,
3597 length: value.length,
3598 })
3599 }
3600}
3601
3602impl From<&SubtleHmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3603 fn from(value: &SubtleHmacKeyAlgorithm) -> Self {
3604 SerializableHmacKeyAlgorithm {
3605 name: value.name.as_str().into(),
3606 hash: (&value.hash).into(),
3607 length: value.length,
3608 }
3609 }
3610}
3611
3612#[derive(Clone, MallocSizeOf)]
3614struct SubtleHmacKeyGenParams {
3615 name: CryptoAlgorithm,
3617
3618 hash: DigestAlgorithm,
3620
3621 length: Option<u32>,
3623}
3624
3625impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHmacKeyGenParams {
3626 type Error = Error;
3627
3628 fn try_from_with_cx_and_name(
3629 object: HandleObject<'a>,
3630 cx: &mut js::context::JSContext,
3631 algorithm_name: CryptoAlgorithm,
3632 ) -> Result<Self, Self::Error> {
3633 let hash = get_required_parameter(cx, object, c"hash", ())?;
3634
3635 Ok(SubtleHmacKeyGenParams {
3636 name: algorithm_name,
3637 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3638 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3639 })
3640 }
3641}
3642
3643#[derive(Clone, MallocSizeOf)]
3645pub(crate) struct SubtleHkdfParams {
3646 name: CryptoAlgorithm,
3648
3649 hash: DigestAlgorithm,
3651
3652 salt: Vec<u8>,
3654
3655 info: Vec<u8>,
3657}
3658
3659impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleHkdfParams {
3660 type Error = Error;
3661
3662 fn try_from_with_cx_and_name(
3663 object: HandleObject<'a>,
3664 cx: &mut js::context::JSContext,
3665 algorithm_name: CryptoAlgorithm,
3666 ) -> Result<Self, Self::Error> {
3667 let hash = get_required_parameter(cx, object, c"hash", ())?;
3668
3669 Ok(SubtleHkdfParams {
3670 name: algorithm_name,
3671 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3672 salt: get_required_buffer_source(cx, object, c"salt")?,
3673 info: get_required_buffer_source(cx, object, c"info")?,
3674 })
3675 }
3676}
3677
3678#[derive(Clone, MallocSizeOf)]
3680pub(crate) struct SubtlePbkdf2Params {
3681 name: CryptoAlgorithm,
3683
3684 salt: Vec<u8>,
3686
3687 iterations: u32,
3689
3690 hash: DigestAlgorithm,
3692}
3693
3694impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtlePbkdf2Params {
3695 type Error = Error;
3696
3697 fn try_from_with_cx_and_name(
3698 object: HandleObject<'a>,
3699 cx: &mut js::context::JSContext,
3700 algorithm_name: CryptoAlgorithm,
3701 ) -> Result<Self, Self::Error> {
3702 let hash = get_required_parameter(cx, object, c"hash", ())?;
3703
3704 Ok(SubtlePbkdf2Params {
3705 name: algorithm_name,
3706 salt: get_required_buffer_source(cx, object, c"salt")?,
3707 iterations: get_required_parameter(
3708 cx,
3709 object,
3710 c"iterations",
3711 ConversionBehavior::EnforceRange,
3712 )?,
3713 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3714 })
3715 }
3716}
3717
3718#[derive(Clone, MallocSizeOf)]
3720struct SubtleContextParams {
3721 name: CryptoAlgorithm,
3723
3724 context: Option<Vec<u8>>,
3726}
3727
3728impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleContextParams {
3729 type Error = Error;
3730
3731 fn try_from_with_cx_and_name(
3732 object: HandleObject<'a>,
3733 cx: &mut js::context::JSContext,
3734 algorithm_name: CryptoAlgorithm,
3735 ) -> Result<Self, Self::Error> {
3736 Ok(SubtleContextParams {
3737 name: algorithm_name,
3738 context: get_optional_buffer_source(cx, object, c"context")?,
3739 })
3740 }
3741}
3742
3743#[derive(Clone, MallocSizeOf)]
3745struct SubtleAeadParams {
3746 name: CryptoAlgorithm,
3748
3749 iv: Vec<u8>,
3751
3752 additional_data: Option<Vec<u8>>,
3754
3755 tag_length: Option<u8>,
3757}
3758
3759impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleAeadParams {
3760 type Error = Error;
3761
3762 fn try_from_with_cx_and_name(
3763 object: HandleObject<'a>,
3764 cx: &mut js::context::JSContext,
3765 algorithm_name: CryptoAlgorithm,
3766 ) -> Result<Self, Self::Error> {
3767 Ok(SubtleAeadParams {
3768 name: algorithm_name,
3769 iv: get_required_buffer_source(cx, object, c"iv")?,
3770 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3771 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3772 })
3773 }
3774}
3775
3776#[derive(Clone, MallocSizeOf)]
3778struct SubtleCShakeParams {
3779 name: CryptoAlgorithm,
3781
3782 output_length: u32,
3784
3785 function_name: Option<Vec<u8>>,
3787
3788 customization: Option<Vec<u8>>,
3790}
3791
3792impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleCShakeParams {
3793 type Error = Error;
3794
3795 fn try_from_with_cx_and_name(
3796 object: HandleObject<'a>,
3797 cx: &mut js::context::JSContext,
3798 algorithm_name: CryptoAlgorithm,
3799 ) -> Result<Self, Self::Error> {
3800 Ok(SubtleCShakeParams {
3801 name: algorithm_name,
3802 output_length: get_required_parameter(
3803 cx,
3804 object,
3805 c"outputLength",
3806 ConversionBehavior::EnforceRange,
3807 )?,
3808 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3809 customization: get_optional_buffer_source(cx, object, c"customization")?,
3810 })
3811 }
3812}
3813
3814impl TryFrom<SerializableCShakeParams> for SubtleCShakeParams {
3815 type Error = ();
3816
3817 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3818 Ok(SubtleCShakeParams {
3819 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3820 output_length: value.output_length,
3821 function_name: value.function_name,
3822 customization: value.customization,
3823 })
3824 }
3825}
3826
3827impl From<&SubtleCShakeParams> for SerializableCShakeParams {
3828 fn from(value: &SubtleCShakeParams) -> Self {
3829 SerializableCShakeParams {
3830 name: value.name.as_str().into(),
3831 output_length: value.output_length,
3832 function_name: value.function_name.clone(),
3833 customization: value.customization.clone(),
3834 }
3835 }
3836}
3837
3838#[derive(Clone, MallocSizeOf)]
3840struct SubtleTurboShakeParams {
3841 name: CryptoAlgorithm,
3843
3844 output_length: u32,
3846
3847 domain_separation: Option<u8>,
3849}
3850
3851impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleTurboShakeParams {
3852 type Error = Error;
3853
3854 fn try_from_with_cx_and_name(
3855 object: HandleObject<'a>,
3856 cx: &mut js::context::JSContext,
3857 algorithm_name: CryptoAlgorithm,
3858 ) -> Result<Self, Self::Error> {
3859 Ok(SubtleTurboShakeParams {
3860 name: algorithm_name,
3861 output_length: get_required_parameter(
3862 cx,
3863 object,
3864 c"outputLength",
3865 ConversionBehavior::EnforceRange,
3866 )?,
3867 domain_separation: get_property(
3868 cx,
3869 object,
3870 c"domainSeparation",
3871 ConversionBehavior::EnforceRange,
3872 )?,
3873 })
3874 }
3875}
3876
3877impl TryFrom<SerializableTurboShakeParams> for SubtleTurboShakeParams {
3878 type Error = ();
3879
3880 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3881 Ok(SubtleTurboShakeParams {
3882 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3883 output_length: value.output_length,
3884 domain_separation: value.domain_separation,
3885 })
3886 }
3887}
3888
3889impl From<&SubtleTurboShakeParams> for SerializableTurboShakeParams {
3890 fn from(value: &SubtleTurboShakeParams) -> Self {
3891 SerializableTurboShakeParams {
3892 name: value.name.as_str().into(),
3893 output_length: value.output_length,
3894 domain_separation: value.domain_separation,
3895 }
3896 }
3897}
3898
3899#[derive(Clone, MallocSizeOf)]
3901struct SubtleKangarooTwelveParams {
3902 name: CryptoAlgorithm,
3904
3905 output_length: u32,
3907
3908 customization: Option<Vec<u8>>,
3910}
3911
3912impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKangarooTwelveParams {
3913 type Error = Error;
3914
3915 fn try_from_with_cx_and_name(
3916 object: HandleObject<'a>,
3917 cx: &mut js::context::JSContext,
3918 algorithm_name: CryptoAlgorithm,
3919 ) -> Result<Self, Self::Error> {
3920 Ok(SubtleKangarooTwelveParams {
3921 name: algorithm_name,
3922 output_length: get_required_parameter(
3923 cx,
3924 object,
3925 c"outputLength",
3926 ConversionBehavior::EnforceRange,
3927 )?,
3928 customization: get_optional_buffer_source(cx, object, c"customization")?,
3929 })
3930 }
3931}
3932
3933impl TryFrom<SerializableKangarooTwelveParams> for SubtleKangarooTwelveParams {
3934 type Error = ();
3935
3936 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
3937 Ok(SubtleKangarooTwelveParams {
3938 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3939 output_length: value.output_length,
3940 customization: value.customization,
3941 })
3942 }
3943}
3944
3945impl From<&SubtleKangarooTwelveParams> for SerializableKangarooTwelveParams {
3946 fn from(value: &SubtleKangarooTwelveParams) -> Self {
3947 SerializableKangarooTwelveParams {
3948 name: value.name.as_str().into(),
3949 output_length: value.output_length,
3950 customization: value.customization.clone(),
3951 }
3952 }
3953}
3954
3955#[derive(Clone, MallocSizeOf)]
3957struct SubtleKmacKeyGenParams {
3958 name: CryptoAlgorithm,
3960
3961 length: Option<u32>,
3963}
3964
3965impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacKeyGenParams {
3966 type Error = Error;
3967
3968 fn try_from_with_cx_and_name(
3969 object: HandleObject,
3970 cx: &mut js::context::JSContext,
3971 algorithm_name: CryptoAlgorithm,
3972 ) -> Result<Self, Self::Error> {
3973 Ok(SubtleKmacKeyGenParams {
3974 name: algorithm_name,
3975 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3976 })
3977 }
3978}
3979
3980#[derive(Clone, MallocSizeOf)]
3982struct SubtleKmacImportParams {
3983 name: CryptoAlgorithm,
3985
3986 length: Option<u32>,
3988}
3989
3990impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacImportParams {
3991 type Error = Error;
3992
3993 fn try_from_with_cx_and_name(
3994 object: HandleObject,
3995 cx: &mut js::context::JSContext,
3996 algorithm_name: CryptoAlgorithm,
3997 ) -> Result<Self, Self::Error> {
3998 Ok(SubtleKmacImportParams {
3999 name: algorithm_name,
4000 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
4001 })
4002 }
4003}
4004
4005#[derive(Clone, MallocSizeOf)]
4007pub(crate) struct SubtleKmacKeyAlgorithm {
4008 name: CryptoAlgorithm,
4010
4011 length: u32,
4013}
4014
4015impl ToJSValConvertible for SubtleKmacKeyAlgorithm {
4016 #[expect(unsafe_code)]
4017 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
4018 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4019
4020 rooted!(&in(cx) let mut name_js = UndefinedValue());
4021 self.name.as_str().safe_to_jsval(cx, name_js.handle_mut());
4022 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
4023 .expect("Failed to set name property of KmacKeyAlgorithm");
4024
4025 rooted!(&in(cx) let mut length_js = UndefinedValue());
4026 self.length.safe_to_jsval(cx, length_js.handle_mut());
4027 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
4028 .expect("Failed to set length property of KmacKeyAlgorithm");
4029
4030 rval.set(ObjectOrNullValue(object.get()));
4031 }
4032}
4033
4034impl TryFrom<SerializableKmacKeyAlgorithm> for SubtleKmacKeyAlgorithm {
4035 type Error = ();
4036
4037 fn try_from(value: SerializableKmacKeyAlgorithm) -> Result<Self, Self::Error> {
4038 Ok(SubtleKmacKeyAlgorithm {
4039 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
4040 length: value.length,
4041 })
4042 }
4043}
4044
4045impl From<&SubtleKmacKeyAlgorithm> for SerializableKmacKeyAlgorithm {
4046 fn from(value: &SubtleKmacKeyAlgorithm) -> Self {
4047 SerializableKmacKeyAlgorithm {
4048 name: value.name.as_str().into(),
4049 length: value.length,
4050 }
4051 }
4052}
4053
4054struct SubtleKmacParams {
4056 name: CryptoAlgorithm,
4058
4059 output_length: u32,
4061
4062 customization: Option<Vec<u8>>,
4064}
4065
4066impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleKmacParams {
4067 type Error = Error;
4068
4069 fn try_from_with_cx_and_name(
4070 object: HandleObject<'a>,
4071 cx: &mut js::context::JSContext,
4072 algorithm_name: CryptoAlgorithm,
4073 ) -> Result<Self, Self::Error> {
4074 Ok(SubtleKmacParams {
4075 name: algorithm_name,
4076 output_length: get_required_parameter(
4077 cx,
4078 object,
4079 c"outputLength",
4080 ConversionBehavior::EnforceRange,
4081 )?,
4082 customization: get_optional_buffer_source(cx, object, c"customization")?,
4083 })
4084 }
4085}
4086
4087#[derive(Clone, MallocSizeOf)]
4089struct SubtleArgon2Params {
4090 name: CryptoAlgorithm,
4092
4093 nonce: Vec<u8>,
4095
4096 parallelism: u32,
4098
4099 memory: u32,
4101
4102 passes: u32,
4104
4105 version: Option<u8>,
4107
4108 secret_value: Option<Vec<u8>>,
4110
4111 associated_data: Option<Vec<u8>>,
4113}
4114
4115impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleArgon2Params {
4116 type Error = Error;
4117
4118 fn try_from_with_cx_and_name(
4119 object: HandleObject<'a>,
4120 cx: &mut js::context::JSContext,
4121 algorithm_name: CryptoAlgorithm,
4122 ) -> Result<Self, Self::Error> {
4123 Ok(SubtleArgon2Params {
4124 name: algorithm_name,
4125 nonce: get_required_buffer_source(cx, object, c"nonce")?,
4126 parallelism: get_required_parameter(
4127 cx,
4128 object,
4129 c"parallelism",
4130 ConversionBehavior::EnforceRange,
4131 )?,
4132 memory: get_required_parameter(
4133 cx,
4134 object,
4135 c"memory",
4136 ConversionBehavior::EnforceRange,
4137 )?,
4138 passes: get_required_parameter(
4139 cx,
4140 object,
4141 c"passes",
4142 ConversionBehavior::EnforceRange,
4143 )?,
4144 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
4145 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
4146 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
4147 })
4148 }
4149}
4150
4151struct SubtleEncapsulatedKey {
4153 shared_key: Option<Trusted<CryptoKey>>,
4155
4156 ciphertext: Option<Vec<u8>>,
4158}
4159
4160impl ToJSValConvertible for SubtleEncapsulatedKey {
4161 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4162 let shared_key = self.shared_key.as_ref().map(|shared_key| shared_key.root());
4163 let ciphertext = self.ciphertext.as_ref().map(|data| {
4164 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
4165 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
4166 .expect("Failed to convert ciphertext to ArrayBufferU8")
4167 });
4168 let encapsulated_key = RootedTraceableBox::new(EncapsulatedKey {
4169 sharedKey: shared_key,
4170 ciphertext,
4171 });
4172 encapsulated_key.safe_to_jsval(cx, rval);
4173 }
4174}
4175
4176struct SubtleEncapsulatedBits {
4178 shared_key: Option<Zeroizing<Vec<u8>>>,
4180
4181 ciphertext: Option<Vec<u8>>,
4183}
4184
4185impl ToJSValConvertible for SubtleEncapsulatedBits {
4186 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4187 let shared_key = self.shared_key.as_ref().map(|data| {
4188 rooted!(&in(cx) let mut shared_key_ptr = ptr::null_mut::<JSObject>());
4189 create_buffer_source::<ArrayBufferU8>(cx, data, shared_key_ptr.handle_mut())
4190 .expect("Failed to convert shared key to ArrayBufferU8")
4191 });
4192 let ciphertext = self.ciphertext.as_ref().map(|data| {
4193 rooted!(&in(cx) let mut ciphertext_ptr = ptr::null_mut::<JSObject>());
4194 create_buffer_source::<ArrayBufferU8>(cx, data, ciphertext_ptr.handle_mut())
4195 .expect("Failed to convert ciphertext to ArrayBufferU8")
4196 });
4197 let encapsulated_bits = RootedTraceableBox::new(EncapsulatedBits {
4198 sharedKey: shared_key,
4199 ciphertext,
4200 });
4201 encapsulated_bits.safe_to_jsval(cx, rval);
4202 }
4203}
4204
4205#[derive(Clone, MallocSizeOf)]
4207struct SubtleEd448Params {
4208 name: CryptoAlgorithm,
4210
4211 context: Option<Vec<u8>>,
4213}
4214
4215impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEd448Params {
4216 type Error = Error;
4217
4218 fn try_from_with_cx_and_name(
4219 object: HandleObject<'a>,
4220 cx: &mut js::context::JSContext,
4221 algorithm_name: CryptoAlgorithm,
4222 ) -> Result<Self, Self::Error> {
4223 Ok(SubtleEd448Params {
4224 name: algorithm_name,
4225 context: get_optional_buffer_source(cx, object, c"context")?,
4226 })
4227 }
4228}
4229
4230fn get_required_parameter<T: FromJSValConvertible>(
4232 cx: &mut js::context::JSContext,
4233 object: HandleObject,
4234 parameter: &std::ffi::CStr,
4235 option: T::Config,
4236) -> Fallible<T> {
4237 get_property::<T>(cx, object, parameter, option)?
4238 .ok_or(Error::Type(c"Missing required parameter".into()))
4239}
4240
4241fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4243 cx: &mut js::context::JSContext,
4244 object: HandleObject,
4245 parameter: &std::ffi::CStr,
4246 option: T::Config,
4247) -> Fallible<RootedTraceableBox<T>> {
4248 get_property::<T>(cx, object, parameter, option)?
4249 .map(RootedTraceableBox::new)
4250 .ok_or(Error::Type(c"Missing required parameter".into()))
4251}
4252
4253fn get_optional_buffer_source(
4257 cx: &mut js::context::JSContext,
4258 object: HandleObject,
4259 parameter: &std::ffi::CStr,
4260) -> Fallible<Option<Vec<u8>>> {
4261 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4262 Ok(buffer_source
4263 .as_ref()
4264 .map(|buffer| get_buffer_source_copy(buffer.into())))
4265}
4266
4267fn get_required_buffer_source(
4271 cx: &mut js::context::JSContext,
4272 object: HandleObject,
4273 parameter: &std::ffi::CStr,
4274) -> Fallible<Vec<u8>> {
4275 get_optional_buffer_source(cx, object, parameter)?
4276 .ok_or(Error::Type(c"Missing required parameter".into()))
4277}
4278
4279enum ExportedKey {
4283 Bytes(Zeroizing<Vec<u8>>),
4284 Jwk(Box<JsonWebKey>),
4285}
4286
4287impl ExportedKey {
4288 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4289 ExportedKey::Bytes(Zeroizing::new(bytes))
4290 }
4291
4292 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4293 ExportedKey::Jwk(Box::new(jwk))
4294 }
4295}
4296
4297#[derive(Clone, MallocSizeOf)]
4301#[expect(clippy::enum_variant_names)]
4302pub(crate) enum KeyAlgorithmAndDerivatives {
4303 KeyAlgorithm(SubtleKeyAlgorithm),
4304 RsaHashedKeyAlgorithm(SubtleRsaHashedKeyAlgorithm),
4305 EcKeyAlgorithm(SubtleEcKeyAlgorithm),
4306 AesKeyAlgorithm(SubtleAesKeyAlgorithm),
4307 HmacKeyAlgorithm(SubtleHmacKeyAlgorithm),
4308 KmacKeyAlgorithm(SubtleKmacKeyAlgorithm),
4309}
4310
4311impl KeyAlgorithmAndDerivatives {
4312 fn name(&self) -> CryptoAlgorithm {
4313 match self {
4314 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4315 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4316 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4317 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4318 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4319 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => algorithm.name,
4320 }
4321 }
4322}
4323
4324impl ToJSValConvertible for KeyAlgorithmAndDerivatives {
4325 fn safe_to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4326 match self {
4327 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4328 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4329 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4330 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4331 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4332 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algo) => algo.safe_to_jsval(cx, rval),
4333 }
4334 }
4335}
4336
4337impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4338 type Error = ();
4339
4340 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4341 match value {
4342 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4343 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4344 ),
4345 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4346 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4347 ),
4348 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4349 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4350 ),
4351 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4352 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4353 ),
4354 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4355 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4356 ),
4357 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => Ok(
4358 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.try_into()?),
4359 ),
4360 }
4361 }
4362}
4363
4364impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4365 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4366 match value {
4367 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4368 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4369 },
4370 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4371 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4372 },
4373 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4374 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4375 },
4376 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4377 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4378 },
4379 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4380 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4381 },
4382 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => {
4383 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.into())
4384 },
4385 }
4386 }
4387}
4388
4389#[derive(Clone, Copy)]
4390enum JwkStringField {
4391 X,
4392 Y,
4393 D,
4394 N,
4395 E,
4396 P,
4397 Q,
4398 DP,
4399 DQ,
4400 QI,
4401 K,
4402 Priv,
4403 Pub,
4404}
4405
4406impl Display for JwkStringField {
4407 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4408 let field_name = match self {
4409 JwkStringField::X => "x",
4410 JwkStringField::Y => "y",
4411 JwkStringField::D => "d",
4412 JwkStringField::N => "n",
4413 JwkStringField::E => "e",
4414 JwkStringField::P => "q",
4415 JwkStringField::Q => "q",
4416 JwkStringField::DP => "dp",
4417 JwkStringField::DQ => "dq",
4418 JwkStringField::QI => "qi",
4419 JwkStringField::K => "k",
4420 JwkStringField::Priv => "priv",
4421 JwkStringField::Pub => "pub",
4422 };
4423 write!(f, "{}", field_name)
4424 }
4425}
4426
4427trait JsonWebKeyExt {
4428 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4429 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4430 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4431 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4432 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4433 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4434 fn decode_optional_string_field(
4435 &self,
4436 field: JwkStringField,
4437 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4438 fn decode_required_string_field(
4439 &self,
4440 field: JwkStringField,
4441 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4442 fn decode_primes_from_oth_field(
4443 &self,
4444 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4445 ) -> Result<(), Error>;
4446}
4447
4448impl JsonWebKeyExt for JsonWebKey {
4449 #[expect(unsafe_code)]
4451 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4452 let json = String::from_utf8_lossy(data);
4457
4458 let json: Vec<_> = json.encode_utf16().collect();
4460
4461 rooted!(&in(cx) let mut result = UndefinedValue());
4465 unsafe {
4466 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4467 return Err(Error::JSFailed);
4468 }
4469 }
4470
4471 let key = match JsonWebKey::new(cx, result.handle()) {
4473 Ok(ConversionResult::Success(key)) => key,
4474 Ok(ConversionResult::Failure(error)) => {
4475 return Err(Error::Type(error.into_owned()));
4476 },
4477 Err(()) => {
4478 return Err(Error::JSFailed);
4479 },
4480 };
4481
4482 if key.kty.is_none() {
4484 return Err(Error::Data(Some(
4485 "'kty' field of key is not defined".into(),
4486 )));
4487 }
4488
4489 Ok(key)
4491 }
4492
4493 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4499 rooted!(&in(cx) let mut data = UndefinedValue());
4500 self.safe_to_jsval(cx, data.handle_mut());
4501 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4502 }
4503
4504 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4505 let mut usages = vec![];
4506 for op in self.key_ops.as_ref().ok_or(Error::Data(Some(
4507 "'key_ops' member is not present in the JSON Web Key".into(),
4508 )))? {
4509 usages.push(
4510 KeyUsage::from_str(&op.str())
4511 .map_err(|_| Error::Data(Some("Unknown key usage".into())))?,
4512 );
4513 }
4514 Ok(usages)
4515 }
4516
4517 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4521 if let Some(ref key_ops) = self.key_ops {
4523 if key_ops
4526 .iter()
4527 .collect::<std::collections::HashSet<_>>()
4528 .len() <
4529 key_ops.len()
4530 {
4531 return Err(Error::Data(Some(
4532 "Duplicate key operation values are present in array".into(),
4533 )));
4534 }
4535 if let Some(ref use_) = self.use_ &&
4538 key_ops.iter().any(|op| op != use_)
4539 {
4540 return Err(Error::Data(Some(
4541 "Key operations are not consistent with intended use for Json Web Key".into(),
4542 )));
4543 }
4544
4545 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4547 if !specified_usages
4548 .iter()
4549 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4550 {
4551 return Err(Error::Data(Some(
4552 "Key operations do not contain all of the specified usage values".into(),
4553 )));
4554 }
4555 }
4556
4557 Ok(())
4558 }
4559
4560 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4562 self.key_ops = Some(
4563 usages
4564 .iter()
4565 .map(|usage| DOMString::from(usage.as_str()))
4566 .collect(),
4567 );
4568 }
4569
4570 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4573 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4574 match field {
4575 JwkStringField::X => self.x = Some(encoded_data),
4576 JwkStringField::Y => self.y = Some(encoded_data),
4577 JwkStringField::D => self.d = Some(encoded_data),
4578 JwkStringField::N => self.n = Some(encoded_data),
4579 JwkStringField::E => self.e = Some(encoded_data),
4580 JwkStringField::P => self.p = Some(encoded_data),
4581 JwkStringField::Q => self.q = Some(encoded_data),
4582 JwkStringField::DP => self.dp = Some(encoded_data),
4583 JwkStringField::DQ => self.dq = Some(encoded_data),
4584 JwkStringField::QI => self.qi = Some(encoded_data),
4585 JwkStringField::K => self.k = Some(encoded_data),
4586 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4587 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4588 }
4589 }
4590
4591 fn decode_optional_string_field(
4594 &self,
4595 field: JwkStringField,
4596 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4597 let field_string = match field {
4598 JwkStringField::X => &self.x,
4599 JwkStringField::Y => &self.y,
4600 JwkStringField::D => &self.d,
4601 JwkStringField::N => &self.n,
4602 JwkStringField::E => &self.e,
4603 JwkStringField::P => &self.p,
4604 JwkStringField::Q => &self.q,
4605 JwkStringField::DP => &self.dp,
4606 JwkStringField::DQ => &self.dq,
4607 JwkStringField::QI => &self.qi,
4608 JwkStringField::K => &self.k,
4609 JwkStringField::Priv => &self.priv_,
4610 JwkStringField::Pub => &self.pub_,
4611 };
4612
4613 field_string
4614 .as_ref()
4615 .map(|field_string| {
4616 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4617 })
4618 .transpose()
4619 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4620 }
4621
4622 fn decode_required_string_field(
4625 &self,
4626 field: JwkStringField,
4627 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4628 self.decode_optional_string_field(field)?
4629 .ok_or(Error::Data(Some(format!(
4630 "The {} field is not present in jwk",
4631 field
4632 ))))
4633 }
4634
4635 fn decode_primes_from_oth_field(
4644 &self,
4645 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4646 ) -> Result<(), Error> {
4647 if self.oth.is_some() &&
4648 (self.p.is_none() ||
4649 self.q.is_none() ||
4650 self.dp.is_none() ||
4651 self.dq.is_none() ||
4652 self.qi.is_none())
4653 {
4654 return Err(Error::Data(Some(
4655 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4656 )));
4657 }
4658
4659 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4660 let r = Base64UrlUnpadded::decode_vec(
4661 &rsa_other_prime_info
4662 .r
4663 .as_ref()
4664 .ok_or(Error::Data(Some(
4665 "The r field is not present in one of the entry of oth field in jwk"
4666 .to_string(),
4667 )))?
4668 .str(),
4669 )
4670 .map_err(|_| {
4671 Error::Data(Some(
4672 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4673 ))
4674 })?;
4675 primes.push(Zeroizing::new(r));
4676
4677 let _d = Base64UrlUnpadded::decode_vec(
4678 &rsa_other_prime_info
4679 .d
4680 .as_ref()
4681 .ok_or(Error::Data(Some(
4682 "The d field is not present in one of the entry of oth field in jwk"
4683 .to_string(),
4684 )))?
4685 .str(),
4686 )
4687 .map_err(|_| {
4688 Error::Data(Some(
4689 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4690 ))
4691 })?;
4692
4693 let _t = Base64UrlUnpadded::decode_vec(
4694 &rsa_other_prime_info
4695 .t
4696 .as_ref()
4697 .ok_or(Error::Data(Some(
4698 "The t field is not present in one of the entry of oth field in jwk"
4699 .to_string(),
4700 )))?
4701 .str(),
4702 )
4703 .map_err(|_| {
4704 Error::Data(Some(
4705 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4706 ))
4707 })?;
4708 }
4709
4710 Ok(())
4711 }
4712}
4713
4714fn normalize_algorithm<Op: Operation>(
4716 cx: &mut js::context::JSContext,
4717 algorithm: &AlgorithmIdentifier,
4718) -> Result<Op::RegisteredAlgorithm, Error> {
4719 match algorithm {
4720 ObjectOrString::String(name) => {
4722 let algorithm = Algorithm {
4726 name: name.to_owned(),
4727 };
4728 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4729 algorithm.safe_to_jsval(cx, algorithm_value.handle_mut());
4730 let algorithm_object = RootedTraceableBox::new(Heap::default());
4731 algorithm_object.set(algorithm_value.to_object());
4732 normalize_algorithm::<Op>(cx, &ObjectOrString::Object(algorithm_object))
4733 },
4734 ObjectOrString::Object(object) => {
4736 let algorithm_name = get_required_parameter::<DOMString>(
4744 cx,
4745 object.handle(),
4746 c"name",
4747 StringificationBehavior::Default,
4748 )?;
4749
4750 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4791 let normalized_algorithm =
4792 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4793
4794 Ok(normalized_algorithm)
4796 },
4797 }
4798}
4799
4800trait Operation {
4859 type RegisteredAlgorithm: NormalizedAlgorithm;
4860}
4861
4862trait NormalizedAlgorithm: Sized {
4863 fn from_object(
4865 cx: &mut js::context::JSContext,
4866 algorithm_name: CryptoAlgorithm,
4867 object: HandleObject,
4868 ) -> Fallible<Self>;
4869 fn name(&self) -> CryptoAlgorithm;
4870}
4871
4872struct EncryptOperation {}
4874
4875impl Operation for EncryptOperation {
4876 type RegisteredAlgorithm = EncryptAlgorithm;
4877}
4878
4879enum EncryptAlgorithm {
4882 RsaOaep(SubtleRsaOaepParams),
4883 AesCtr(SubtleAesCtrParams),
4884 AesCbc(SubtleAesCbcParams),
4885 AesGcm(SubtleAesGcmParams),
4886 AesOcb(SubtleAeadParams),
4887 ChaCha20Poly1305(SubtleAeadParams),
4888}
4889
4890impl NormalizedAlgorithm for EncryptAlgorithm {
4891 fn from_object(
4892 cx: &mut js::context::JSContext,
4893 algorithm_name: CryptoAlgorithm,
4894 object: HandleObject,
4895 ) -> Fallible<Self> {
4896 match algorithm_name {
4897 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4898 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4899 )),
4900 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4901 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4902 )),
4903 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4904 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4905 )),
4906 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4907 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4908 )),
4909 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4910 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4911 )),
4912 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4913 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4914 )),
4915 _ => Err(Error::NotSupported(Some(format!(
4916 "{} does not support \"encrypt\" operation",
4917 algorithm_name.as_str()
4918 )))),
4919 }
4920 }
4921
4922 fn name(&self) -> CryptoAlgorithm {
4923 match self {
4924 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4925 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4926 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4927 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4928 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4929 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4930 }
4931 }
4932}
4933
4934impl EncryptAlgorithm {
4935 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4936 match self {
4937 EncryptAlgorithm::RsaOaep(algorithm) => {
4938 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4939 },
4940 EncryptAlgorithm::AesCtr(algorithm) => {
4941 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4942 },
4943 EncryptAlgorithm::AesCbc(algorithm) => {
4944 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4945 },
4946 EncryptAlgorithm::AesGcm(algorithm) => {
4947 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4948 },
4949 EncryptAlgorithm::AesOcb(algorithm) => {
4950 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4951 },
4952 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4953 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4954 },
4955 }
4956 }
4957}
4958
4959struct DecryptOperation {}
4961
4962impl Operation for DecryptOperation {
4963 type RegisteredAlgorithm = DecryptAlgorithm;
4964}
4965
4966enum DecryptAlgorithm {
4969 RsaOaep(SubtleRsaOaepParams),
4970 AesCtr(SubtleAesCtrParams),
4971 AesCbc(SubtleAesCbcParams),
4972 AesGcm(SubtleAesGcmParams),
4973 AesOcb(SubtleAeadParams),
4974 ChaCha20Poly1305(SubtleAeadParams),
4975}
4976
4977impl NormalizedAlgorithm for DecryptAlgorithm {
4978 fn from_object(
4979 cx: &mut js::context::JSContext,
4980 algorithm_name: CryptoAlgorithm,
4981 object: HandleObject,
4982 ) -> Fallible<Self> {
4983 match algorithm_name {
4984 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4985 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4986 )),
4987 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4988 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4989 )),
4990 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4991 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4992 )),
4993 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4994 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4995 )),
4996 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4997 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4998 )),
4999 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
5000 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5001 )),
5002 _ => Err(Error::NotSupported(Some(format!(
5003 "{} does not support \"decrypt\" operation",
5004 algorithm_name.as_str()
5005 )))),
5006 }
5007 }
5008
5009 fn name(&self) -> CryptoAlgorithm {
5010 match self {
5011 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
5012 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
5013 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
5014 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
5015 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
5016 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5017 }
5018 }
5019}
5020
5021impl DecryptAlgorithm {
5022 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5023 match self {
5024 DecryptAlgorithm::RsaOaep(algorithm) => {
5025 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
5026 },
5027 DecryptAlgorithm::AesCtr(algorithm) => {
5028 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
5029 },
5030 DecryptAlgorithm::AesCbc(algorithm) => {
5031 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
5032 },
5033 DecryptAlgorithm::AesGcm(algorithm) => {
5034 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
5035 },
5036 DecryptAlgorithm::AesOcb(algorithm) => {
5037 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
5038 },
5039 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
5040 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
5041 },
5042 }
5043 }
5044}
5045
5046struct SignOperation {}
5048
5049impl Operation for SignOperation {
5050 type RegisteredAlgorithm = SignAlgorithm;
5051}
5052
5053enum SignAlgorithm {
5056 RsassaPkcs1V1_5(SubtleAlgorithm),
5057 RsaPss(SubtleRsaPssParams),
5058 Ecdsa(SubtleEcdsaParams),
5059 Ed25519(SubtleAlgorithm),
5060 Ed448(SubtleEd448Params),
5061 Hmac(SubtleAlgorithm),
5062 MlDsa(SubtleContextParams),
5063 Kmac(SubtleKmacParams),
5064}
5065
5066impl NormalizedAlgorithm for SignAlgorithm {
5067 fn from_object(
5068 cx: &mut js::context::JSContext,
5069 algorithm_name: CryptoAlgorithm,
5070 object: HandleObject,
5071 ) -> Fallible<Self> {
5072 match algorithm_name {
5073 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
5074 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5075 )),
5076 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
5077 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5078 )),
5079 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
5080 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5081 )),
5082 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
5083 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5084 )),
5085 CryptoAlgorithm::Ed448 => Ok(SignAlgorithm::Ed448(
5086 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5087 )),
5088 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
5089 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5090 )),
5091 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5092 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5093 ),
5094 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(SignAlgorithm::Kmac(
5095 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5096 )),
5097 _ => Err(Error::NotSupported(Some(format!(
5098 "{} does not support \"sign\" operation",
5099 algorithm_name.as_str()
5100 )))),
5101 }
5102 }
5103
5104 fn name(&self) -> CryptoAlgorithm {
5105 match self {
5106 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5107 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
5108 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
5109 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
5110 SignAlgorithm::Ed448(algorithm) => algorithm.name,
5111 SignAlgorithm::Hmac(algorithm) => algorithm.name,
5112 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
5113 SignAlgorithm::Kmac(algorithm) => algorithm.name,
5114 }
5115 }
5116}
5117
5118impl SignAlgorithm {
5119 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
5120 match self {
5121 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5122 rsassa_pkcs1_v1_5_operation::sign(key, message)
5123 },
5124 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
5125 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
5126 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
5127 SignAlgorithm::Ed448(algorithm) => ed448_operation::sign(algorithm, key, message),
5128 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
5129 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
5130 SignAlgorithm::Kmac(algorithm) => kmac_operation::sign(algorithm, key, message),
5131 }
5132 }
5133}
5134
5135struct VerifyOperation {}
5137
5138impl Operation for VerifyOperation {
5139 type RegisteredAlgorithm = VerifyAlgorithm;
5140}
5141
5142enum VerifyAlgorithm {
5145 RsassaPkcs1V1_5(SubtleAlgorithm),
5146 RsaPss(SubtleRsaPssParams),
5147 Ecdsa(SubtleEcdsaParams),
5148 Ed25519(SubtleAlgorithm),
5149 Ed448(SubtleEd448Params),
5150 Hmac(SubtleAlgorithm),
5151 MlDsa(SubtleContextParams),
5152 Kmac(SubtleKmacParams),
5153}
5154
5155impl NormalizedAlgorithm for VerifyAlgorithm {
5156 fn from_object(
5157 cx: &mut js::context::JSContext,
5158 algorithm_name: CryptoAlgorithm,
5159 object: HandleObject,
5160 ) -> Fallible<Self> {
5161 match algorithm_name {
5162 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
5163 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5164 )),
5165 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
5166 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5167 )),
5168 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
5169 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5170 )),
5171 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
5172 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5173 )),
5174 CryptoAlgorithm::Ed448 => Ok(VerifyAlgorithm::Ed448(
5175 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5176 )),
5177 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
5178 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5179 )),
5180 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5181 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5182 ),
5183 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(VerifyAlgorithm::Kmac(
5184 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5185 )),
5186 _ => Err(Error::NotSupported(Some(format!(
5187 "{} does not support \"verify\" operation",
5188 algorithm_name.as_str()
5189 )))),
5190 }
5191 }
5192
5193 fn name(&self) -> CryptoAlgorithm {
5194 match self {
5195 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5196 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
5197 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5198 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
5199 VerifyAlgorithm::Ed448(algorithm) => algorithm.name,
5200 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
5201 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
5202 VerifyAlgorithm::Kmac(algorithm) => algorithm.name,
5203 }
5204 }
5205}
5206
5207impl VerifyAlgorithm {
5208 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
5209 match self {
5210 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5211 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
5212 },
5213 VerifyAlgorithm::RsaPss(algorithm) => {
5214 rsa_pss_operation::verify(algorithm, key, message, signature)
5215 },
5216 VerifyAlgorithm::Ecdsa(algorithm) => {
5217 ecdsa_operation::verify(algorithm, key, message, signature)
5218 },
5219 VerifyAlgorithm::Ed25519(_algorithm) => {
5220 ed25519_operation::verify(key, message, signature)
5221 },
5222 VerifyAlgorithm::Ed448(algorithm) => {
5223 ed448_operation::verify(algorithm, key, message, signature)
5224 },
5225 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
5226 VerifyAlgorithm::MlDsa(algorithm) => {
5227 ml_dsa_operation::verify(algorithm, key, message, signature)
5228 },
5229 VerifyAlgorithm::Kmac(algorithm) => {
5230 kmac_operation::verify(algorithm, key, message, signature)
5231 },
5232 }
5233 }
5234}
5235
5236struct DigestOperation {}
5238
5239impl Operation for DigestOperation {
5240 type RegisteredAlgorithm = DigestAlgorithm;
5241}
5242
5243#[derive(Clone, MallocSizeOf)]
5246enum DigestAlgorithm {
5247 Sha(SubtleAlgorithm),
5248 Sha3(SubtleAlgorithm),
5249 CShake(SubtleCShakeParams),
5250 TurboShake(SubtleTurboShakeParams),
5251 KangarooTwelve(SubtleKangarooTwelveParams),
5252}
5253
5254impl NormalizedAlgorithm for DigestAlgorithm {
5255 fn from_object(
5256 cx: &mut js::context::JSContext,
5257 algorithm_name: CryptoAlgorithm,
5258 object: HandleObject,
5259 ) -> Fallible<Self> {
5260 match algorithm_name {
5261 CryptoAlgorithm::Sha1 |
5262 CryptoAlgorithm::Sha256 |
5263 CryptoAlgorithm::Sha384 |
5264 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
5265 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5266 )),
5267 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5268 Ok(DigestAlgorithm::Sha3(
5269 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5270 ))
5271 },
5272 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5273 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5274 )),
5275 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5276 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5277 ),
5278 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5279 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5280 )),
5281 _ => Err(Error::NotSupported(Some(format!(
5282 "{} does not support \"digest\" operation",
5283 algorithm_name.as_str()
5284 )))),
5285 }
5286 }
5287
5288 fn name(&self) -> CryptoAlgorithm {
5289 match self {
5290 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5291 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5292 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5293 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5294 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5295 }
5296 }
5297}
5298
5299impl DigestAlgorithm {
5300 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5301 match self {
5302 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5303 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5304 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5305 DigestAlgorithm::TurboShake(algorithm) => {
5306 turboshake_operation::digest(algorithm, message)
5307 },
5308 DigestAlgorithm::KangarooTwelve(algorithm) => {
5309 kangarootwelve_operation::digest(algorithm, message)
5310 },
5311 }
5312 }
5313}
5314
5315impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5316 type Error = ();
5317
5318 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5319 match value {
5320 SerializableDigestAlgorithm::Sha(algorithm) => {
5321 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5322 },
5323 SerializableDigestAlgorithm::Sha3(algorithm) => {
5324 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5325 },
5326 SerializableDigestAlgorithm::CShake(algorithm) => {
5327 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5328 },
5329 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5330 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5331 },
5332 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5333 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5334 },
5335 }
5336 }
5337}
5338
5339impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5340 fn from(value: &DigestAlgorithm) -> Self {
5341 match value {
5342 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5343 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5344 DigestAlgorithm::CShake(algorithm) => {
5345 SerializableDigestAlgorithm::CShake(algorithm.into())
5346 },
5347 DigestAlgorithm::TurboShake(algorithm) => {
5348 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5349 },
5350 DigestAlgorithm::KangarooTwelve(algorithm) => {
5351 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5352 },
5353 }
5354 }
5355}
5356
5357struct DeriveBitsOperation {}
5359
5360impl Operation for DeriveBitsOperation {
5361 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5362}
5363
5364enum DeriveBitsAlgorithm {
5367 Ecdh(SubtleEcdhKeyDeriveParams),
5368 X25519(SubtleEcdhKeyDeriveParams),
5369 X448(SubtleEcdhKeyDeriveParams),
5370 Hkdf(SubtleHkdfParams),
5371 Pbkdf2(SubtlePbkdf2Params),
5372 Argon2(SubtleArgon2Params),
5373}
5374
5375impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5376 fn from_object(
5377 cx: &mut js::context::JSContext,
5378 algorithm_name: CryptoAlgorithm,
5379 object: HandleObject,
5380 ) -> Fallible<Self> {
5381 match algorithm_name {
5382 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5383 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5384 )),
5385 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5386 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5387 )),
5388 CryptoAlgorithm::X448 => Ok(DeriveBitsAlgorithm::X448(
5389 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5390 )),
5391 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5392 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5393 )),
5394 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5395 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5396 )),
5397 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5398 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5399 ),
5400 _ => Err(Error::NotSupported(Some(format!(
5401 "{} does not support \"deriveBits\" operation",
5402 algorithm_name.as_str()
5403 )))),
5404 }
5405 }
5406
5407 fn name(&self) -> CryptoAlgorithm {
5408 match self {
5409 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5410 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5411 DeriveBitsAlgorithm::X448(algorithm) => algorithm.name,
5412 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5413 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5414 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5415 }
5416 }
5417}
5418
5419impl DeriveBitsAlgorithm {
5420 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5421 match self {
5422 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5423 ecdh_operation::derive_bits(algorithm, key, length)
5424 },
5425 DeriveBitsAlgorithm::X25519(algorithm) => {
5426 x25519_operation::derive_bits(algorithm, key, length)
5427 },
5428 DeriveBitsAlgorithm::X448(algorithm) => {
5429 x448_operation::derive_bits(algorithm, key, length)
5430 },
5431 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5432 hkdf_operation::derive_bits(algorithm, key, length)
5433 },
5434 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5435 pbkdf2_operation::derive_bits(algorithm, key, length)
5436 },
5437 DeriveBitsAlgorithm::Argon2(algorithm) => {
5438 argon2_operation::derive_bits(algorithm, key, length)
5439 },
5440 }
5441 }
5442}
5443
5444struct WrapKeyOperation {}
5446
5447impl Operation for WrapKeyOperation {
5448 type RegisteredAlgorithm = WrapKeyAlgorithm;
5449}
5450
5451enum WrapKeyAlgorithm {
5454 AesKw(SubtleAlgorithm),
5455}
5456
5457impl NormalizedAlgorithm for WrapKeyAlgorithm {
5458 fn from_object(
5459 cx: &mut js::context::JSContext,
5460 algorithm_name: CryptoAlgorithm,
5461 object: HandleObject,
5462 ) -> Fallible<Self> {
5463 match algorithm_name {
5464 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5465 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5466 )),
5467 _ => Err(Error::NotSupported(Some(format!(
5468 "{} does not support \"wrapKey\" operation",
5469 algorithm_name.as_str()
5470 )))),
5471 }
5472 }
5473
5474 fn name(&self) -> CryptoAlgorithm {
5475 match self {
5476 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5477 }
5478 }
5479}
5480
5481impl WrapKeyAlgorithm {
5482 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5483 match self {
5484 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5485 }
5486 }
5487}
5488
5489struct UnwrapKeyOperation {}
5491
5492impl Operation for UnwrapKeyOperation {
5493 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5494}
5495
5496enum UnwrapKeyAlgorithm {
5499 AesKw(SubtleAlgorithm),
5500}
5501
5502impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5503 fn from_object(
5504 cx: &mut js::context::JSContext,
5505 algorithm_name: CryptoAlgorithm,
5506 object: HandleObject,
5507 ) -> Fallible<Self> {
5508 match algorithm_name {
5509 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5510 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5511 )),
5512 _ => Err(Error::NotSupported(Some(format!(
5513 "{} does not support \"unwrapKey\" operation",
5514 algorithm_name.as_str()
5515 )))),
5516 }
5517 }
5518
5519 fn name(&self) -> CryptoAlgorithm {
5520 match self {
5521 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5522 }
5523 }
5524}
5525
5526impl UnwrapKeyAlgorithm {
5527 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5528 match self {
5529 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5530 }
5531 }
5532}
5533
5534struct GenerateKeyOperation {}
5536
5537impl Operation for GenerateKeyOperation {
5538 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5539}
5540
5541enum GenerateKeyAlgorithm {
5544 RsassaPkcs1V1_5(SubtleRsaHashedKeyGenParams),
5545 RsaPss(SubtleRsaHashedKeyGenParams),
5546 RsaOaep(SubtleRsaHashedKeyGenParams),
5547 Ecdsa(SubtleEcKeyGenParams),
5548 Ecdh(SubtleEcKeyGenParams),
5549 Ed25519(SubtleAlgorithm),
5550 X25519(SubtleAlgorithm),
5551 Ed448(SubtleAlgorithm),
5552 X448(SubtleAlgorithm),
5553 AesCtr(SubtleAesKeyGenParams),
5554 AesCbc(SubtleAesKeyGenParams),
5555 AesGcm(SubtleAesKeyGenParams),
5556 AesKw(SubtleAesKeyGenParams),
5557 Hmac(SubtleHmacKeyGenParams),
5558 MlKem(SubtleAlgorithm),
5559 MlDsa(SubtleAlgorithm),
5560 AesOcb(SubtleAesKeyGenParams),
5561 ChaCha20Poly1305(SubtleAlgorithm),
5562 Kmac(SubtleKmacKeyGenParams),
5563}
5564
5565impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5566 fn from_object(
5567 cx: &mut js::context::JSContext,
5568 algorithm_name: CryptoAlgorithm,
5569 object: HandleObject,
5570 ) -> Fallible<Self> {
5571 match algorithm_name {
5572 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5573 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5574 )),
5575 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5576 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5577 )),
5578 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5579 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5580 )),
5581 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5582 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5583 )),
5584 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5585 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5586 )),
5587 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5588 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5589 )),
5590 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5591 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5592 )),
5593 CryptoAlgorithm::Ed448 => Ok(GenerateKeyAlgorithm::Ed448(
5594 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5595 )),
5596 CryptoAlgorithm::X448 => Ok(GenerateKeyAlgorithm::X448(
5597 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5598 )),
5599 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5600 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5601 )),
5602 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5603 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5604 )),
5605 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5606 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5607 )),
5608 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5609 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5610 )),
5611 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5612 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5613 )),
5614 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5615 Ok(GenerateKeyAlgorithm::MlKem(
5616 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5617 ))
5618 },
5619 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5620 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5621 ),
5622 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5623 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5624 )),
5625 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5626 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5627 )),
5628 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GenerateKeyAlgorithm::Kmac(
5629 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5630 )),
5631 _ => Err(Error::NotSupported(Some(format!(
5632 "{} does not support \"generateKey\" operation",
5633 algorithm_name.as_str()
5634 )))),
5635 }
5636 }
5637
5638 fn name(&self) -> CryptoAlgorithm {
5639 match self {
5640 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5641 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5642 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5643 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5644 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5645 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5646 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5647 GenerateKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5648 GenerateKeyAlgorithm::X448(algorithm) => algorithm.name,
5649 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5650 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5651 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5652 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5653 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5654 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5655 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5656 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5657 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5658 GenerateKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5659 }
5660 }
5661}
5662
5663impl GenerateKeyAlgorithm {
5664 fn generate_key(
5665 &self,
5666 cx: &mut js::context::JSContext,
5667 global: &GlobalScope,
5668 extractable: bool,
5669 usages: Vec<KeyUsage>,
5670 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5671 match self {
5672 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5673 rsassa_pkcs1_v1_5_operation::generate_key(
5674 cx,
5675 global,
5676 algorithm,
5677 extractable,
5678 usages,
5679 )
5680 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5681 },
5682 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5683 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5684 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5685 },
5686 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5687 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5688 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5689 },
5690 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5691 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5692 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5693 },
5694 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5695 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5696 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5697 },
5698 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5699 ed25519_operation::generate_key(cx, global, extractable, usages)
5700 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5701 },
5702 GenerateKeyAlgorithm::X25519(_algorithm) => {
5703 x25519_operation::generate_key(cx, global, extractable, usages)
5704 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5705 },
5706 GenerateKeyAlgorithm::Ed448(_algorithm) => {
5707 ed448_operation::generate_key(cx, global, extractable, usages)
5708 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5709 },
5710 GenerateKeyAlgorithm::X448(_algorithm) => {
5711 x448_operation::generate_key(cx, global, extractable, usages)
5712 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5713 },
5714 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5715 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5716 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5717 },
5718 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5719 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5720 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5721 },
5722 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5723 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5724 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5725 },
5726 GenerateKeyAlgorithm::AesKw(algorithm) => {
5727 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5728 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5729 },
5730 GenerateKeyAlgorithm::Hmac(algorithm) => {
5731 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5732 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5733 },
5734 GenerateKeyAlgorithm::MlKem(algorithm) => {
5735 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5736 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5737 },
5738 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5739 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5740 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5741 },
5742 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5743 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5744 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5745 },
5746 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5747 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5748 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5749 },
5750 GenerateKeyAlgorithm::Kmac(algorithm) => {
5751 kmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5752 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5753 },
5754 }
5755 }
5756}
5757
5758struct ImportKeyOperation {}
5760
5761impl Operation for ImportKeyOperation {
5762 type RegisteredAlgorithm = ImportKeyAlgorithm;
5763}
5764
5765enum ImportKeyAlgorithm {
5768 RsassaPkcs1V1_5(SubtleRsaHashedImportParams),
5769 RsaPss(SubtleRsaHashedImportParams),
5770 RsaOaep(SubtleRsaHashedImportParams),
5771 Ecdsa(SubtleEcKeyImportParams),
5772 Ecdh(SubtleEcKeyImportParams),
5773 Ed25519(SubtleAlgorithm),
5774 X25519(SubtleAlgorithm),
5775 Ed448(SubtleAlgorithm),
5776 X448(SubtleAlgorithm),
5777 AesCtr(SubtleAlgorithm),
5778 AesCbc(SubtleAlgorithm),
5779 AesGcm(SubtleAlgorithm),
5780 AesKw(SubtleAlgorithm),
5781 Hmac(SubtleHmacImportParams),
5782 Hkdf(SubtleAlgorithm),
5783 Pbkdf2(SubtleAlgorithm),
5784 MlKem(SubtleAlgorithm),
5785 MlDsa(SubtleAlgorithm),
5786 AesOcb(SubtleAlgorithm),
5787 ChaCha20Poly1305(SubtleAlgorithm),
5788 Kmac(SubtleKmacImportParams),
5789 Argon2(SubtleAlgorithm),
5790}
5791
5792impl NormalizedAlgorithm for ImportKeyAlgorithm {
5793 fn from_object(
5794 cx: &mut js::context::JSContext,
5795 algorithm_name: CryptoAlgorithm,
5796 object: HandleObject,
5797 ) -> Fallible<Self> {
5798 match algorithm_name {
5799 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5800 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5801 )),
5802 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5803 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5804 )),
5805 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5806 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5807 )),
5808 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5809 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5810 )),
5811 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5812 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5813 )),
5814 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5815 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5816 )),
5817 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5818 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5819 )),
5820 CryptoAlgorithm::Ed448 => Ok(ImportKeyAlgorithm::Ed448(
5821 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5822 )),
5823 CryptoAlgorithm::X448 => Ok(ImportKeyAlgorithm::X448(
5824 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5825 )),
5826 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5827 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5828 )),
5829 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5830 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5831 )),
5832 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5833 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5834 )),
5835 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5836 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5837 )),
5838 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5839 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5840 )),
5841 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5842 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5843 )),
5844 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5845 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5846 )),
5847 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5848 Ok(ImportKeyAlgorithm::MlKem(
5849 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5850 ))
5851 },
5852 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5853 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5854 ),
5855 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5856 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5857 )),
5858 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5859 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5860 )),
5861 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ImportKeyAlgorithm::Kmac(
5862 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5863 )),
5864 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5865 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5866 ),
5867 _ => Err(Error::NotSupported(Some(format!(
5868 "{} does not support \"importKey\" operation",
5869 algorithm_name.as_str()
5870 )))),
5871 }
5872 }
5873
5874 fn name(&self) -> CryptoAlgorithm {
5875 match self {
5876 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5877 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5878 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5879 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5880 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5881 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5882 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
5883 ImportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5884 ImportKeyAlgorithm::X448(algorithm) => algorithm.name,
5885 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5886 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5887 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5888 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5889 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5890 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
5891 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5892 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5893 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5894 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5895 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5896 ImportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5897 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
5898 }
5899 }
5900}
5901
5902impl ImportKeyAlgorithm {
5903 fn import_key(
5904 &self,
5905 cx: &mut js::context::JSContext,
5906 global: &GlobalScope,
5907 format: KeyFormat,
5908 key_data: &[u8],
5909 extractable: bool,
5910 usages: Vec<KeyUsage>,
5911 ) -> Result<DomRoot<CryptoKey>, Error> {
5912 match self {
5913 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5914 rsassa_pkcs1_v1_5_operation::import_key(
5915 cx,
5916 global,
5917 algorithm,
5918 format,
5919 key_data,
5920 extractable,
5921 usages,
5922 )
5923 },
5924 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
5925 cx,
5926 global,
5927 algorithm,
5928 format,
5929 key_data,
5930 extractable,
5931 usages,
5932 ),
5933 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
5934 cx,
5935 global,
5936 algorithm,
5937 format,
5938 key_data,
5939 extractable,
5940 usages,
5941 ),
5942 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
5943 cx,
5944 global,
5945 algorithm,
5946 format,
5947 key_data,
5948 extractable,
5949 usages,
5950 ),
5951 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
5952 cx,
5953 global,
5954 algorithm,
5955 format,
5956 key_data,
5957 extractable,
5958 usages,
5959 ),
5960 ImportKeyAlgorithm::Ed25519(_algorithm) => {
5961 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5962 },
5963 ImportKeyAlgorithm::X25519(_algorithm) => {
5964 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
5965 },
5966 ImportKeyAlgorithm::Ed448(_algorithm) => {
5967 ed448_operation::import_key(cx, global, format, key_data, extractable, usages)
5968 },
5969 ImportKeyAlgorithm::X448(_algorithm) => {
5970 x448_operation::import_key(cx, global, format, key_data, extractable, usages)
5971 },
5972 ImportKeyAlgorithm::AesCtr(_algorithm) => {
5973 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
5974 },
5975 ImportKeyAlgorithm::AesCbc(_algorithm) => {
5976 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
5977 },
5978 ImportKeyAlgorithm::AesGcm(_algorithm) => {
5979 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
5980 },
5981 ImportKeyAlgorithm::AesKw(_algorithm) => {
5982 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
5983 },
5984 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
5985 cx,
5986 global,
5987 algorithm,
5988 format,
5989 key_data,
5990 extractable,
5991 usages,
5992 ),
5993 ImportKeyAlgorithm::Hkdf(_algorithm) => {
5994 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
5995 },
5996 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
5997 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
5998 },
5999 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
6000 cx,
6001 global,
6002 algorithm,
6003 format,
6004 key_data,
6005 extractable,
6006 usages,
6007 ),
6008 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
6009 cx,
6010 global,
6011 algorithm,
6012 format,
6013 key_data,
6014 extractable,
6015 usages,
6016 ),
6017 ImportKeyAlgorithm::AesOcb(_algorithm) => {
6018 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
6019 },
6020 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6021 chacha20_poly1305_operation::import_key(
6022 cx,
6023 global,
6024 format,
6025 key_data,
6026 extractable,
6027 usages,
6028 )
6029 },
6030 ImportKeyAlgorithm::Kmac(algorithm) => kmac_operation::import_key(
6031 cx,
6032 global,
6033 algorithm,
6034 format,
6035 key_data,
6036 extractable,
6037 usages,
6038 ),
6039 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
6040 cx,
6041 global,
6042 algorithm,
6043 format,
6044 key_data,
6045 extractable,
6046 usages,
6047 ),
6048 }
6049 }
6050}
6051
6052struct ExportKeyOperation {}
6054
6055impl Operation for ExportKeyOperation {
6056 type RegisteredAlgorithm = ExportKeyAlgorithm;
6057}
6058
6059enum ExportKeyAlgorithm {
6062 RsassaPkcs1V1_5(SubtleAlgorithm),
6063 RsaPss(SubtleAlgorithm),
6064 RsaOaep(SubtleAlgorithm),
6065 Ecdsa(SubtleAlgorithm),
6066 Ecdh(SubtleAlgorithm),
6067 Ed25519(SubtleAlgorithm),
6068 X25519(SubtleAlgorithm),
6069 Ed448(SubtleAlgorithm),
6070 X448(SubtleAlgorithm),
6071 AesCtr(SubtleAlgorithm),
6072 AesCbc(SubtleAlgorithm),
6073 AesGcm(SubtleAlgorithm),
6074 AesKw(SubtleAlgorithm),
6075 Hmac(SubtleAlgorithm),
6076 MlKem(SubtleAlgorithm),
6077 MlDsa(SubtleAlgorithm),
6078 AesOcb(SubtleAlgorithm),
6079 ChaCha20Poly1305(SubtleAlgorithm),
6080 Kmac(SubtleAlgorithm),
6081}
6082
6083impl NormalizedAlgorithm for ExportKeyAlgorithm {
6084 fn from_object(
6085 cx: &mut js::context::JSContext,
6086 algorithm_name: CryptoAlgorithm,
6087 object: HandleObject,
6088 ) -> Fallible<Self> {
6089 match algorithm_name {
6090 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
6091 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6092 )),
6093 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
6094 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6095 )),
6096 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
6097 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6098 )),
6099 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
6100 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6101 )),
6102 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
6103 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6104 )),
6105 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
6106 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6107 )),
6108 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
6109 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6110 )),
6111 CryptoAlgorithm::Ed448 => Ok(ExportKeyAlgorithm::Ed448(
6112 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6113 )),
6114 CryptoAlgorithm::X448 => Ok(ExportKeyAlgorithm::X448(
6115 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6116 )),
6117 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
6118 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6119 )),
6120 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
6121 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6122 )),
6123 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
6124 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6125 )),
6126 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
6127 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6128 )),
6129 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
6130 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6131 )),
6132 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6133 Ok(ExportKeyAlgorithm::MlKem(
6134 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6135 ))
6136 },
6137 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6138 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6139 ),
6140 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
6141 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6142 )),
6143 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
6144 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6145 )),
6146 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ExportKeyAlgorithm::Kmac(
6147 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6148 )),
6149 _ => Err(Error::NotSupported(Some(format!(
6150 "{} does not support \"exportKey\" operation",
6151 algorithm_name.as_str()
6152 )))),
6153 }
6154 }
6155
6156 fn name(&self) -> CryptoAlgorithm {
6157 match self {
6158 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6159 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6160 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6161 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6162 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6163 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6164 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6165 ExportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6166 ExportKeyAlgorithm::X448(algorithm) => algorithm.name,
6167 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6168 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6169 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6170 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6171 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6172 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6173 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6174 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6175 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6176 ExportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6177 }
6178 }
6179}
6180
6181impl ExportKeyAlgorithm {
6182 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
6183 match self {
6184 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
6185 rsassa_pkcs1_v1_5_operation::export_key(format, key)
6186 },
6187 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
6188 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
6189 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
6190 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
6191 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
6192 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
6193 ExportKeyAlgorithm::Ed448(_algorithm) => ed448_operation::export_key(format, key),
6194 ExportKeyAlgorithm::X448(_algorithm) => x448_operation::export_key(format, key),
6195 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
6196 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
6197 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
6198 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
6199 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
6200 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
6201 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
6202 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
6203 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6204 chacha20_poly1305_operation::export_key(format, key)
6205 },
6206 ExportKeyAlgorithm::Kmac(_algorithm) => kmac_operation::export_key(format, key),
6207 }
6208 }
6209}
6210
6211struct GetKeyLengthOperation {}
6213
6214impl Operation for GetKeyLengthOperation {
6215 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
6216}
6217
6218enum GetKeyLengthAlgorithm {
6221 AesCtr(SubtleAesDerivedKeyParams),
6222 AesCbc(SubtleAesDerivedKeyParams),
6223 AesGcm(SubtleAesDerivedKeyParams),
6224 AesKw(SubtleAesDerivedKeyParams),
6225 Hmac(SubtleHmacImportParams),
6226 Hkdf(SubtleAlgorithm),
6227 Pbkdf2(SubtleAlgorithm),
6228 AesOcb(SubtleAesDerivedKeyParams),
6229 ChaCha20Poly1305(SubtleAlgorithm),
6230 Kmac(SubtleKmacImportParams),
6231 Argon2(SubtleAlgorithm),
6232}
6233
6234impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
6235 fn from_object(
6236 cx: &mut js::context::JSContext,
6237 algorithm_name: CryptoAlgorithm,
6238 object: HandleObject,
6239 ) -> Fallible<Self> {
6240 match algorithm_name {
6241 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
6242 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6243 )),
6244 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
6245 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6246 )),
6247 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
6248 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6249 )),
6250 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
6251 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6252 )),
6253 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
6254 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6255 )),
6256 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
6257 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6258 )),
6259 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
6260 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6261 )),
6262 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
6263 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6264 )),
6265 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
6266 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6267 )),
6268 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GetKeyLengthAlgorithm::Kmac(
6269 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6270 )),
6271 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
6272 Ok(GetKeyLengthAlgorithm::Argon2(
6273 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6274 ))
6275 },
6276 _ => Err(Error::NotSupported(Some(format!(
6277 "{} does not support \"get key length\" operation",
6278 algorithm_name.as_str()
6279 )))),
6280 }
6281 }
6282
6283 fn name(&self) -> CryptoAlgorithm {
6284 match self {
6285 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
6286 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
6287 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
6288 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
6289 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
6290 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
6291 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6292 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
6293 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6294 GetKeyLengthAlgorithm::Kmac(algorithm) => algorithm.name,
6295 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
6296 }
6297 }
6298}
6299
6300impl GetKeyLengthAlgorithm {
6301 fn get_key_length(&self) -> Result<Option<u32>, Error> {
6302 match self {
6303 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
6304 aes_ctr_operation::get_key_length(algorithm)
6305 },
6306 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
6307 aes_cbc_operation::get_key_length(algorithm)
6308 },
6309 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
6310 aes_gcm_operation::get_key_length(algorithm)
6311 },
6312 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
6313 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
6314 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
6315 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
6316 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
6317 aes_ocb_operation::get_key_length(algorithm)
6318 },
6319 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
6320 chacha20_poly1305_operation::get_key_length()
6321 },
6322 GetKeyLengthAlgorithm::Kmac(algorithm) => kmac_operation::get_key_length(algorithm),
6323 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
6324 }
6325 }
6326}
6327
6328struct EncapsulateOperation {}
6330
6331impl Operation for EncapsulateOperation {
6332 type RegisteredAlgorithm = EncapsulateAlgorithm;
6333}
6334
6335enum EncapsulateAlgorithm {
6338 MlKem(SubtleAlgorithm),
6339}
6340
6341impl NormalizedAlgorithm for EncapsulateAlgorithm {
6342 fn from_object(
6343 cx: &mut js::context::JSContext,
6344 algorithm_name: CryptoAlgorithm,
6345 object: HandleObject,
6346 ) -> Fallible<Self> {
6347 match algorithm_name {
6348 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6349 Ok(EncapsulateAlgorithm::MlKem(
6350 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6351 ))
6352 },
6353 _ => Err(Error::NotSupported(Some(format!(
6354 "{} does not support \"encapsulate\" operation",
6355 algorithm_name.as_str()
6356 )))),
6357 }
6358 }
6359
6360 fn name(&self) -> CryptoAlgorithm {
6361 match self {
6362 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6363 }
6364 }
6365}
6366
6367impl EncapsulateAlgorithm {
6368 fn encapsulate(&self, key: &CryptoKey) -> Result<SubtleEncapsulatedBits, Error> {
6369 match self {
6370 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6371 }
6372 }
6373}
6374
6375struct DecapsulateOperation {}
6377
6378impl Operation for DecapsulateOperation {
6379 type RegisteredAlgorithm = DecapsulateAlgorithm;
6380}
6381
6382enum DecapsulateAlgorithm {
6385 MlKem(SubtleAlgorithm),
6386}
6387
6388impl NormalizedAlgorithm for DecapsulateAlgorithm {
6389 fn from_object(
6390 cx: &mut js::context::JSContext,
6391 algorithm_name: CryptoAlgorithm,
6392 object: HandleObject,
6393 ) -> Fallible<Self> {
6394 match algorithm_name {
6395 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6396 Ok(DecapsulateAlgorithm::MlKem(
6397 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6398 ))
6399 },
6400 _ => Err(Error::NotSupported(Some(format!(
6401 "{} does not support \"decapsulate\" operation",
6402 algorithm_name.as_str()
6403 )))),
6404 }
6405 }
6406
6407 fn name(&self) -> CryptoAlgorithm {
6408 match self {
6409 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6410 }
6411 }
6412}
6413
6414impl DecapsulateAlgorithm {
6415 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
6416 match self {
6417 DecapsulateAlgorithm::MlKem(algorithm) => {
6418 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6419 },
6420 }
6421 }
6422}
6423
6424struct GetPublicKeyOperation {}
6426
6427impl Operation for GetPublicKeyOperation {
6428 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6429}
6430
6431enum GetPublicKeyAlgorithm {
6434 RsassaPkcs1v1_5(SubtleAlgorithm),
6435 RsaPss(SubtleAlgorithm),
6436 RsaOaep(SubtleAlgorithm),
6437 Ecdsa(SubtleAlgorithm),
6438 Ecdh(SubtleAlgorithm),
6439 Ed25519(SubtleAlgorithm),
6440 X25519(SubtleAlgorithm),
6441 Ed448(SubtleAlgorithm),
6442 X448(SubtleAlgorithm),
6443 MlKem(SubtleAlgorithm),
6444 MlDsa(SubtleAlgorithm),
6445}
6446
6447impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6448 fn from_object(
6449 cx: &mut js::context::JSContext,
6450 algorithm_name: CryptoAlgorithm,
6451 object: HandleObject,
6452 ) -> Fallible<Self> {
6453 match algorithm_name {
6454 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6455 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6456 )),
6457 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6458 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6459 )),
6460 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6461 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6462 )),
6463 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6464 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6465 )),
6466 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6467 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6468 )),
6469 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6470 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6471 )),
6472 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6473 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6474 )),
6475 CryptoAlgorithm::Ed448 => Ok(GetPublicKeyAlgorithm::Ed448(
6476 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6477 )),
6478 CryptoAlgorithm::X448 => Ok(GetPublicKeyAlgorithm::X448(
6479 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6480 )),
6481 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6482 Ok(GetPublicKeyAlgorithm::MlKem(
6483 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6484 ))
6485 },
6486 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6487 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6488 ),
6489 _ => Err(Error::NotSupported(Some(format!(
6490 "{} does not support \"getPublicKey\" operation",
6491 algorithm_name.as_str()
6492 )))),
6493 }
6494 }
6495
6496 fn name(&self) -> CryptoAlgorithm {
6497 match self {
6498 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6499 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6500 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6501 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6502 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6503 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6504 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6505 GetPublicKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6506 GetPublicKeyAlgorithm::X448(algorithm) => algorithm.name,
6507 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6508 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6509 }
6510 }
6511}
6512
6513impl GetPublicKeyAlgorithm {
6514 fn get_public_key(
6515 &self,
6516 cx: &mut js::context::JSContext,
6517 global: &GlobalScope,
6518 key: &CryptoKey,
6519 algorithm: &KeyAlgorithmAndDerivatives,
6520 usages: Vec<KeyUsage>,
6521 ) -> Result<DomRoot<CryptoKey>, Error> {
6522 match self {
6523 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6524 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6525 },
6526 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6527 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6528 },
6529 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6530 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6531 },
6532 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6533 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6534 },
6535 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6536 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6537 },
6538 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6539 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6540 },
6541 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6542 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6543 },
6544 GetPublicKeyAlgorithm::Ed448(_algorithm) => {
6545 ed448_operation::get_public_key(cx, global, key, algorithm, usages)
6546 },
6547 GetPublicKeyAlgorithm::X448(_algorithm) => {
6548 x448_operation::get_public_key(cx, global, key, algorithm, usages)
6549 },
6550 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6551 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6552 },
6553 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6554 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6555 },
6556 }
6557 }
6558}