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 as AlgorithmWithDOMString, AlgorithmIdentifier, JsonWebKey, KeyFormat,
67 SubtleCryptoMethods,
68};
69use crate::dom::bindings::codegen::UnionTypes::{
70 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
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.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: EncapsulatedKey,
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: EncapsulatedBits,
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 = EncapsulatedKey {
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_static(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_static(
2439 normalized_algorithm.name().as_str(),
2440 )),
2441 )
2442 .is_ok();
2443 }
2444
2445 match operation {
2491 "encrypt" => {
2492 let Ok(normalized_algorithm) = normalize_algorithm::<EncryptOperation>(cx, algorithm)
2493 else {
2494 return false;
2495 };
2496
2497 match normalized_algorithm {
2498 EncryptAlgorithm::RsaOaep(_) => true,
2499 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
2500 normalized_algorithm.counter.len() == 16 &&
2501 normalized_algorithm.length != 0 &&
2502 normalized_algorithm.length <= 128
2503 },
2504 EncryptAlgorithm::AesCbc(normalized_algorithm) => {
2505 normalized_algorithm.iv.len() == 16
2506 },
2507 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
2508 normalized_algorithm.iv.len() <= u64::MAX as usize &&
2509 normalized_algorithm
2510 .additional_data
2511 .is_none_or(|additional_data| {
2512 additional_data.len() <= u64::MAX as usize
2513 }) &&
2514 normalized_algorithm.tag_length.is_none_or(|length| {
2515 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
2516 })
2517 },
2518 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
2519 normalized_algorithm.iv.len() <= 15 &&
2520 normalized_algorithm
2521 .tag_length
2522 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2523 },
2524 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2525 normalized_algorithm.iv.len() == 12 &&
2526 normalized_algorithm
2527 .tag_length
2528 .is_none_or(|length| length == 128)
2529 },
2530 }
2531 },
2532 "decrypt" => {
2533 let Ok(normalized_algorithm) = normalize_algorithm::<DecryptOperation>(cx, algorithm)
2534 else {
2535 return false;
2536 };
2537
2538 match normalized_algorithm {
2539 DecryptAlgorithm::RsaOaep(_) => true,
2540 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
2541 normalized_algorithm.counter.len() == 16 &&
2542 normalized_algorithm.length != 0 &&
2543 normalized_algorithm.length <= 128
2544 },
2545 DecryptAlgorithm::AesCbc(normalized_algorithm) => {
2546 normalized_algorithm.iv.len() == 16
2547 },
2548 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
2549 normalized_algorithm
2550 .tag_length
2551 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
2552 normalized_algorithm.iv.len() <= u64::MAX as usize &&
2553 normalized_algorithm
2554 .additional_data
2555 .is_none_or(|additional_data| {
2556 additional_data.len() <= u64::MAX as usize
2557 })
2558 },
2559 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
2560 normalized_algorithm.iv.len() <= 15 &&
2561 normalized_algorithm
2562 .tag_length
2563 .is_none_or(|length| matches!(length, 64 | 96 | 128))
2564 },
2565 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
2566 normalized_algorithm.iv.len() == 12 &&
2567 normalized_algorithm
2568 .tag_length
2569 .is_none_or(|length| length == 128)
2570 },
2571 }
2572 },
2573 "sign" => {
2574 let Ok(normalized_algorithm) = normalize_algorithm::<SignOperation>(cx, algorithm)
2575 else {
2576 return false;
2577 };
2578
2579 match normalized_algorithm {
2580 SignAlgorithm::RsassaPkcs1V1_5(_) |
2581 SignAlgorithm::RsaPss(_) |
2582 SignAlgorithm::Ecdsa(_) |
2583 SignAlgorithm::Ed25519(_) => true,
2584 SignAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2585 .context
2586 .is_none_or(|context| context.len() <= 255),
2587 SignAlgorithm::Hmac(_) | SignAlgorithm::MlDsa(_) | SignAlgorithm::Kmac(_) => true,
2588 }
2589 },
2590 "verify" => {
2591 let Ok(normalized_algorithm) = normalize_algorithm::<VerifyOperation>(cx, algorithm)
2592 else {
2593 return false;
2594 };
2595
2596 match normalized_algorithm {
2597 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
2598 VerifyAlgorithm::RsaPss(_) |
2599 VerifyAlgorithm::Ecdsa(_) |
2600 VerifyAlgorithm::Ed25519(_) => true,
2601 VerifyAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
2602 .context
2603 .is_none_or(|context| context.len() <= 255),
2604 VerifyAlgorithm::Hmac(_) | VerifyAlgorithm::MlDsa(_) | VerifyAlgorithm::Kmac(_) => {
2605 true
2606 },
2607 }
2608 },
2609 "digest" => {
2610 let Ok(normalized_algorithm) = normalize_algorithm::<DigestOperation>(cx, algorithm)
2611 else {
2612 return false;
2613 };
2614
2615 match normalized_algorithm {
2616 DigestAlgorithm::Sha(_) |
2617 DigestAlgorithm::Sha3(_) |
2618 DigestAlgorithm::CShake(_) |
2619 DigestAlgorithm::TurboShake(_) => true,
2620 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
2621 normalized_algorithm.output_length != 0 &&
2622 normalized_algorithm.output_length.is_multiple_of(8)
2623 },
2624 }
2625 },
2626 "deriveBits" => {
2627 let Ok(normalized_algorithm) =
2628 normalize_algorithm::<DeriveBitsOperation>(cx, algorithm)
2629 else {
2630 return false;
2631 };
2632
2633 match normalized_algorithm {
2634 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => {
2635 let public_key = normalized_algorithm.public.root();
2636 let Ok(maximum_length) = ecdh_operation::maximum_length(&public_key) else {
2637 return false;
2638 };
2639 public_key.Type() == KeyType::Public &&
2640 public_key.algorithm().name() == normalized_algorithm.name &&
2641 length.is_none_or(|length| length <= maximum_length)
2642 },
2643 DeriveBitsAlgorithm::X25519(normalized_algorithm) => {
2644 let public_key = normalized_algorithm.public.root();
2645 public_key.Type() == KeyType::Public &&
2646 public_key.algorithm().name() == normalized_algorithm.name &&
2647 length.is_none_or(|length| length <= 256)
2648 },
2649 DeriveBitsAlgorithm::X448(_) => {
2650 length.is_none_or(|length| x448_operation::SECRET_LENGTH as u32 * 8 >= length)
2651 },
2652 DeriveBitsAlgorithm::Hkdf(normalized_algorithm) => {
2653 let hash_length = match normalized_algorithm.hash.name() {
2654 CryptoAlgorithm::Sha1 => 160,
2655 CryptoAlgorithm::Sha256 => 256,
2656 CryptoAlgorithm::Sha384 => 384,
2657 CryptoAlgorithm::Sha512 => 512,
2658 _ => return false,
2659 };
2660 length.is_some_and(|length| length % 8 == 0 && length <= 255 * hash_length)
2661 },
2662 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
2663 length.is_some_and(|length| length % 8 == 0) &&
2664 normalized_algorithm.iterations != 0
2665 },
2666 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
2667 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
2668 normalized_algorithm
2669 .version
2670 .is_none_or(|version| version == 19) &&
2671 normalized_algorithm.parallelism != 0 &&
2672 normalized_algorithm.parallelism <= 16777215 &&
2673 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
2674 normalized_algorithm.passes != 0
2675 },
2676 }
2677 },
2678 "wrapKey" => {
2679 let Ok(normalized_algorithm) = normalize_algorithm::<WrapKeyOperation>(cx, algorithm)
2680 else {
2681 return check_support_for_algorithm(cx, "encrypt", algorithm, length);
2682 };
2683
2684 match normalized_algorithm {
2685 WrapKeyAlgorithm::AesKw(_) => true,
2686 }
2687 },
2688 "unwrapKey" => {
2689 let Ok(normalized_algorithm) = normalize_algorithm::<UnwrapKeyOperation>(cx, algorithm)
2690 else {
2691 return check_support_for_algorithm(cx, "decrypt", algorithm, length);
2692 };
2693
2694 match normalized_algorithm {
2695 UnwrapKeyAlgorithm::AesKw(_) => true,
2696 }
2697 },
2698 "generateKey" => {
2699 let Ok(normalized_algorithm) =
2700 normalize_algorithm::<GenerateKeyOperation>(cx, algorithm)
2701 else {
2702 return false;
2703 };
2704
2705 match normalized_algorithm {
2706 GenerateKeyAlgorithm::RsassaPkcs1V1_5(normalized_algorithm) |
2707 GenerateKeyAlgorithm::RsaPss(normalized_algorithm) |
2708 GenerateKeyAlgorithm::RsaOaep(normalized_algorithm) => {
2709 normalized_algorithm.validate_parameters().is_ok()
2710 },
2711 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
2712 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
2713 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2714 },
2715 GenerateKeyAlgorithm::Ed25519(_) |
2716 GenerateKeyAlgorithm::X25519(_) |
2717 GenerateKeyAlgorithm::Ed448(_) |
2718 GenerateKeyAlgorithm::X448(_) => true,
2719 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
2720 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
2721 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
2722 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
2723 matches!(normalized_algorithm.length, 128 | 192 | 256)
2724 },
2725 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
2726 normalized_algorithm.length.is_none_or(|length| length != 0)
2727 },
2728 GenerateKeyAlgorithm::MlKem(_) | GenerateKeyAlgorithm::MlDsa(_) => true,
2729 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
2730 matches!(normalized_algorithm.length, 128 | 192 | 256)
2731 },
2732 GenerateKeyAlgorithm::ChaCha20Poly1305(_) | GenerateKeyAlgorithm::Kmac(_) => true,
2733 }
2734 },
2735 "importKey" => {
2736 let Ok(normalized_algorithm) = normalize_algorithm::<ImportKeyOperation>(cx, algorithm)
2737 else {
2738 return false;
2739 };
2740
2741 match normalized_algorithm {
2742 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2743 ImportKeyAlgorithm::RsaPss(_) |
2744 ImportKeyAlgorithm::RsaOaep(_) => true,
2745 ImportKeyAlgorithm::Ecdsa(normalized_algorithm) |
2746 ImportKeyAlgorithm::Ecdh(normalized_algorithm) => {
2747 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
2748 },
2749 ImportKeyAlgorithm::Ed25519(_) |
2750 ImportKeyAlgorithm::X25519(_) |
2751 ImportKeyAlgorithm::Ed448(_) |
2752 ImportKeyAlgorithm::X448(_) |
2753 ImportKeyAlgorithm::AesCtr(_) |
2754 ImportKeyAlgorithm::AesCbc(_) |
2755 ImportKeyAlgorithm::AesGcm(_) |
2756 ImportKeyAlgorithm::AesKw(_) => true,
2757 ImportKeyAlgorithm::Hmac(normalized_algorithm) => {
2758 normalized_algorithm.length.is_none_or(|length| length != 0)
2759 },
2760 ImportKeyAlgorithm::Hkdf(_) |
2761 ImportKeyAlgorithm::Pbkdf2(_) |
2762 ImportKeyAlgorithm::MlKem(_) |
2763 ImportKeyAlgorithm::MlDsa(_) |
2764 ImportKeyAlgorithm::AesOcb(_) |
2765 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
2766 ImportKeyAlgorithm::Kmac(_) |
2767 ImportKeyAlgorithm::Argon2(_) => true,
2768 }
2769 },
2770 "exportKey" => {
2771 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2772 else {
2773 return false;
2774 };
2775
2776 match normalized_algorithm {
2777 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
2778 ExportKeyAlgorithm::RsaPss(_) |
2779 ExportKeyAlgorithm::RsaOaep(_) |
2780 ExportKeyAlgorithm::Ecdsa(_) |
2781 ExportKeyAlgorithm::Ecdh(_) |
2782 ExportKeyAlgorithm::Ed25519(_) |
2783 ExportKeyAlgorithm::X25519(_) |
2784 ExportKeyAlgorithm::Ed448(_) |
2785 ExportKeyAlgorithm::X448(_) |
2786 ExportKeyAlgorithm::AesCtr(_) |
2787 ExportKeyAlgorithm::AesCbc(_) |
2788 ExportKeyAlgorithm::AesGcm(_) |
2789 ExportKeyAlgorithm::AesKw(_) |
2790 ExportKeyAlgorithm::Hmac(_) |
2791 ExportKeyAlgorithm::MlKem(_) |
2792 ExportKeyAlgorithm::MlDsa(_) |
2793 ExportKeyAlgorithm::AesOcb(_) |
2794 ExportKeyAlgorithm::ChaCha20Poly1305(_) |
2795 ExportKeyAlgorithm::Kmac(_) => true,
2796 }
2797 },
2798 "get key length" => {
2799 let Ok(normalized_algorithm) =
2800 normalize_algorithm::<GetKeyLengthOperation>(cx, algorithm)
2801 else {
2802 return false;
2803 };
2804
2805 match normalized_algorithm {
2806 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
2807 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
2808 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
2809 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
2810 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2811 },
2812 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
2813 normalized_derived_key_algorithm
2814 .length
2815 .is_none_or(|length| length != 0)
2816 },
2817 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
2818 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
2819 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
2820 },
2821 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) |
2822 GetKeyLengthAlgorithm::Kmac(_) |
2823 GetKeyLengthAlgorithm::Argon2(_) => true,
2824 }
2825 },
2826 "encapsulate" => {
2827 let Ok(normalized_algorithm) =
2828 normalize_algorithm::<EncapsulateOperation>(cx, algorithm)
2829 else {
2830 return false;
2831 };
2832
2833 match normalized_algorithm {
2834 EncapsulateAlgorithm::MlKem(_) => true,
2835 }
2836 },
2837 "decapsulate" => {
2838 let Ok(normalized_algorithm) =
2839 normalize_algorithm::<DecapsulateOperation>(cx, algorithm)
2840 else {
2841 return false;
2842 };
2843
2844 match normalized_algorithm {
2845 DecapsulateAlgorithm::MlKem(_) => true,
2846 }
2847 },
2848 _ => false,
2849 }
2850
2851 }
2855
2856trait TryFromWithCxAndName<T>: Sized {
2858 type Error;
2859
2860 fn try_from_with_cx_and_name(
2861 value: T,
2862 cx: &mut js::context::JSContext,
2863 algorithm_name: CryptoAlgorithm,
2864 ) -> Result<Self, Self::Error>;
2865}
2866
2867trait TryIntoWithCxAndName<T>: Sized {
2869 type Error;
2870
2871 fn try_into_with_cx_and_name(
2872 self,
2873 cx: &mut js::context::JSContext,
2874 algorithm_name: CryptoAlgorithm,
2875 ) -> Result<T, Self::Error>;
2876}
2877
2878impl<T, U> TryIntoWithCxAndName<U> for T
2879where
2880 U: TryFromWithCxAndName<T>,
2881{
2882 type Error = U::Error;
2883
2884 fn try_into_with_cx_and_name(
2885 self,
2886 cx: &mut js::context::JSContext,
2887 algorithm_name: CryptoAlgorithm,
2888 ) -> Result<U, Self::Error> {
2889 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2890 }
2891}
2892
2893#[derive(Clone, MallocSizeOf)]
2898struct Algorithm {
2899 name: CryptoAlgorithm,
2901}
2902
2903impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Algorithm {
2904 type Error = Error;
2905
2906 fn try_from_with_cx_and_name(
2907 _object: HandleObject<'a>,
2908 _cx: &mut js::context::JSContext,
2909 algorithm_name: CryptoAlgorithm,
2910 ) -> Result<Self, Self::Error> {
2911 Ok(Algorithm {
2912 name: algorithm_name,
2913 })
2914 }
2915}
2916
2917impl TryFrom<SerializableAlgorithm> for Algorithm {
2918 type Error = ();
2919
2920 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2921 Ok(Algorithm {
2922 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2923 })
2924 }
2925}
2926
2927impl From<&Algorithm> for SerializableAlgorithm {
2928 fn from(value: &Algorithm) -> Self {
2929 SerializableAlgorithm {
2930 name: value.name.as_str().into(),
2931 }
2932 }
2933}
2934
2935#[derive(Clone, MallocSizeOf)]
2937pub(crate) struct KeyAlgorithm {
2938 name: CryptoAlgorithm,
2940}
2941
2942impl ToJSValConvertible for KeyAlgorithm {
2943 #[expect(unsafe_code)]
2944 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
2945 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2946
2947 rooted!(&in(cx) let mut name_js = UndefinedValue());
2948 self.name.as_str().to_jsval(cx, name_js.handle_mut());
2949 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2950 .expect("Failed to set name property of KeyAlgorithm");
2951
2952 rval.set(ObjectOrNullValue(object.get()));
2953 }
2954}
2955
2956impl TryFrom<SerializableKeyAlgorithm> for KeyAlgorithm {
2957 type Error = ();
2958
2959 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2960 Ok(KeyAlgorithm {
2961 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2962 })
2963 }
2964}
2965
2966impl From<&KeyAlgorithm> for SerializableKeyAlgorithm {
2967 fn from(value: &KeyAlgorithm) -> Self {
2968 SerializableKeyAlgorithm {
2969 name: value.name.as_str().into(),
2970 }
2971 }
2972}
2973
2974#[derive(Clone, MallocSizeOf)]
2976pub(crate) struct RsaHashedKeyGenParams {
2977 name: CryptoAlgorithm,
2979
2980 modulus_length: u32,
2982
2983 public_exponent: Vec<u8>,
2985
2986 hash: DigestAlgorithm,
2988}
2989
2990impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedKeyGenParams {
2991 type Error = Error;
2992
2993 fn try_from_with_cx_and_name(
2994 object: HandleObject,
2995 cx: &mut js::context::JSContext,
2996 algorithm_name: CryptoAlgorithm,
2997 ) -> Result<Self, Self::Error> {
2998 let hash = get_required_parameter(cx, object, c"hash", ())?;
2999
3000 Ok(RsaHashedKeyGenParams {
3001 name: algorithm_name,
3002 modulus_length: get_required_parameter(
3003 cx,
3004 object,
3005 c"modulusLength",
3006 ConversionBehavior::EnforceRange,
3007 )?,
3008 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
3009 cx,
3010 object,
3011 c"publicExponent",
3012 (),
3013 )?
3014 .to_vec()
3015 .unwrap_or_default(),
3016 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3017 })
3018 }
3019}
3020
3021impl RsaHashedKeyGenParams {
3022 fn validate_parameters(&self) -> Result<(), Error> {
3024 let modulus_length = self.modulus_length;
3026
3027 let public_exponent = &self.public_exponent;
3030
3031 let is_less_than_3 = |public_exponent: &[u8]| {
3034 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
3035 byte_iterator.next().is_none_or(|byte| *byte < 3) && byte_iterator.count() == 0
3036 };
3037 let is_even =
3038 |public_exponent: &[u8]| public_exponent.last().is_none_or(|byte| byte % 2 == 0);
3039 let upper_bound_first_byte = (1u8 << (modulus_length % 8)).wrapping_sub(1);
3040 let upper_bound_length_in_bytes = modulus_length.div_ceil(8) as usize;
3041 let is_greater_than_upper_bound = |public_exponent: &[u8]| {
3042 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
3043 byte_iterator
3044 .next()
3045 .is_some_and(|byte| *byte > upper_bound_first_byte) &&
3046 byte_iterator.count() + 1 >= upper_bound_length_in_bytes
3047 };
3048 let is_equal_to_upper_bound = |public_exponent: &[u8]| {
3049 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
3050 byte_iterator
3051 .next()
3052 .is_some_and(|byte| *byte == upper_bound_first_byte) &&
3053 byte_iterator.clone().all(|byte| *byte == 255) &&
3054 byte_iterator.count() + 1 == upper_bound_length_in_bytes
3055 };
3056 if modulus_length < 4 ||
3057 is_less_than_3(public_exponent) ||
3058 is_even(public_exponent) ||
3059 is_greater_than_upper_bound(public_exponent) ||
3060 is_equal_to_upper_bound(public_exponent)
3061 {
3062 return Err(Error::Operation(Some(
3063 "Invalid RsaHashedKeyGenParams".into(),
3064 )));
3065 }
3066
3067 Ok(())
3068 }
3069}
3070
3071#[derive(Clone, MallocSizeOf)]
3073pub(crate) struct RsaHashedKeyAlgorithm {
3074 name: CryptoAlgorithm,
3076
3077 modulus_length: u32,
3079
3080 public_exponent: Vec<u8>,
3082
3083 hash: DigestAlgorithm,
3085}
3086
3087impl ToJSValConvertible for RsaHashedKeyAlgorithm {
3088 #[expect(unsafe_code)]
3089 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3090 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3091
3092 rooted!(&in(cx) let mut name_js = UndefinedValue());
3093 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3094 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3095 .expect("Failed to set name property of RsaHashedKeyAlgorithm");
3096
3097 rooted!(&in(cx) let mut modulus_length_js = UndefinedValue());
3098 self.modulus_length
3099 .to_jsval(cx, modulus_length_js.handle_mut());
3100 set_dictionary_property(
3101 cx,
3102 object.handle(),
3103 c"modulusLength",
3104 modulus_length_js.handle(),
3105 )
3106 .expect("Failed to set modulusLength property of RsaHashedKeyAlgorithm");
3107
3108 rooted!(&in(cx) let mut public_exponent_js = UndefinedValue());
3109 rooted!(&in(cx) let mut public_exponent_js_object = ptr::null_mut::<JSObject>());
3110 let public_exponent = create_buffer_source::<ArrayBufferU8>(
3111 cx,
3112 &self.public_exponent,
3113 public_exponent_js_object.handle_mut(),
3114 )
3115 .expect("Failed to convert publicExponent to Uint8Array");
3116 public_exponent.to_jsval(cx, public_exponent_js.handle_mut());
3117 set_dictionary_property(
3118 cx,
3119 object.handle(),
3120 c"publicExponent",
3121 public_exponent_js.handle(),
3122 )
3123 .expect("Failed to set publicExponent property of RsaHashedKeyAlgorithm");
3124
3125 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3126 let hash = KeyAlgorithm {
3127 name: self.hash.name(),
3128 };
3129 hash.to_jsval(cx, hash_js.handle_mut());
3130 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3131 .expect("Failed to set hash property of RsaHashedKeyAlgorithm");
3132
3133 rval.set(ObjectOrNullValue(object.get()));
3134 }
3135}
3136
3137impl TryFrom<SerializableRsaHashedKeyAlgorithm> for RsaHashedKeyAlgorithm {
3138 type Error = ();
3139
3140 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
3141 Ok(RsaHashedKeyAlgorithm {
3142 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3143 modulus_length: value.modulus_length,
3144 public_exponent: value.public_exponent,
3145 hash: value.hash.try_into()?,
3146 })
3147 }
3148}
3149
3150impl From<&RsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
3151 fn from(value: &RsaHashedKeyAlgorithm) -> Self {
3152 SerializableRsaHashedKeyAlgorithm {
3153 name: value.name.as_str().into(),
3154 modulus_length: value.modulus_length,
3155 public_exponent: value.public_exponent.clone(),
3156 hash: (&value.hash).into(),
3157 }
3158 }
3159}
3160
3161#[derive(Clone, MallocSizeOf)]
3163struct RsaHashedImportParams {
3164 name: CryptoAlgorithm,
3166
3167 hash: DigestAlgorithm,
3169}
3170
3171impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedImportParams {
3172 type Error = Error;
3173
3174 fn try_from_with_cx_and_name(
3175 object: HandleObject,
3176 cx: &mut js::context::JSContext,
3177 algorithm_name: CryptoAlgorithm,
3178 ) -> Result<Self, Self::Error> {
3179 let hash = get_required_parameter(cx, object, c"hash", ())?;
3180
3181 Ok(RsaHashedImportParams {
3182 name: algorithm_name,
3183 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3184 })
3185 }
3186}
3187
3188#[derive(Clone, MallocSizeOf)]
3190struct RsaPssParams {
3191 name: CryptoAlgorithm,
3193
3194 salt_length: u32,
3196}
3197
3198impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaPssParams {
3199 type Error = Error;
3200
3201 fn try_from_with_cx_and_name(
3202 object: HandleObject,
3203 cx: &mut js::context::JSContext,
3204 algorithm_name: CryptoAlgorithm,
3205 ) -> Result<Self, Self::Error> {
3206 Ok(RsaPssParams {
3207 name: algorithm_name,
3208 salt_length: get_required_parameter(
3209 cx,
3210 object,
3211 c"saltLength",
3212 ConversionBehavior::EnforceRange,
3213 )?,
3214 })
3215 }
3216}
3217
3218#[derive(Clone, MallocSizeOf)]
3220struct RsaOaepParams {
3221 name: CryptoAlgorithm,
3223
3224 label: Option<Vec<u8>>,
3226}
3227
3228impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaOaepParams {
3229 type Error = Error;
3230
3231 fn try_from_with_cx_and_name(
3232 object: HandleObject<'a>,
3233 cx: &mut js::context::JSContext,
3234 algorithm_name: CryptoAlgorithm,
3235 ) -> Result<Self, Self::Error> {
3236 Ok(RsaOaepParams {
3237 name: algorithm_name,
3238 label: get_optional_buffer_source(cx, object, c"label")?,
3239 })
3240 }
3241}
3242
3243#[derive(Clone, MallocSizeOf)]
3245struct EcdsaParams {
3246 name: CryptoAlgorithm,
3248
3249 hash: DigestAlgorithm,
3251}
3252
3253impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcdsaParams {
3254 type Error = Error;
3255
3256 fn try_from_with_cx_and_name(
3257 object: HandleObject<'a>,
3258 cx: &mut js::context::JSContext,
3259 algorithm_name: CryptoAlgorithm,
3260 ) -> Result<Self, Self::Error> {
3261 let hash = get_required_parameter(cx, object, c"hash", ())?;
3262
3263 Ok(EcdsaParams {
3264 name: algorithm_name,
3265 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3266 })
3267 }
3268}
3269
3270#[derive(Clone, MallocSizeOf)]
3272struct EcKeyGenParams {
3273 name: CryptoAlgorithm,
3275
3276 named_curve: String,
3278}
3279
3280impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyGenParams {
3281 type Error = Error;
3282
3283 fn try_from_with_cx_and_name(
3284 object: HandleObject<'a>,
3285 cx: &mut js::context::JSContext,
3286 algorithm_name: CryptoAlgorithm,
3287 ) -> Result<Self, Self::Error> {
3288 Ok(EcKeyGenParams {
3289 name: algorithm_name,
3290 named_curve: String::from(get_required_parameter::<DOMString>(
3291 cx,
3292 object,
3293 c"namedCurve",
3294 StringificationBehavior::Default,
3295 )?),
3296 })
3297 }
3298}
3299
3300#[derive(Clone, MallocSizeOf)]
3302pub(crate) struct EcKeyAlgorithm {
3303 name: CryptoAlgorithm,
3305
3306 named_curve: String,
3308}
3309
3310impl ToJSValConvertible for EcKeyAlgorithm {
3311 #[expect(unsafe_code)]
3312 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3313 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3314
3315 rooted!(&in(cx) let mut name_js = UndefinedValue());
3316 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3317 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3318 .expect("Failed to set name property of EcKeyAlgorithm");
3319
3320 rooted!(&in(cx) let mut named_curve_js = UndefinedValue());
3321 self.named_curve.to_jsval(cx, named_curve_js.handle_mut());
3322 set_dictionary_property(cx, object.handle(), c"namedCurve", named_curve_js.handle())
3323 .expect("Failed to set namedCurve property of EcKeyAlgorithm");
3324
3325 rval.set(ObjectOrNullValue(object.get()));
3326 }
3327}
3328
3329impl TryFrom<SerializableEcKeyAlgorithm> for EcKeyAlgorithm {
3330 type Error = ();
3331
3332 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3333 Ok(EcKeyAlgorithm {
3334 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3335 named_curve: value.named_curve,
3336 })
3337 }
3338}
3339
3340impl From<&EcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3341 fn from(value: &EcKeyAlgorithm) -> Self {
3342 SerializableEcKeyAlgorithm {
3343 name: value.name.as_str().into(),
3344 named_curve: value.named_curve.clone(),
3345 }
3346 }
3347}
3348
3349#[derive(Clone, MallocSizeOf)]
3351struct EcKeyImportParams {
3352 name: CryptoAlgorithm,
3354
3355 named_curve: String,
3357}
3358
3359impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyImportParams {
3360 type Error = Error;
3361
3362 fn try_from_with_cx_and_name(
3363 object: HandleObject<'a>,
3364 cx: &mut js::context::JSContext,
3365 algorithm_name: CryptoAlgorithm,
3366 ) -> Result<Self, Self::Error> {
3367 Ok(EcKeyImportParams {
3368 name: algorithm_name,
3369 named_curve: String::from(get_required_parameter::<DOMString>(
3370 cx,
3371 object,
3372 c"namedCurve",
3373 StringificationBehavior::Default,
3374 )?),
3375 })
3376 }
3377}
3378
3379#[derive(Clone, MallocSizeOf)]
3381struct EcdhKeyDeriveParams {
3382 name: CryptoAlgorithm,
3384
3385 public: Trusted<CryptoKey>,
3387}
3388
3389impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcdhKeyDeriveParams {
3390 type Error = Error;
3391
3392 fn try_from_with_cx_and_name(
3393 object: HandleObject<'a>,
3394 cx: &mut js::context::JSContext,
3395 algorithm_name: CryptoAlgorithm,
3396 ) -> Result<Self, Self::Error> {
3397 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3398
3399 Ok(EcdhKeyDeriveParams {
3400 name: algorithm_name,
3401 public: Trusted::new(&public),
3402 })
3403 }
3404}
3405
3406#[derive(Clone, MallocSizeOf)]
3408struct AesCtrParams {
3409 name: CryptoAlgorithm,
3411
3412 counter: Vec<u8>,
3414
3415 length: u8,
3417}
3418
3419impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCtrParams {
3420 type Error = Error;
3421
3422 fn try_from_with_cx_and_name(
3423 object: HandleObject<'a>,
3424 cx: &mut js::context::JSContext,
3425 algorithm_name: CryptoAlgorithm,
3426 ) -> Result<Self, Self::Error> {
3427 Ok(AesCtrParams {
3428 name: algorithm_name,
3429 counter: get_required_buffer_source(cx, object, c"counter")?,
3430 length: get_required_parameter(
3431 cx,
3432 object,
3433 c"length",
3434 ConversionBehavior::EnforceRange,
3435 )?,
3436 })
3437 }
3438}
3439
3440#[derive(Clone, MallocSizeOf)]
3442pub(crate) struct AesKeyAlgorithm {
3443 name: CryptoAlgorithm,
3445
3446 length: u16,
3448}
3449
3450impl ToJSValConvertible for AesKeyAlgorithm {
3451 #[expect(unsafe_code)]
3452 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3453 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3454
3455 rooted!(&in(cx) let mut name_js = UndefinedValue());
3456 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3457 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3458 .expect("Failed to set name property of AesKeyAlgorithm");
3459
3460 rooted!(&in(cx) let mut length_js = UndefinedValue());
3461 self.length.to_jsval(cx, length_js.handle_mut());
3462 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3463 .expect("Failed to set length property of AesKeyAlgorithm");
3464
3465 rval.set(ObjectOrNullValue(object.get()));
3466 }
3467}
3468
3469impl TryFrom<SerializableAesKeyAlgorithm> for AesKeyAlgorithm {
3470 type Error = ();
3471
3472 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3473 Ok(AesKeyAlgorithm {
3474 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3475 length: value.length,
3476 })
3477 }
3478}
3479
3480impl From<&AesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3481 fn from(value: &AesKeyAlgorithm) -> Self {
3482 SerializableAesKeyAlgorithm {
3483 name: value.name.as_str().into(),
3484 length: value.length,
3485 }
3486 }
3487}
3488
3489#[derive(Clone, MallocSizeOf)]
3491struct AesKeyGenParams {
3492 name: CryptoAlgorithm,
3494
3495 length: u16,
3497}
3498
3499impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesKeyGenParams {
3500 type Error = Error;
3501
3502 fn try_from_with_cx_and_name(
3503 object: HandleObject<'a>,
3504 cx: &mut js::context::JSContext,
3505 algorithm_name: CryptoAlgorithm,
3506 ) -> Result<Self, Self::Error> {
3507 Ok(AesKeyGenParams {
3508 name: algorithm_name,
3509 length: get_required_parameter(
3510 cx,
3511 object,
3512 c"length",
3513 ConversionBehavior::EnforceRange,
3514 )?,
3515 })
3516 }
3517}
3518
3519#[derive(Clone, MallocSizeOf)]
3521struct AesDerivedKeyParams {
3522 name: CryptoAlgorithm,
3524
3525 length: u16,
3527}
3528
3529impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesDerivedKeyParams {
3530 type Error = Error;
3531
3532 fn try_from_with_cx_and_name(
3533 object: HandleObject<'a>,
3534 cx: &mut js::context::JSContext,
3535 algorithm_name: CryptoAlgorithm,
3536 ) -> Result<Self, Self::Error> {
3537 Ok(AesDerivedKeyParams {
3538 name: algorithm_name,
3539 length: get_required_parameter(
3540 cx,
3541 object,
3542 c"length",
3543 ConversionBehavior::EnforceRange,
3544 )?,
3545 })
3546 }
3547}
3548
3549#[derive(Clone, MallocSizeOf)]
3551struct AesCbcParams {
3552 name: CryptoAlgorithm,
3554
3555 iv: Vec<u8>,
3557}
3558
3559impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCbcParams {
3560 type Error = Error;
3561
3562 fn try_from_with_cx_and_name(
3563 object: HandleObject<'a>,
3564 cx: &mut js::context::JSContext,
3565 algorithm_name: CryptoAlgorithm,
3566 ) -> Result<Self, Self::Error> {
3567 Ok(AesCbcParams {
3568 name: algorithm_name,
3569 iv: get_required_buffer_source(cx, object, c"iv")?,
3570 })
3571 }
3572}
3573
3574#[derive(Clone, MallocSizeOf)]
3576struct AesGcmParams {
3577 name: CryptoAlgorithm,
3579
3580 iv: Vec<u8>,
3582
3583 additional_data: Option<Vec<u8>>,
3585
3586 tag_length: Option<u8>,
3588}
3589
3590impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesGcmParams {
3591 type Error = Error;
3592
3593 fn try_from_with_cx_and_name(
3594 object: HandleObject<'a>,
3595 cx: &mut js::context::JSContext,
3596 algorithm_name: CryptoAlgorithm,
3597 ) -> Result<Self, Self::Error> {
3598 Ok(AesGcmParams {
3599 name: algorithm_name,
3600 iv: get_required_buffer_source(cx, object, c"iv")?,
3601 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3602 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3603 })
3604 }
3605}
3606
3607#[derive(Clone, MallocSizeOf)]
3609struct HmacImportParams {
3610 name: CryptoAlgorithm,
3612
3613 hash: DigestAlgorithm,
3615
3616 length: Option<u32>,
3618}
3619
3620impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacImportParams {
3621 type Error = Error;
3622
3623 fn try_from_with_cx_and_name(
3624 object: HandleObject<'a>,
3625 cx: &mut js::context::JSContext,
3626 algorithm_name: CryptoAlgorithm,
3627 ) -> Result<Self, Self::Error> {
3628 let hash = get_required_parameter(cx, object, c"hash", ())?;
3629
3630 Ok(HmacImportParams {
3631 name: algorithm_name,
3632 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3633 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3634 })
3635 }
3636}
3637
3638#[derive(Clone, MallocSizeOf)]
3640pub(crate) struct HmacKeyAlgorithm {
3641 name: CryptoAlgorithm,
3643
3644 hash: DigestAlgorithm,
3646
3647 length: u32,
3649}
3650
3651impl ToJSValConvertible for HmacKeyAlgorithm {
3652 #[expect(unsafe_code)]
3653 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3654 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3655
3656 rooted!(&in(cx) let mut name_js = UndefinedValue());
3657 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3658 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3659 .expect("Failed to set name property of HmacKeyAlgorithm");
3660
3661 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3662 let hash = KeyAlgorithm {
3663 name: self.hash.name(),
3664 };
3665 hash.to_jsval(cx, hash_js.handle_mut());
3666 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3667 .expect("Failed to set hash property of HmacKeyAlgorithm");
3668
3669 rooted!(&in(cx) let mut length_js = UndefinedValue());
3670 self.length.to_jsval(cx, length_js.handle_mut());
3671 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3672 .expect("Failed to set length property of HmacKeyAlgorithm");
3673
3674 rval.set(ObjectOrNullValue(object.get()));
3675 }
3676}
3677
3678impl TryFrom<SerializableHmacKeyAlgorithm> for HmacKeyAlgorithm {
3679 type Error = ();
3680
3681 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3682 Ok(HmacKeyAlgorithm {
3683 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3684 hash: value.hash.try_into()?,
3685 length: value.length,
3686 })
3687 }
3688}
3689
3690impl From<&HmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3691 fn from(value: &HmacKeyAlgorithm) -> Self {
3692 SerializableHmacKeyAlgorithm {
3693 name: value.name.as_str().into(),
3694 hash: (&value.hash).into(),
3695 length: value.length,
3696 }
3697 }
3698}
3699
3700#[derive(Clone, MallocSizeOf)]
3702struct HmacKeyGenParams {
3703 name: CryptoAlgorithm,
3705
3706 hash: DigestAlgorithm,
3708
3709 length: Option<u32>,
3711}
3712
3713impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacKeyGenParams {
3714 type Error = Error;
3715
3716 fn try_from_with_cx_and_name(
3717 object: HandleObject<'a>,
3718 cx: &mut js::context::JSContext,
3719 algorithm_name: CryptoAlgorithm,
3720 ) -> Result<Self, Self::Error> {
3721 let hash = get_required_parameter(cx, object, c"hash", ())?;
3722
3723 Ok(HmacKeyGenParams {
3724 name: algorithm_name,
3725 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3726 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3727 })
3728 }
3729}
3730
3731#[derive(Clone, MallocSizeOf)]
3733pub(crate) struct HkdfParams {
3734 name: CryptoAlgorithm,
3736
3737 hash: DigestAlgorithm,
3739
3740 salt: Vec<u8>,
3742
3743 info: Vec<u8>,
3745}
3746
3747impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HkdfParams {
3748 type Error = Error;
3749
3750 fn try_from_with_cx_and_name(
3751 object: HandleObject<'a>,
3752 cx: &mut js::context::JSContext,
3753 algorithm_name: CryptoAlgorithm,
3754 ) -> Result<Self, Self::Error> {
3755 let hash = get_required_parameter(cx, object, c"hash", ())?;
3756
3757 Ok(HkdfParams {
3758 name: algorithm_name,
3759 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3760 salt: get_required_buffer_source(cx, object, c"salt")?,
3761 info: get_required_buffer_source(cx, object, c"info")?,
3762 })
3763 }
3764}
3765
3766#[derive(Clone, MallocSizeOf)]
3768pub(crate) struct Pbkdf2Params {
3769 name: CryptoAlgorithm,
3771
3772 salt: Vec<u8>,
3774
3775 iterations: u32,
3777
3778 hash: DigestAlgorithm,
3780}
3781
3782impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Pbkdf2Params {
3783 type Error = Error;
3784
3785 fn try_from_with_cx_and_name(
3786 object: HandleObject<'a>,
3787 cx: &mut js::context::JSContext,
3788 algorithm_name: CryptoAlgorithm,
3789 ) -> Result<Self, Self::Error> {
3790 let hash = get_required_parameter(cx, object, c"hash", ())?;
3791
3792 Ok(Pbkdf2Params {
3793 name: algorithm_name,
3794 salt: get_required_buffer_source(cx, object, c"salt")?,
3795 iterations: get_required_parameter(
3796 cx,
3797 object,
3798 c"iterations",
3799 ConversionBehavior::EnforceRange,
3800 )?,
3801 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3802 })
3803 }
3804}
3805
3806#[derive(Clone, MallocSizeOf)]
3808struct ContextParams {
3809 name: CryptoAlgorithm,
3811
3812 context: Option<Vec<u8>>,
3814}
3815
3816impl<'a> TryFromWithCxAndName<HandleObject<'a>> for ContextParams {
3817 type Error = Error;
3818
3819 fn try_from_with_cx_and_name(
3820 object: HandleObject<'a>,
3821 cx: &mut js::context::JSContext,
3822 algorithm_name: CryptoAlgorithm,
3823 ) -> Result<Self, Self::Error> {
3824 Ok(ContextParams {
3825 name: algorithm_name,
3826 context: get_optional_buffer_source(cx, object, c"context")?,
3827 })
3828 }
3829}
3830
3831#[derive(Clone, MallocSizeOf)]
3833struct AeadParams {
3834 name: CryptoAlgorithm,
3836
3837 iv: Vec<u8>,
3839
3840 additional_data: Option<Vec<u8>>,
3842
3843 tag_length: Option<u8>,
3845}
3846
3847impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AeadParams {
3848 type Error = Error;
3849
3850 fn try_from_with_cx_and_name(
3851 object: HandleObject<'a>,
3852 cx: &mut js::context::JSContext,
3853 algorithm_name: CryptoAlgorithm,
3854 ) -> Result<Self, Self::Error> {
3855 Ok(AeadParams {
3856 name: algorithm_name,
3857 iv: get_required_buffer_source(cx, object, c"iv")?,
3858 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3859 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3860 })
3861 }
3862}
3863
3864#[derive(Clone, MallocSizeOf)]
3866struct CShakeParams {
3867 name: CryptoAlgorithm,
3869
3870 output_length: u32,
3872
3873 function_name: Option<Vec<u8>>,
3875
3876 customization: Option<Vec<u8>>,
3878}
3879
3880impl<'a> TryFromWithCxAndName<HandleObject<'a>> for CShakeParams {
3881 type Error = Error;
3882
3883 fn try_from_with_cx_and_name(
3884 object: HandleObject<'a>,
3885 cx: &mut js::context::JSContext,
3886 algorithm_name: CryptoAlgorithm,
3887 ) -> Result<Self, Self::Error> {
3888 Ok(CShakeParams {
3889 name: algorithm_name,
3890 output_length: get_required_parameter(
3891 cx,
3892 object,
3893 c"outputLength",
3894 ConversionBehavior::EnforceRange,
3895 )?,
3896 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3897 customization: get_optional_buffer_source(cx, object, c"customization")?,
3898 })
3899 }
3900}
3901
3902impl TryFrom<SerializableCShakeParams> for CShakeParams {
3903 type Error = ();
3904
3905 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3906 Ok(CShakeParams {
3907 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3908 output_length: value.output_length,
3909 function_name: value.function_name,
3910 customization: value.customization,
3911 })
3912 }
3913}
3914
3915impl From<&CShakeParams> for SerializableCShakeParams {
3916 fn from(value: &CShakeParams) -> Self {
3917 SerializableCShakeParams {
3918 name: value.name.as_str().into(),
3919 output_length: value.output_length,
3920 function_name: value.function_name.clone(),
3921 customization: value.customization.clone(),
3922 }
3923 }
3924}
3925
3926#[derive(Clone, MallocSizeOf)]
3928struct TurboShakeParams {
3929 name: CryptoAlgorithm,
3931
3932 output_length: u32,
3934
3935 domain_separation: Option<u8>,
3937}
3938
3939impl<'a> TryFromWithCxAndName<HandleObject<'a>> for TurboShakeParams {
3940 type Error = Error;
3941
3942 fn try_from_with_cx_and_name(
3943 object: HandleObject<'a>,
3944 cx: &mut js::context::JSContext,
3945 algorithm_name: CryptoAlgorithm,
3946 ) -> Result<Self, Self::Error> {
3947 Ok(TurboShakeParams {
3948 name: algorithm_name,
3949 output_length: get_required_parameter(
3950 cx,
3951 object,
3952 c"outputLength",
3953 ConversionBehavior::EnforceRange,
3954 )?,
3955 domain_separation: get_property(
3956 cx,
3957 object,
3958 c"domainSeparation",
3959 ConversionBehavior::EnforceRange,
3960 )?,
3961 })
3962 }
3963}
3964
3965impl TryFrom<SerializableTurboShakeParams> for TurboShakeParams {
3966 type Error = ();
3967
3968 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3969 Ok(TurboShakeParams {
3970 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3971 output_length: value.output_length,
3972 domain_separation: value.domain_separation,
3973 })
3974 }
3975}
3976
3977impl From<&TurboShakeParams> for SerializableTurboShakeParams {
3978 fn from(value: &TurboShakeParams) -> Self {
3979 SerializableTurboShakeParams {
3980 name: value.name.as_str().into(),
3981 output_length: value.output_length,
3982 domain_separation: value.domain_separation,
3983 }
3984 }
3985}
3986
3987#[derive(Clone, MallocSizeOf)]
3989struct KangarooTwelveParams {
3990 name: CryptoAlgorithm,
3992
3993 output_length: u32,
3995
3996 customization: Option<Vec<u8>>,
3998}
3999
4000impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KangarooTwelveParams {
4001 type Error = Error;
4002
4003 fn try_from_with_cx_and_name(
4004 object: HandleObject<'a>,
4005 cx: &mut js::context::JSContext,
4006 algorithm_name: CryptoAlgorithm,
4007 ) -> Result<Self, Self::Error> {
4008 Ok(KangarooTwelveParams {
4009 name: algorithm_name,
4010 output_length: get_required_parameter(
4011 cx,
4012 object,
4013 c"outputLength",
4014 ConversionBehavior::EnforceRange,
4015 )?,
4016 customization: get_optional_buffer_source(cx, object, c"customization")?,
4017 })
4018 }
4019}
4020
4021impl TryFrom<SerializableKangarooTwelveParams> for KangarooTwelveParams {
4022 type Error = ();
4023
4024 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
4025 Ok(KangarooTwelveParams {
4026 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
4027 output_length: value.output_length,
4028 customization: value.customization,
4029 })
4030 }
4031}
4032
4033impl From<&KangarooTwelveParams> for SerializableKangarooTwelveParams {
4034 fn from(value: &KangarooTwelveParams) -> Self {
4035 SerializableKangarooTwelveParams {
4036 name: value.name.as_str().into(),
4037 output_length: value.output_length,
4038 customization: value.customization.clone(),
4039 }
4040 }
4041}
4042
4043#[derive(Clone, MallocSizeOf)]
4045struct KmacKeyGenParams {
4046 name: CryptoAlgorithm,
4048
4049 length: Option<u32>,
4051}
4052
4053impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacKeyGenParams {
4054 type Error = Error;
4055
4056 fn try_from_with_cx_and_name(
4057 object: HandleObject,
4058 cx: &mut js::context::JSContext,
4059 algorithm_name: CryptoAlgorithm,
4060 ) -> Result<Self, Self::Error> {
4061 Ok(KmacKeyGenParams {
4062 name: algorithm_name,
4063 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
4064 })
4065 }
4066}
4067
4068#[derive(Clone, MallocSizeOf)]
4070struct KmacImportParams {
4071 name: CryptoAlgorithm,
4073
4074 length: Option<u32>,
4076}
4077
4078impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacImportParams {
4079 type Error = Error;
4080
4081 fn try_from_with_cx_and_name(
4082 object: HandleObject,
4083 cx: &mut js::context::JSContext,
4084 algorithm_name: CryptoAlgorithm,
4085 ) -> Result<Self, Self::Error> {
4086 Ok(KmacImportParams {
4087 name: algorithm_name,
4088 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
4089 })
4090 }
4091}
4092
4093#[derive(Clone, MallocSizeOf)]
4095pub(crate) struct KmacKeyAlgorithm {
4096 name: CryptoAlgorithm,
4098
4099 length: u32,
4101}
4102
4103impl ToJSValConvertible for KmacKeyAlgorithm {
4104 #[expect(unsafe_code)]
4105 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
4106 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4107
4108 rooted!(&in(cx) let mut name_js = UndefinedValue());
4109 self.name.as_str().to_jsval(cx, name_js.handle_mut());
4110 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
4111 .expect("Failed to set name property of KmacKeyAlgorithm");
4112
4113 rooted!(&in(cx) let mut length_js = UndefinedValue());
4114 self.length.to_jsval(cx, length_js.handle_mut());
4115 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
4116 .expect("Failed to set length property of KmacKeyAlgorithm");
4117
4118 rval.set(ObjectOrNullValue(object.get()));
4119 }
4120}
4121
4122impl TryFrom<SerializableKmacKeyAlgorithm> for KmacKeyAlgorithm {
4123 type Error = ();
4124
4125 fn try_from(value: SerializableKmacKeyAlgorithm) -> Result<Self, Self::Error> {
4126 Ok(KmacKeyAlgorithm {
4127 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
4128 length: value.length,
4129 })
4130 }
4131}
4132
4133impl From<&KmacKeyAlgorithm> for SerializableKmacKeyAlgorithm {
4134 fn from(value: &KmacKeyAlgorithm) -> Self {
4135 SerializableKmacKeyAlgorithm {
4136 name: value.name.as_str().into(),
4137 length: value.length,
4138 }
4139 }
4140}
4141
4142struct KmacParams {
4144 name: CryptoAlgorithm,
4146
4147 output_length: u32,
4149
4150 customization: Option<Vec<u8>>,
4152}
4153
4154impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacParams {
4155 type Error = Error;
4156
4157 fn try_from_with_cx_and_name(
4158 object: HandleObject<'a>,
4159 cx: &mut js::context::JSContext,
4160 algorithm_name: CryptoAlgorithm,
4161 ) -> Result<Self, Self::Error> {
4162 Ok(KmacParams {
4163 name: algorithm_name,
4164 output_length: get_required_parameter(
4165 cx,
4166 object,
4167 c"outputLength",
4168 ConversionBehavior::EnforceRange,
4169 )?,
4170 customization: get_optional_buffer_source(cx, object, c"customization")?,
4171 })
4172 }
4173}
4174
4175#[derive(Clone, MallocSizeOf)]
4177struct Argon2Params {
4178 name: CryptoAlgorithm,
4180
4181 nonce: Vec<u8>,
4183
4184 parallelism: u32,
4186
4187 memory: u32,
4189
4190 passes: u32,
4192
4193 version: Option<u8>,
4195
4196 secret_value: Option<Vec<u8>>,
4198
4199 associated_data: Option<Vec<u8>>,
4201}
4202
4203impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Argon2Params {
4204 type Error = Error;
4205
4206 fn try_from_with_cx_and_name(
4207 object: HandleObject<'a>,
4208 cx: &mut js::context::JSContext,
4209 algorithm_name: CryptoAlgorithm,
4210 ) -> Result<Self, Self::Error> {
4211 Ok(Argon2Params {
4212 name: algorithm_name,
4213 nonce: get_required_buffer_source(cx, object, c"nonce")?,
4214 parallelism: get_required_parameter(
4215 cx,
4216 object,
4217 c"parallelism",
4218 ConversionBehavior::EnforceRange,
4219 )?,
4220 memory: get_required_parameter(
4221 cx,
4222 object,
4223 c"memory",
4224 ConversionBehavior::EnforceRange,
4225 )?,
4226 passes: get_required_parameter(
4227 cx,
4228 object,
4229 c"passes",
4230 ConversionBehavior::EnforceRange,
4231 )?,
4232 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
4233 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
4234 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
4235 })
4236 }
4237}
4238
4239struct EncapsulatedKey {
4241 shared_key: Option<Trusted<CryptoKey>>,
4243
4244 ciphertext: Option<Vec<u8>>,
4246}
4247
4248impl ToJSValConvertible for EncapsulatedKey {
4249 #[expect(unsafe_code)]
4250 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
4251 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4252
4253 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
4254 self.shared_key
4255 .as_ref()
4256 .map(|shared_key| shared_key.root())
4257 .to_jsval(cx, shared_key_js.handle_mut());
4258 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
4259 .expect("Failed to set sharedKey property of EncapsulatedKey");
4260
4261 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
4262 self.ciphertext
4263 .as_ref()
4264 .map(|ciphertext| {
4265 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
4266 create_buffer_source::<ArrayBufferU8>(
4267 cx,
4268 ciphertext,
4269 ciphertext_js_object.handle_mut(),
4270 )
4271 .expect("Failed to convert ciphertext to ArrayBufferU8")
4272 })
4273 .to_jsval(cx, ciphertext_js.handle_mut());
4274 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4275 .expect("Failed to set ciphertext property of EncapsulatedKey");
4276
4277 rval.set(ObjectOrNullValue(object.get()));
4278 }
4279}
4280
4281struct EncapsulatedBits {
4283 shared_key: Option<Zeroizing<Vec<u8>>>,
4285
4286 ciphertext: Option<Vec<u8>>,
4288}
4289
4290impl ToJSValConvertible for EncapsulatedBits {
4291 #[expect(unsafe_code)]
4292 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
4293 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4294
4295 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
4296 self.shared_key
4297 .as_ref()
4298 .map(|shared_key| {
4299 rooted!(&in(cx) let mut shared_key_js_object = ptr::null_mut::<JSObject>());
4300 create_buffer_source::<ArrayBufferU8>(
4301 cx,
4302 shared_key,
4303 shared_key_js_object.handle_mut(),
4304 )
4305 .expect("Failed to convert shared_key to ArrayBufferU8")
4306 })
4307 .to_jsval(cx, shared_key_js.handle_mut());
4308 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
4309 .expect("Failed to set sharedKey property of EncapsulatedBits");
4310
4311 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
4312 self.ciphertext
4313 .as_ref()
4314 .map(|ciphertext| {
4315 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
4316 create_buffer_source::<ArrayBufferU8>(
4317 cx,
4318 ciphertext,
4319 ciphertext_js_object.handle_mut(),
4320 )
4321 .expect("Failed to convert ciphertext to ArrayBufferU8")
4322 })
4323 .to_jsval(cx, ciphertext_js.handle_mut());
4324 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4325 .expect("Failed to set ciphertext property of EncapsulatedBits");
4326
4327 rval.set(ObjectOrNullValue(object.get()));
4328 }
4329}
4330
4331#[derive(Clone, MallocSizeOf)]
4333struct SubtleEd448Params {
4334 name: CryptoAlgorithm,
4336
4337 context: Option<Vec<u8>>,
4339}
4340
4341impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEd448Params {
4342 type Error = Error;
4343
4344 fn try_from_with_cx_and_name(
4345 object: HandleObject<'a>,
4346 cx: &mut js::context::JSContext,
4347 algorithm_name: CryptoAlgorithm,
4348 ) -> Result<Self, Self::Error> {
4349 Ok(SubtleEd448Params {
4350 name: algorithm_name,
4351 context: get_optional_buffer_source(cx, object, c"context")?,
4352 })
4353 }
4354}
4355
4356fn get_required_parameter<T: FromJSValConvertible>(
4358 cx: &mut js::context::JSContext,
4359 object: HandleObject,
4360 parameter: &std::ffi::CStr,
4361 option: T::Config,
4362) -> Fallible<T> {
4363 get_property::<T>(cx, object, parameter, option)?
4364 .ok_or(Error::Type(c"Missing required parameter".into()))
4365}
4366
4367fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4369 cx: &mut js::context::JSContext,
4370 object: HandleObject,
4371 parameter: &std::ffi::CStr,
4372 option: T::Config,
4373) -> Fallible<RootedTraceableBox<T>> {
4374 get_property::<T>(cx, object, parameter, option)?
4375 .map(RootedTraceableBox::new)
4376 .ok_or(Error::Type(c"Missing required parameter".into()))
4377}
4378
4379fn get_optional_buffer_source(
4383 cx: &mut js::context::JSContext,
4384 object: HandleObject,
4385 parameter: &std::ffi::CStr,
4386) -> Fallible<Option<Vec<u8>>> {
4387 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4388 Ok(buffer_source
4389 .as_ref()
4390 .map(|buffer| get_buffer_source_copy(buffer.into())))
4391}
4392
4393fn get_required_buffer_source(
4397 cx: &mut js::context::JSContext,
4398 object: HandleObject,
4399 parameter: &std::ffi::CStr,
4400) -> Fallible<Vec<u8>> {
4401 get_optional_buffer_source(cx, object, parameter)?
4402 .ok_or(Error::Type(c"Missing required parameter".into()))
4403}
4404
4405enum ExportedKey {
4409 Bytes(Zeroizing<Vec<u8>>),
4410 Jwk(Box<JsonWebKey>),
4411}
4412
4413impl ExportedKey {
4414 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4415 ExportedKey::Bytes(Zeroizing::new(bytes))
4416 }
4417
4418 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4419 ExportedKey::Jwk(Box::new(jwk))
4420 }
4421}
4422
4423#[derive(Clone, MallocSizeOf)]
4427#[expect(clippy::enum_variant_names)]
4428pub(crate) enum KeyAlgorithmAndDerivatives {
4429 KeyAlgorithm(KeyAlgorithm),
4430 RsaHashedKeyAlgorithm(RsaHashedKeyAlgorithm),
4431 EcKeyAlgorithm(EcKeyAlgorithm),
4432 AesKeyAlgorithm(AesKeyAlgorithm),
4433 HmacKeyAlgorithm(HmacKeyAlgorithm),
4434 KmacKeyAlgorithm(KmacKeyAlgorithm),
4435}
4436
4437impl KeyAlgorithmAndDerivatives {
4438 fn name(&self) -> CryptoAlgorithm {
4439 match self {
4440 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4441 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4442 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4443 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4444 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4445 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => algorithm.name,
4446 }
4447 }
4448}
4449
4450impl ToJSValConvertible for KeyAlgorithmAndDerivatives {
4451 fn to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4452 match self {
4453 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4454 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4455 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4456 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4457 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4458 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4459 }
4460 }
4461}
4462
4463impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4464 type Error = ();
4465
4466 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4467 match value {
4468 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4469 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4470 ),
4471 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4472 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4473 ),
4474 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4475 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4476 ),
4477 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4478 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4479 ),
4480 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4481 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4482 ),
4483 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => Ok(
4484 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.try_into()?),
4485 ),
4486 }
4487 }
4488}
4489
4490impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4491 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4492 match value {
4493 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4494 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4495 },
4496 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4497 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4498 },
4499 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4500 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4501 },
4502 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4503 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4504 },
4505 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4506 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4507 },
4508 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => {
4509 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.into())
4510 },
4511 }
4512 }
4513}
4514
4515#[derive(Clone, Copy)]
4516enum JwkStringField {
4517 X,
4518 Y,
4519 D,
4520 N,
4521 E,
4522 P,
4523 Q,
4524 DP,
4525 DQ,
4526 QI,
4527 K,
4528 Priv,
4529 Pub,
4530}
4531
4532impl Display for JwkStringField {
4533 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4534 let field_name = match self {
4535 JwkStringField::X => "x",
4536 JwkStringField::Y => "y",
4537 JwkStringField::D => "d",
4538 JwkStringField::N => "n",
4539 JwkStringField::E => "e",
4540 JwkStringField::P => "q",
4541 JwkStringField::Q => "q",
4542 JwkStringField::DP => "dp",
4543 JwkStringField::DQ => "dq",
4544 JwkStringField::QI => "qi",
4545 JwkStringField::K => "k",
4546 JwkStringField::Priv => "priv",
4547 JwkStringField::Pub => "pub",
4548 };
4549 write!(f, "{}", field_name)
4550 }
4551}
4552
4553trait JsonWebKeyExt {
4554 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4555 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4556 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4557 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4558 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4559 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4560 fn decode_optional_string_field(
4561 &self,
4562 field: JwkStringField,
4563 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4564 fn decode_required_string_field(
4565 &self,
4566 field: JwkStringField,
4567 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4568 fn decode_primes_from_oth_field(
4569 &self,
4570 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4571 ) -> Result<(), Error>;
4572}
4573
4574impl JsonWebKeyExt for JsonWebKey {
4575 #[expect(unsafe_code)]
4577 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4578 let json = String::from_utf8_lossy(data);
4583
4584 let json: Vec<_> = json.encode_utf16().collect();
4586
4587 rooted!(&in(cx) let mut result = UndefinedValue());
4591 unsafe {
4592 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4593 return Err(Error::JSFailed);
4594 }
4595 }
4596
4597 let key = match JsonWebKey::new(cx, result.handle()) {
4599 Ok(ConversionResult::Success(key)) => key,
4600 Ok(ConversionResult::Failure(error)) => {
4601 return Err(Error::Type(error.into_owned()));
4602 },
4603 Err(()) => {
4604 return Err(Error::JSFailed);
4605 },
4606 };
4607
4608 if key.kty.is_none() {
4610 return Err(Error::Data(Some(
4611 "'kty' field of key is not defined".into(),
4612 )));
4613 }
4614
4615 Ok(key)
4617 }
4618
4619 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4625 rooted!(&in(cx) let mut data = UndefinedValue());
4626 self.to_jsval(cx, data.handle_mut());
4627 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4628 }
4629
4630 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4631 let mut usages = vec![];
4632 for op in self.key_ops.as_ref().ok_or(Error::Data(Some(
4633 "'key_ops' member is not present in the JSON Web Key".into(),
4634 )))? {
4635 usages.push(
4636 KeyUsage::from_str(&op.str())
4637 .map_err(|_| Error::Data(Some("Unknown key usage".into())))?,
4638 );
4639 }
4640 Ok(usages)
4641 }
4642
4643 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4647 if let Some(ref key_ops) = self.key_ops {
4649 if key_ops
4652 .iter()
4653 .collect::<std::collections::HashSet<_>>()
4654 .len() <
4655 key_ops.len()
4656 {
4657 return Err(Error::Data(Some(
4658 "Duplicate key operation values are present in array".into(),
4659 )));
4660 }
4661 if let Some(ref use_) = self.use_ &&
4664 key_ops.iter().any(|op| op != use_)
4665 {
4666 return Err(Error::Data(Some(
4667 "Key operations are not consistent with intended use for Json Web Key".into(),
4668 )));
4669 }
4670
4671 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4673 if !specified_usages
4674 .iter()
4675 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4676 {
4677 return Err(Error::Data(Some(
4678 "Key operations do not contain all of the specified usage values".into(),
4679 )));
4680 }
4681 }
4682
4683 Ok(())
4684 }
4685
4686 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4688 self.key_ops = Some(
4689 usages
4690 .iter()
4691 .map(|usage| DOMString::from(usage.as_str()))
4692 .collect(),
4693 );
4694 }
4695
4696 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4699 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4700 match field {
4701 JwkStringField::X => self.x = Some(encoded_data),
4702 JwkStringField::Y => self.y = Some(encoded_data),
4703 JwkStringField::D => self.d = Some(encoded_data),
4704 JwkStringField::N => self.n = Some(encoded_data),
4705 JwkStringField::E => self.e = Some(encoded_data),
4706 JwkStringField::P => self.p = Some(encoded_data),
4707 JwkStringField::Q => self.q = Some(encoded_data),
4708 JwkStringField::DP => self.dp = Some(encoded_data),
4709 JwkStringField::DQ => self.dq = Some(encoded_data),
4710 JwkStringField::QI => self.qi = Some(encoded_data),
4711 JwkStringField::K => self.k = Some(encoded_data),
4712 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4713 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4714 }
4715 }
4716
4717 fn decode_optional_string_field(
4720 &self,
4721 field: JwkStringField,
4722 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4723 let field_string = match field {
4724 JwkStringField::X => &self.x,
4725 JwkStringField::Y => &self.y,
4726 JwkStringField::D => &self.d,
4727 JwkStringField::N => &self.n,
4728 JwkStringField::E => &self.e,
4729 JwkStringField::P => &self.p,
4730 JwkStringField::Q => &self.q,
4731 JwkStringField::DP => &self.dp,
4732 JwkStringField::DQ => &self.dq,
4733 JwkStringField::QI => &self.qi,
4734 JwkStringField::K => &self.k,
4735 JwkStringField::Priv => &self.priv_,
4736 JwkStringField::Pub => &self.pub_,
4737 };
4738
4739 field_string
4740 .as_ref()
4741 .map(|field_string| {
4742 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4743 })
4744 .transpose()
4745 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4746 }
4747
4748 fn decode_required_string_field(
4751 &self,
4752 field: JwkStringField,
4753 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4754 self.decode_optional_string_field(field)?
4755 .ok_or(Error::Data(Some(format!(
4756 "The {} field is not present in jwk",
4757 field
4758 ))))
4759 }
4760
4761 fn decode_primes_from_oth_field(
4770 &self,
4771 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4772 ) -> Result<(), Error> {
4773 if self.oth.is_some() &&
4774 (self.p.is_none() ||
4775 self.q.is_none() ||
4776 self.dp.is_none() ||
4777 self.dq.is_none() ||
4778 self.qi.is_none())
4779 {
4780 return Err(Error::Data(Some(
4781 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4782 )));
4783 }
4784
4785 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4786 let r = Base64UrlUnpadded::decode_vec(
4787 &rsa_other_prime_info
4788 .r
4789 .as_ref()
4790 .ok_or(Error::Data(Some(
4791 "The r field is not present in one of the entry of oth field in jwk"
4792 .to_string(),
4793 )))?
4794 .str(),
4795 )
4796 .map_err(|_| {
4797 Error::Data(Some(
4798 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4799 ))
4800 })?;
4801 primes.push(Zeroizing::new(r));
4802
4803 let _d = Base64UrlUnpadded::decode_vec(
4804 &rsa_other_prime_info
4805 .d
4806 .as_ref()
4807 .ok_or(Error::Data(Some(
4808 "The d field is not present in one of the entry of oth field in jwk"
4809 .to_string(),
4810 )))?
4811 .str(),
4812 )
4813 .map_err(|_| {
4814 Error::Data(Some(
4815 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4816 ))
4817 })?;
4818
4819 let _t = Base64UrlUnpadded::decode_vec(
4820 &rsa_other_prime_info
4821 .t
4822 .as_ref()
4823 .ok_or(Error::Data(Some(
4824 "The t field is not present in one of the entry of oth field in jwk"
4825 .to_string(),
4826 )))?
4827 .str(),
4828 )
4829 .map_err(|_| {
4830 Error::Data(Some(
4831 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4832 ))
4833 })?;
4834 }
4835
4836 Ok(())
4837 }
4838}
4839
4840fn normalize_algorithm<Op: Operation>(
4842 cx: &mut js::context::JSContext,
4843 algorithm: &AlgorithmIdentifier,
4844) -> Result<Op::RegisteredAlgorithm, Error> {
4845 match algorithm {
4846 AlgorithmIdentifier::String(name) => {
4848 let algorithm = AlgorithmWithDOMString {
4855 name: name.to_owned(),
4856 };
4857 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4858 algorithm.to_jsval(cx, algorithm_value.handle_mut());
4859 let algorithm_object = RootedTraceableBox::new(Heap::default());
4860 algorithm_object.set(algorithm_value.to_object());
4861 normalize_algorithm::<Op>(cx, &AlgorithmIdentifier::Object(algorithm_object))
4862 },
4863 AlgorithmIdentifier::Object(object) => {
4865 let algorithm_name = get_required_parameter::<DOMString>(
4873 cx,
4874 object.handle(),
4875 c"name",
4876 StringificationBehavior::Default,
4877 )?;
4878
4879 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4920 let normalized_algorithm =
4921 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4922
4923 Ok(normalized_algorithm)
4925 },
4926 }
4927}
4928
4929trait Operation {
4988 type RegisteredAlgorithm: NormalizedAlgorithm;
4989}
4990
4991trait NormalizedAlgorithm: Sized {
4992 fn from_object(
4994 cx: &mut js::context::JSContext,
4995 algorithm_name: CryptoAlgorithm,
4996 object: HandleObject,
4997 ) -> Fallible<Self>;
4998 fn name(&self) -> CryptoAlgorithm;
4999}
5000
5001struct EncryptOperation {}
5003
5004impl Operation for EncryptOperation {
5005 type RegisteredAlgorithm = EncryptAlgorithm;
5006}
5007
5008enum EncryptAlgorithm {
5011 RsaOaep(RsaOaepParams),
5012 AesCtr(AesCtrParams),
5013 AesCbc(AesCbcParams),
5014 AesGcm(AesGcmParams),
5015 AesOcb(AeadParams),
5016 ChaCha20Poly1305(AeadParams),
5017}
5018
5019impl NormalizedAlgorithm for EncryptAlgorithm {
5020 fn from_object(
5021 cx: &mut js::context::JSContext,
5022 algorithm_name: CryptoAlgorithm,
5023 object: HandleObject,
5024 ) -> Fallible<Self> {
5025 match algorithm_name {
5026 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
5027 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5028 )),
5029 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
5030 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5031 )),
5032 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
5033 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5034 )),
5035 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
5036 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5037 )),
5038 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
5039 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5040 )),
5041 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
5042 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5043 )),
5044 _ => Err(Error::NotSupported(Some(format!(
5045 "{} does not support \"encrypt\" operation",
5046 algorithm_name.as_str()
5047 )))),
5048 }
5049 }
5050
5051 fn name(&self) -> CryptoAlgorithm {
5052 match self {
5053 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
5054 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
5055 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
5056 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
5057 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
5058 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5059 }
5060 }
5061}
5062
5063impl EncryptAlgorithm {
5064 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5065 match self {
5066 EncryptAlgorithm::RsaOaep(algorithm) => {
5067 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
5068 },
5069 EncryptAlgorithm::AesCtr(algorithm) => {
5070 aes_ctr_operation::encrypt(algorithm, key, plaintext)
5071 },
5072 EncryptAlgorithm::AesCbc(algorithm) => {
5073 aes_cbc_operation::encrypt(algorithm, key, plaintext)
5074 },
5075 EncryptAlgorithm::AesGcm(algorithm) => {
5076 aes_gcm_operation::encrypt(algorithm, key, plaintext)
5077 },
5078 EncryptAlgorithm::AesOcb(algorithm) => {
5079 aes_ocb_operation::encrypt(algorithm, key, plaintext)
5080 },
5081 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
5082 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
5083 },
5084 }
5085 }
5086}
5087
5088struct DecryptOperation {}
5090
5091impl Operation for DecryptOperation {
5092 type RegisteredAlgorithm = DecryptAlgorithm;
5093}
5094
5095enum DecryptAlgorithm {
5098 RsaOaep(RsaOaepParams),
5099 AesCtr(AesCtrParams),
5100 AesCbc(AesCbcParams),
5101 AesGcm(AesGcmParams),
5102 AesOcb(AeadParams),
5103 ChaCha20Poly1305(AeadParams),
5104}
5105
5106impl NormalizedAlgorithm for DecryptAlgorithm {
5107 fn from_object(
5108 cx: &mut js::context::JSContext,
5109 algorithm_name: CryptoAlgorithm,
5110 object: HandleObject,
5111 ) -> Fallible<Self> {
5112 match algorithm_name {
5113 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
5114 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5115 )),
5116 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
5117 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5118 )),
5119 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
5120 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5121 )),
5122 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
5123 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5124 )),
5125 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
5126 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5127 )),
5128 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
5129 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5130 )),
5131 _ => Err(Error::NotSupported(Some(format!(
5132 "{} does not support \"decrypt\" operation",
5133 algorithm_name.as_str()
5134 )))),
5135 }
5136 }
5137
5138 fn name(&self) -> CryptoAlgorithm {
5139 match self {
5140 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
5141 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
5142 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
5143 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
5144 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
5145 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5146 }
5147 }
5148}
5149
5150impl DecryptAlgorithm {
5151 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5152 match self {
5153 DecryptAlgorithm::RsaOaep(algorithm) => {
5154 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
5155 },
5156 DecryptAlgorithm::AesCtr(algorithm) => {
5157 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
5158 },
5159 DecryptAlgorithm::AesCbc(algorithm) => {
5160 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
5161 },
5162 DecryptAlgorithm::AesGcm(algorithm) => {
5163 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
5164 },
5165 DecryptAlgorithm::AesOcb(algorithm) => {
5166 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
5167 },
5168 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
5169 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
5170 },
5171 }
5172 }
5173}
5174
5175struct SignOperation {}
5177
5178impl Operation for SignOperation {
5179 type RegisteredAlgorithm = SignAlgorithm;
5180}
5181
5182enum SignAlgorithm {
5185 RsassaPkcs1V1_5(Algorithm),
5186 RsaPss(RsaPssParams),
5187 Ecdsa(EcdsaParams),
5188 Ed25519(Algorithm),
5189 Ed448(SubtleEd448Params),
5190 Hmac(Algorithm),
5191 MlDsa(ContextParams),
5192 Kmac(KmacParams),
5193}
5194
5195impl NormalizedAlgorithm for SignAlgorithm {
5196 fn from_object(
5197 cx: &mut js::context::JSContext,
5198 algorithm_name: CryptoAlgorithm,
5199 object: HandleObject,
5200 ) -> Fallible<Self> {
5201 match algorithm_name {
5202 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
5203 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5204 )),
5205 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
5206 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5207 )),
5208 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
5209 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5210 )),
5211 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
5212 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5213 )),
5214 CryptoAlgorithm::Ed448 => Ok(SignAlgorithm::Ed448(
5215 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5216 )),
5217 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
5218 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5219 )),
5220 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5221 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5222 ),
5223 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(SignAlgorithm::Kmac(
5224 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5225 )),
5226 _ => Err(Error::NotSupported(Some(format!(
5227 "{} does not support \"sign\" operation",
5228 algorithm_name.as_str()
5229 )))),
5230 }
5231 }
5232
5233 fn name(&self) -> CryptoAlgorithm {
5234 match self {
5235 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5236 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
5237 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
5238 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
5239 SignAlgorithm::Ed448(algorithm) => algorithm.name,
5240 SignAlgorithm::Hmac(algorithm) => algorithm.name,
5241 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
5242 SignAlgorithm::Kmac(algorithm) => algorithm.name,
5243 }
5244 }
5245}
5246
5247impl SignAlgorithm {
5248 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
5249 match self {
5250 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5251 rsassa_pkcs1_v1_5_operation::sign(key, message)
5252 },
5253 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
5254 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
5255 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
5256 SignAlgorithm::Ed448(algorithm) => ed448_operation::sign(algorithm, key, message),
5257 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
5258 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
5259 SignAlgorithm::Kmac(algorithm) => kmac_operation::sign(algorithm, key, message),
5260 }
5261 }
5262}
5263
5264struct VerifyOperation {}
5266
5267impl Operation for VerifyOperation {
5268 type RegisteredAlgorithm = VerifyAlgorithm;
5269}
5270
5271enum VerifyAlgorithm {
5274 RsassaPkcs1V1_5(Algorithm),
5275 RsaPss(RsaPssParams),
5276 Ecdsa(EcdsaParams),
5277 Ed25519(Algorithm),
5278 Ed448(SubtleEd448Params),
5279 Hmac(Algorithm),
5280 MlDsa(ContextParams),
5281 Kmac(KmacParams),
5282}
5283
5284impl NormalizedAlgorithm for VerifyAlgorithm {
5285 fn from_object(
5286 cx: &mut js::context::JSContext,
5287 algorithm_name: CryptoAlgorithm,
5288 object: HandleObject,
5289 ) -> Fallible<Self> {
5290 match algorithm_name {
5291 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
5292 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5293 )),
5294 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
5295 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5296 )),
5297 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
5298 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5299 )),
5300 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
5301 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5302 )),
5303 CryptoAlgorithm::Ed448 => Ok(VerifyAlgorithm::Ed448(
5304 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5305 )),
5306 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
5307 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5308 )),
5309 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5310 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5311 ),
5312 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(VerifyAlgorithm::Kmac(
5313 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5314 )),
5315 _ => Err(Error::NotSupported(Some(format!(
5316 "{} does not support \"verify\" operation",
5317 algorithm_name.as_str()
5318 )))),
5319 }
5320 }
5321
5322 fn name(&self) -> CryptoAlgorithm {
5323 match self {
5324 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5325 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
5326 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5327 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
5328 VerifyAlgorithm::Ed448(algorithm) => algorithm.name,
5329 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
5330 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
5331 VerifyAlgorithm::Kmac(algorithm) => algorithm.name,
5332 }
5333 }
5334}
5335
5336impl VerifyAlgorithm {
5337 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
5338 match self {
5339 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5340 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
5341 },
5342 VerifyAlgorithm::RsaPss(algorithm) => {
5343 rsa_pss_operation::verify(algorithm, key, message, signature)
5344 },
5345 VerifyAlgorithm::Ecdsa(algorithm) => {
5346 ecdsa_operation::verify(algorithm, key, message, signature)
5347 },
5348 VerifyAlgorithm::Ed25519(_algorithm) => {
5349 ed25519_operation::verify(key, message, signature)
5350 },
5351 VerifyAlgorithm::Ed448(algorithm) => {
5352 ed448_operation::verify(algorithm, key, message, signature)
5353 },
5354 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
5355 VerifyAlgorithm::MlDsa(algorithm) => {
5356 ml_dsa_operation::verify(algorithm, key, message, signature)
5357 },
5358 VerifyAlgorithm::Kmac(algorithm) => {
5359 kmac_operation::verify(algorithm, key, message, signature)
5360 },
5361 }
5362 }
5363}
5364
5365struct DigestOperation {}
5367
5368impl Operation for DigestOperation {
5369 type RegisteredAlgorithm = DigestAlgorithm;
5370}
5371
5372#[derive(Clone, MallocSizeOf)]
5375enum DigestAlgorithm {
5376 Sha(Algorithm),
5377 Sha3(Algorithm),
5378 CShake(CShakeParams),
5379 TurboShake(TurboShakeParams),
5380 KangarooTwelve(KangarooTwelveParams),
5381}
5382
5383impl NormalizedAlgorithm for DigestAlgorithm {
5384 fn from_object(
5385 cx: &mut js::context::JSContext,
5386 algorithm_name: CryptoAlgorithm,
5387 object: HandleObject,
5388 ) -> Fallible<Self> {
5389 match algorithm_name {
5390 CryptoAlgorithm::Sha1 |
5391 CryptoAlgorithm::Sha256 |
5392 CryptoAlgorithm::Sha384 |
5393 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
5394 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5395 )),
5396 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5397 Ok(DigestAlgorithm::Sha3(
5398 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5399 ))
5400 },
5401 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5402 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5403 )),
5404 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5405 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5406 ),
5407 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5408 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5409 )),
5410 _ => Err(Error::NotSupported(Some(format!(
5411 "{} does not support \"digest\" operation",
5412 algorithm_name.as_str()
5413 )))),
5414 }
5415 }
5416
5417 fn name(&self) -> CryptoAlgorithm {
5418 match self {
5419 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5420 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5421 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5422 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5423 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5424 }
5425 }
5426}
5427
5428impl DigestAlgorithm {
5429 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5430 match self {
5431 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5432 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5433 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5434 DigestAlgorithm::TurboShake(algorithm) => {
5435 turboshake_operation::digest(algorithm, message)
5436 },
5437 DigestAlgorithm::KangarooTwelve(algorithm) => {
5438 kangarootwelve_operation::digest(algorithm, message)
5439 },
5440 }
5441 }
5442}
5443
5444impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5445 type Error = ();
5446
5447 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5448 match value {
5449 SerializableDigestAlgorithm::Sha(algorithm) => {
5450 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5451 },
5452 SerializableDigestAlgorithm::Sha3(algorithm) => {
5453 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5454 },
5455 SerializableDigestAlgorithm::CShake(algorithm) => {
5456 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5457 },
5458 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5459 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5460 },
5461 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5462 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5463 },
5464 }
5465 }
5466}
5467
5468impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5469 fn from(value: &DigestAlgorithm) -> Self {
5470 match value {
5471 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5472 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5473 DigestAlgorithm::CShake(algorithm) => {
5474 SerializableDigestAlgorithm::CShake(algorithm.into())
5475 },
5476 DigestAlgorithm::TurboShake(algorithm) => {
5477 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5478 },
5479 DigestAlgorithm::KangarooTwelve(algorithm) => {
5480 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5481 },
5482 }
5483 }
5484}
5485
5486struct DeriveBitsOperation {}
5488
5489impl Operation for DeriveBitsOperation {
5490 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5491}
5492
5493enum DeriveBitsAlgorithm {
5496 Ecdh(EcdhKeyDeriveParams),
5497 X25519(EcdhKeyDeriveParams),
5498 X448(EcdhKeyDeriveParams),
5499 Hkdf(HkdfParams),
5500 Pbkdf2(Pbkdf2Params),
5501 Argon2(Argon2Params),
5502}
5503
5504impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5505 fn from_object(
5506 cx: &mut js::context::JSContext,
5507 algorithm_name: CryptoAlgorithm,
5508 object: HandleObject,
5509 ) -> Fallible<Self> {
5510 match algorithm_name {
5511 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5512 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5513 )),
5514 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5515 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5516 )),
5517 CryptoAlgorithm::X448 => Ok(DeriveBitsAlgorithm::X448(
5518 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5519 )),
5520 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5521 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5522 )),
5523 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5524 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5525 )),
5526 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5527 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5528 ),
5529 _ => Err(Error::NotSupported(Some(format!(
5530 "{} does not support \"deriveBits\" operation",
5531 algorithm_name.as_str()
5532 )))),
5533 }
5534 }
5535
5536 fn name(&self) -> CryptoAlgorithm {
5537 match self {
5538 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5539 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5540 DeriveBitsAlgorithm::X448(algorithm) => algorithm.name,
5541 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5542 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5543 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5544 }
5545 }
5546}
5547
5548impl DeriveBitsAlgorithm {
5549 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5550 match self {
5551 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5552 ecdh_operation::derive_bits(algorithm, key, length)
5553 },
5554 DeriveBitsAlgorithm::X25519(algorithm) => {
5555 x25519_operation::derive_bits(algorithm, key, length)
5556 },
5557 DeriveBitsAlgorithm::X448(algorithm) => {
5558 x448_operation::derive_bits(algorithm, key, length)
5559 },
5560 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5561 hkdf_operation::derive_bits(algorithm, key, length)
5562 },
5563 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5564 pbkdf2_operation::derive_bits(algorithm, key, length)
5565 },
5566 DeriveBitsAlgorithm::Argon2(algorithm) => {
5567 argon2_operation::derive_bits(algorithm, key, length)
5568 },
5569 }
5570 }
5571}
5572
5573struct WrapKeyOperation {}
5575
5576impl Operation for WrapKeyOperation {
5577 type RegisteredAlgorithm = WrapKeyAlgorithm;
5578}
5579
5580enum WrapKeyAlgorithm {
5583 AesKw(Algorithm),
5584}
5585
5586impl NormalizedAlgorithm for WrapKeyAlgorithm {
5587 fn from_object(
5588 cx: &mut js::context::JSContext,
5589 algorithm_name: CryptoAlgorithm,
5590 object: HandleObject,
5591 ) -> Fallible<Self> {
5592 match algorithm_name {
5593 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5594 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5595 )),
5596 _ => Err(Error::NotSupported(Some(format!(
5597 "{} does not support \"wrapKey\" operation",
5598 algorithm_name.as_str()
5599 )))),
5600 }
5601 }
5602
5603 fn name(&self) -> CryptoAlgorithm {
5604 match self {
5605 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5606 }
5607 }
5608}
5609
5610impl WrapKeyAlgorithm {
5611 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5612 match self {
5613 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5614 }
5615 }
5616}
5617
5618struct UnwrapKeyOperation {}
5620
5621impl Operation for UnwrapKeyOperation {
5622 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5623}
5624
5625enum UnwrapKeyAlgorithm {
5628 AesKw(Algorithm),
5629}
5630
5631impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5632 fn from_object(
5633 cx: &mut js::context::JSContext,
5634 algorithm_name: CryptoAlgorithm,
5635 object: HandleObject,
5636 ) -> Fallible<Self> {
5637 match algorithm_name {
5638 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5639 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5640 )),
5641 _ => Err(Error::NotSupported(Some(format!(
5642 "{} does not support \"unwrapKey\" operation",
5643 algorithm_name.as_str()
5644 )))),
5645 }
5646 }
5647
5648 fn name(&self) -> CryptoAlgorithm {
5649 match self {
5650 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5651 }
5652 }
5653}
5654
5655impl UnwrapKeyAlgorithm {
5656 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5657 match self {
5658 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5659 }
5660 }
5661}
5662
5663struct GenerateKeyOperation {}
5665
5666impl Operation for GenerateKeyOperation {
5667 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5668}
5669
5670enum GenerateKeyAlgorithm {
5673 RsassaPkcs1V1_5(RsaHashedKeyGenParams),
5674 RsaPss(RsaHashedKeyGenParams),
5675 RsaOaep(RsaHashedKeyGenParams),
5676 Ecdsa(EcKeyGenParams),
5677 Ecdh(EcKeyGenParams),
5678 Ed25519(Algorithm),
5679 X25519(Algorithm),
5680 Ed448(Algorithm),
5681 X448(Algorithm),
5682 AesCtr(AesKeyGenParams),
5683 AesCbc(AesKeyGenParams),
5684 AesGcm(AesKeyGenParams),
5685 AesKw(AesKeyGenParams),
5686 Hmac(HmacKeyGenParams),
5687 MlKem(Algorithm),
5688 MlDsa(Algorithm),
5689 AesOcb(AesKeyGenParams),
5690 ChaCha20Poly1305(Algorithm),
5691 Kmac(KmacKeyGenParams),
5692}
5693
5694impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5695 fn from_object(
5696 cx: &mut js::context::JSContext,
5697 algorithm_name: CryptoAlgorithm,
5698 object: HandleObject,
5699 ) -> Fallible<Self> {
5700 match algorithm_name {
5701 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5702 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5703 )),
5704 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5705 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5706 )),
5707 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5708 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5709 )),
5710 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5711 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5712 )),
5713 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5714 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5715 )),
5716 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5717 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5718 )),
5719 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5720 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5721 )),
5722 CryptoAlgorithm::Ed448 => Ok(GenerateKeyAlgorithm::Ed448(
5723 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5724 )),
5725 CryptoAlgorithm::X448 => Ok(GenerateKeyAlgorithm::X448(
5726 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5727 )),
5728 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5729 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5730 )),
5731 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5732 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5733 )),
5734 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5735 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5736 )),
5737 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5738 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5739 )),
5740 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5741 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5742 )),
5743 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5744 Ok(GenerateKeyAlgorithm::MlKem(
5745 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5746 ))
5747 },
5748 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5749 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5750 ),
5751 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5752 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5753 )),
5754 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5755 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5756 )),
5757 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GenerateKeyAlgorithm::Kmac(
5758 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5759 )),
5760 _ => Err(Error::NotSupported(Some(format!(
5761 "{} does not support \"generateKey\" operation",
5762 algorithm_name.as_str()
5763 )))),
5764 }
5765 }
5766
5767 fn name(&self) -> CryptoAlgorithm {
5768 match self {
5769 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5770 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5771 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5772 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5773 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5774 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5775 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5776 GenerateKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5777 GenerateKeyAlgorithm::X448(algorithm) => algorithm.name,
5778 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5779 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5780 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5781 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5782 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5783 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5784 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5785 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5786 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5787 GenerateKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5788 }
5789 }
5790}
5791
5792impl GenerateKeyAlgorithm {
5793 fn generate_key(
5794 &self,
5795 cx: &mut js::context::JSContext,
5796 global: &GlobalScope,
5797 extractable: bool,
5798 usages: Vec<KeyUsage>,
5799 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5800 match self {
5801 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5802 rsassa_pkcs1_v1_5_operation::generate_key(
5803 cx,
5804 global,
5805 algorithm,
5806 extractable,
5807 usages,
5808 )
5809 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5810 },
5811 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5812 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5813 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5814 },
5815 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5816 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5817 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5818 },
5819 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5820 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5821 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5822 },
5823 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5824 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5825 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5826 },
5827 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5828 ed25519_operation::generate_key(cx, global, extractable, usages)
5829 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5830 },
5831 GenerateKeyAlgorithm::X25519(_algorithm) => {
5832 x25519_operation::generate_key(cx, global, extractable, usages)
5833 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5834 },
5835 GenerateKeyAlgorithm::Ed448(_algorithm) => {
5836 ed448_operation::generate_key(cx, global, extractable, usages)
5837 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5838 },
5839 GenerateKeyAlgorithm::X448(_algorithm) => {
5840 x448_operation::generate_key(cx, global, extractable, usages)
5841 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5842 },
5843 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5844 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5845 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5846 },
5847 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5848 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5849 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5850 },
5851 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5852 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5853 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5854 },
5855 GenerateKeyAlgorithm::AesKw(algorithm) => {
5856 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5857 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5858 },
5859 GenerateKeyAlgorithm::Hmac(algorithm) => {
5860 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5861 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5862 },
5863 GenerateKeyAlgorithm::MlKem(algorithm) => {
5864 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5865 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5866 },
5867 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5868 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5869 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5870 },
5871 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5872 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5873 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5874 },
5875 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5876 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5877 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5878 },
5879 GenerateKeyAlgorithm::Kmac(algorithm) => {
5880 kmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5881 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5882 },
5883 }
5884 }
5885}
5886
5887struct ImportKeyOperation {}
5889
5890impl Operation for ImportKeyOperation {
5891 type RegisteredAlgorithm = ImportKeyAlgorithm;
5892}
5893
5894enum ImportKeyAlgorithm {
5897 RsassaPkcs1V1_5(RsaHashedImportParams),
5898 RsaPss(RsaHashedImportParams),
5899 RsaOaep(RsaHashedImportParams),
5900 Ecdsa(EcKeyImportParams),
5901 Ecdh(EcKeyImportParams),
5902 Ed25519(Algorithm),
5903 X25519(Algorithm),
5904 Ed448(Algorithm),
5905 X448(Algorithm),
5906 AesCtr(Algorithm),
5907 AesCbc(Algorithm),
5908 AesGcm(Algorithm),
5909 AesKw(Algorithm),
5910 Hmac(HmacImportParams),
5911 Hkdf(Algorithm),
5912 Pbkdf2(Algorithm),
5913 MlKem(Algorithm),
5914 MlDsa(Algorithm),
5915 AesOcb(Algorithm),
5916 ChaCha20Poly1305(Algorithm),
5917 Kmac(KmacImportParams),
5918 Argon2(Algorithm),
5919}
5920
5921impl NormalizedAlgorithm for ImportKeyAlgorithm {
5922 fn from_object(
5923 cx: &mut js::context::JSContext,
5924 algorithm_name: CryptoAlgorithm,
5925 object: HandleObject,
5926 ) -> Fallible<Self> {
5927 match algorithm_name {
5928 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5929 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5930 )),
5931 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5932 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5933 )),
5934 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5935 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5936 )),
5937 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5938 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5939 )),
5940 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5941 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5942 )),
5943 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5944 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5945 )),
5946 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5947 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5948 )),
5949 CryptoAlgorithm::Ed448 => Ok(ImportKeyAlgorithm::Ed448(
5950 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5951 )),
5952 CryptoAlgorithm::X448 => Ok(ImportKeyAlgorithm::X448(
5953 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5954 )),
5955 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5956 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5957 )),
5958 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5959 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5960 )),
5961 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5962 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5963 )),
5964 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5965 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5966 )),
5967 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5968 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5969 )),
5970 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5971 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5972 )),
5973 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5974 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5975 )),
5976 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5977 Ok(ImportKeyAlgorithm::MlKem(
5978 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5979 ))
5980 },
5981 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5982 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5983 ),
5984 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5985 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5986 )),
5987 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
5988 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5989 )),
5990 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ImportKeyAlgorithm::Kmac(
5991 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5992 )),
5993 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5994 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5995 ),
5996 _ => Err(Error::NotSupported(Some(format!(
5997 "{} does not support \"importKey\" operation",
5998 algorithm_name.as_str()
5999 )))),
6000 }
6001 }
6002
6003 fn name(&self) -> CryptoAlgorithm {
6004 match self {
6005 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6006 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6007 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6008 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6009 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6010 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6011 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6012 ImportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6013 ImportKeyAlgorithm::X448(algorithm) => algorithm.name,
6014 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6015 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6016 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6017 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6018 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6019 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
6020 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6021 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6022 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6023 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6024 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6025 ImportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6026 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
6027 }
6028 }
6029}
6030
6031impl ImportKeyAlgorithm {
6032 fn import_key(
6033 &self,
6034 cx: &mut js::context::JSContext,
6035 global: &GlobalScope,
6036 format: KeyFormat,
6037 key_data: &[u8],
6038 extractable: bool,
6039 usages: Vec<KeyUsage>,
6040 ) -> Result<DomRoot<CryptoKey>, Error> {
6041 match self {
6042 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
6043 rsassa_pkcs1_v1_5_operation::import_key(
6044 cx,
6045 global,
6046 algorithm,
6047 format,
6048 key_data,
6049 extractable,
6050 usages,
6051 )
6052 },
6053 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
6054 cx,
6055 global,
6056 algorithm,
6057 format,
6058 key_data,
6059 extractable,
6060 usages,
6061 ),
6062 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
6063 cx,
6064 global,
6065 algorithm,
6066 format,
6067 key_data,
6068 extractable,
6069 usages,
6070 ),
6071 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
6072 cx,
6073 global,
6074 algorithm,
6075 format,
6076 key_data,
6077 extractable,
6078 usages,
6079 ),
6080 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
6081 cx,
6082 global,
6083 algorithm,
6084 format,
6085 key_data,
6086 extractable,
6087 usages,
6088 ),
6089 ImportKeyAlgorithm::Ed25519(_algorithm) => {
6090 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6091 },
6092 ImportKeyAlgorithm::X25519(_algorithm) => {
6093 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6094 },
6095 ImportKeyAlgorithm::Ed448(_algorithm) => {
6096 ed448_operation::import_key(cx, global, format, key_data, extractable, usages)
6097 },
6098 ImportKeyAlgorithm::X448(_algorithm) => {
6099 x448_operation::import_key(cx, global, format, key_data, extractable, usages)
6100 },
6101 ImportKeyAlgorithm::AesCtr(_algorithm) => {
6102 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
6103 },
6104 ImportKeyAlgorithm::AesCbc(_algorithm) => {
6105 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
6106 },
6107 ImportKeyAlgorithm::AesGcm(_algorithm) => {
6108 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
6109 },
6110 ImportKeyAlgorithm::AesKw(_algorithm) => {
6111 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
6112 },
6113 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
6114 cx,
6115 global,
6116 algorithm,
6117 format,
6118 key_data,
6119 extractable,
6120 usages,
6121 ),
6122 ImportKeyAlgorithm::Hkdf(_algorithm) => {
6123 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
6124 },
6125 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
6126 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
6127 },
6128 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
6129 cx,
6130 global,
6131 algorithm,
6132 format,
6133 key_data,
6134 extractable,
6135 usages,
6136 ),
6137 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
6138 cx,
6139 global,
6140 algorithm,
6141 format,
6142 key_data,
6143 extractable,
6144 usages,
6145 ),
6146 ImportKeyAlgorithm::AesOcb(_algorithm) => {
6147 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
6148 },
6149 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6150 chacha20_poly1305_operation::import_key(
6151 cx,
6152 global,
6153 format,
6154 key_data,
6155 extractable,
6156 usages,
6157 )
6158 },
6159 ImportKeyAlgorithm::Kmac(algorithm) => kmac_operation::import_key(
6160 cx,
6161 global,
6162 algorithm,
6163 format,
6164 key_data,
6165 extractable,
6166 usages,
6167 ),
6168 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
6169 cx,
6170 global,
6171 algorithm,
6172 format,
6173 key_data,
6174 extractable,
6175 usages,
6176 ),
6177 }
6178 }
6179}
6180
6181struct ExportKeyOperation {}
6183
6184impl Operation for ExportKeyOperation {
6185 type RegisteredAlgorithm = ExportKeyAlgorithm;
6186}
6187
6188enum ExportKeyAlgorithm {
6191 RsassaPkcs1V1_5(Algorithm),
6192 RsaPss(Algorithm),
6193 RsaOaep(Algorithm),
6194 Ecdsa(Algorithm),
6195 Ecdh(Algorithm),
6196 Ed25519(Algorithm),
6197 X25519(Algorithm),
6198 Ed448(Algorithm),
6199 X448(Algorithm),
6200 AesCtr(Algorithm),
6201 AesCbc(Algorithm),
6202 AesGcm(Algorithm),
6203 AesKw(Algorithm),
6204 Hmac(Algorithm),
6205 MlKem(Algorithm),
6206 MlDsa(Algorithm),
6207 AesOcb(Algorithm),
6208 ChaCha20Poly1305(Algorithm),
6209 Kmac(Algorithm),
6210}
6211
6212impl NormalizedAlgorithm for ExportKeyAlgorithm {
6213 fn from_object(
6214 cx: &mut js::context::JSContext,
6215 algorithm_name: CryptoAlgorithm,
6216 object: HandleObject,
6217 ) -> Fallible<Self> {
6218 match algorithm_name {
6219 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
6220 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6221 )),
6222 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
6223 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6224 )),
6225 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
6226 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6227 )),
6228 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
6229 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6230 )),
6231 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
6232 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6233 )),
6234 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
6235 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6236 )),
6237 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
6238 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6239 )),
6240 CryptoAlgorithm::Ed448 => Ok(ExportKeyAlgorithm::Ed448(
6241 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6242 )),
6243 CryptoAlgorithm::X448 => Ok(ExportKeyAlgorithm::X448(
6244 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6245 )),
6246 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
6247 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6248 )),
6249 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
6250 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6251 )),
6252 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
6253 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6254 )),
6255 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
6256 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6257 )),
6258 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
6259 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6260 )),
6261 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6262 Ok(ExportKeyAlgorithm::MlKem(
6263 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6264 ))
6265 },
6266 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6267 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6268 ),
6269 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
6270 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6271 )),
6272 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
6273 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6274 )),
6275 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ExportKeyAlgorithm::Kmac(
6276 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6277 )),
6278 _ => Err(Error::NotSupported(Some(format!(
6279 "{} does not support \"exportKey\" operation",
6280 algorithm_name.as_str()
6281 )))),
6282 }
6283 }
6284
6285 fn name(&self) -> CryptoAlgorithm {
6286 match self {
6287 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6288 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6289 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6290 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6291 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6292 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6293 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6294 ExportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6295 ExportKeyAlgorithm::X448(algorithm) => algorithm.name,
6296 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6297 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6298 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6299 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6300 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6301 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6302 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6303 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6304 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6305 ExportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6306 }
6307 }
6308}
6309
6310impl ExportKeyAlgorithm {
6311 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
6312 match self {
6313 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
6314 rsassa_pkcs1_v1_5_operation::export_key(format, key)
6315 },
6316 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
6317 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
6318 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
6319 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
6320 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
6321 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
6322 ExportKeyAlgorithm::Ed448(_algorithm) => ed448_operation::export_key(format, key),
6323 ExportKeyAlgorithm::X448(_algorithm) => x448_operation::export_key(format, key),
6324 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
6325 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
6326 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
6327 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
6328 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
6329 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
6330 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
6331 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
6332 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6333 chacha20_poly1305_operation::export_key(format, key)
6334 },
6335 ExportKeyAlgorithm::Kmac(_algorithm) => kmac_operation::export_key(format, key),
6336 }
6337 }
6338}
6339
6340struct GetKeyLengthOperation {}
6342
6343impl Operation for GetKeyLengthOperation {
6344 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
6345}
6346
6347enum GetKeyLengthAlgorithm {
6350 AesCtr(AesDerivedKeyParams),
6351 AesCbc(AesDerivedKeyParams),
6352 AesGcm(AesDerivedKeyParams),
6353 AesKw(AesDerivedKeyParams),
6354 Hmac(HmacImportParams),
6355 Hkdf(Algorithm),
6356 Pbkdf2(Algorithm),
6357 AesOcb(AesDerivedKeyParams),
6358 ChaCha20Poly1305(Algorithm),
6359 Kmac(KmacImportParams),
6360 Argon2(Algorithm),
6361}
6362
6363impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
6364 fn from_object(
6365 cx: &mut js::context::JSContext,
6366 algorithm_name: CryptoAlgorithm,
6367 object: HandleObject,
6368 ) -> Fallible<Self> {
6369 match algorithm_name {
6370 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
6371 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6372 )),
6373 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
6374 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6375 )),
6376 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
6377 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6378 )),
6379 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
6380 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6381 )),
6382 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
6383 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6384 )),
6385 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
6386 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6387 )),
6388 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
6389 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6390 )),
6391 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
6392 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6393 )),
6394 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
6395 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6396 )),
6397 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GetKeyLengthAlgorithm::Kmac(
6398 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6399 )),
6400 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
6401 Ok(GetKeyLengthAlgorithm::Argon2(
6402 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6403 ))
6404 },
6405 _ => Err(Error::NotSupported(Some(format!(
6406 "{} does not support \"get key length\" operation",
6407 algorithm_name.as_str()
6408 )))),
6409 }
6410 }
6411
6412 fn name(&self) -> CryptoAlgorithm {
6413 match self {
6414 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
6415 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
6416 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
6417 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
6418 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
6419 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
6420 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6421 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
6422 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6423 GetKeyLengthAlgorithm::Kmac(algorithm) => algorithm.name,
6424 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
6425 }
6426 }
6427}
6428
6429impl GetKeyLengthAlgorithm {
6430 fn get_key_length(&self) -> Result<Option<u32>, Error> {
6431 match self {
6432 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
6433 aes_ctr_operation::get_key_length(algorithm)
6434 },
6435 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
6436 aes_cbc_operation::get_key_length(algorithm)
6437 },
6438 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
6439 aes_gcm_operation::get_key_length(algorithm)
6440 },
6441 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
6442 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
6443 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
6444 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
6445 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
6446 aes_ocb_operation::get_key_length(algorithm)
6447 },
6448 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
6449 chacha20_poly1305_operation::get_key_length()
6450 },
6451 GetKeyLengthAlgorithm::Kmac(algorithm) => kmac_operation::get_key_length(algorithm),
6452 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
6453 }
6454 }
6455}
6456
6457struct EncapsulateOperation {}
6459
6460impl Operation for EncapsulateOperation {
6461 type RegisteredAlgorithm = EncapsulateAlgorithm;
6462}
6463
6464enum EncapsulateAlgorithm {
6467 MlKem(Algorithm),
6468}
6469
6470impl NormalizedAlgorithm for EncapsulateAlgorithm {
6471 fn from_object(
6472 cx: &mut js::context::JSContext,
6473 algorithm_name: CryptoAlgorithm,
6474 object: HandleObject,
6475 ) -> Fallible<Self> {
6476 match algorithm_name {
6477 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6478 Ok(EncapsulateAlgorithm::MlKem(
6479 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6480 ))
6481 },
6482 _ => Err(Error::NotSupported(Some(format!(
6483 "{} does not support \"encapsulate\" operation",
6484 algorithm_name.as_str()
6485 )))),
6486 }
6487 }
6488
6489 fn name(&self) -> CryptoAlgorithm {
6490 match self {
6491 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6492 }
6493 }
6494}
6495
6496impl EncapsulateAlgorithm {
6497 fn encapsulate(&self, key: &CryptoKey) -> Result<EncapsulatedBits, Error> {
6498 match self {
6499 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6500 }
6501 }
6502}
6503
6504struct DecapsulateOperation {}
6506
6507impl Operation for DecapsulateOperation {
6508 type RegisteredAlgorithm = DecapsulateAlgorithm;
6509}
6510
6511enum DecapsulateAlgorithm {
6514 MlKem(Algorithm),
6515}
6516
6517impl NormalizedAlgorithm for DecapsulateAlgorithm {
6518 fn from_object(
6519 cx: &mut js::context::JSContext,
6520 algorithm_name: CryptoAlgorithm,
6521 object: HandleObject,
6522 ) -> Fallible<Self> {
6523 match algorithm_name {
6524 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6525 Ok(DecapsulateAlgorithm::MlKem(
6526 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6527 ))
6528 },
6529 _ => Err(Error::NotSupported(Some(format!(
6530 "{} does not support \"decapsulate\" operation",
6531 algorithm_name.as_str()
6532 )))),
6533 }
6534 }
6535
6536 fn name(&self) -> CryptoAlgorithm {
6537 match self {
6538 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6539 }
6540 }
6541}
6542
6543impl DecapsulateAlgorithm {
6544 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
6545 match self {
6546 DecapsulateAlgorithm::MlKem(algorithm) => {
6547 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6548 },
6549 }
6550 }
6551}
6552
6553struct GetPublicKeyOperation {}
6555
6556impl Operation for GetPublicKeyOperation {
6557 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6558}
6559
6560enum GetPublicKeyAlgorithm {
6563 RsassaPkcs1v1_5(Algorithm),
6564 RsaPss(Algorithm),
6565 RsaOaep(Algorithm),
6566 Ecdsa(Algorithm),
6567 Ecdh(Algorithm),
6568 Ed25519(Algorithm),
6569 X25519(Algorithm),
6570 Ed448(Algorithm),
6571 X448(Algorithm),
6572 MlKem(Algorithm),
6573 MlDsa(Algorithm),
6574}
6575
6576impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6577 fn from_object(
6578 cx: &mut js::context::JSContext,
6579 algorithm_name: CryptoAlgorithm,
6580 object: HandleObject,
6581 ) -> Fallible<Self> {
6582 match algorithm_name {
6583 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6584 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6585 )),
6586 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6587 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6588 )),
6589 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6590 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6591 )),
6592 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6593 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6594 )),
6595 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6596 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6597 )),
6598 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6599 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6600 )),
6601 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6602 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6603 )),
6604 CryptoAlgorithm::Ed448 => Ok(GetPublicKeyAlgorithm::Ed448(
6605 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6606 )),
6607 CryptoAlgorithm::X448 => Ok(GetPublicKeyAlgorithm::X448(
6608 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6609 )),
6610 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6611 Ok(GetPublicKeyAlgorithm::MlKem(
6612 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6613 ))
6614 },
6615 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6616 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6617 ),
6618 _ => Err(Error::NotSupported(Some(format!(
6619 "{} does not support \"getPublicKey\" operation",
6620 algorithm_name.as_str()
6621 )))),
6622 }
6623 }
6624
6625 fn name(&self) -> CryptoAlgorithm {
6626 match self {
6627 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6628 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6629 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6630 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6631 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6632 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6633 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6634 GetPublicKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6635 GetPublicKeyAlgorithm::X448(algorithm) => algorithm.name,
6636 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6637 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6638 }
6639 }
6640}
6641
6642impl GetPublicKeyAlgorithm {
6643 fn get_public_key(
6644 &self,
6645 cx: &mut js::context::JSContext,
6646 global: &GlobalScope,
6647 key: &CryptoKey,
6648 algorithm: &KeyAlgorithmAndDerivatives,
6649 usages: Vec<KeyUsage>,
6650 ) -> Result<DomRoot<CryptoKey>, Error> {
6651 match self {
6652 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6653 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6654 },
6655 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6656 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6657 },
6658 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6659 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6660 },
6661 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6662 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6663 },
6664 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6665 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6666 },
6667 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6668 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6669 },
6670 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6671 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6672 },
6673 GetPublicKeyAlgorithm::Ed448(_algorithm) => {
6674 ed448_operation::get_public_key(cx, global, key, algorithm, usages)
6675 },
6676 GetPublicKeyAlgorithm::X448(_algorithm) => {
6677 x448_operation::get_public_key(cx, global, key, algorithm, usages)
6678 },
6679 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6680 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6681 },
6682 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6683 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6684 },
6685 }
6686 }
6687}