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 hybrid_kem_operation;
22mod kangarootwelve_operation;
23mod kmac_operation;
24mod ml_dsa_operation;
25mod ml_kem_operation;
26mod pbkdf2_operation;
27mod rsa_common;
28mod rsa_oaep_operation;
29mod rsa_pss_operation;
30mod rsassa_pkcs1_v1_5_operation;
31mod sha3_operation;
32mod sha_operation;
33mod turboshake_operation;
34mod x25519_operation;
35mod x448_operation;
36
37use std::fmt::Display;
38use std::marker::PhantomData;
39use std::ptr;
40use std::str::FromStr;
41
42use base64ct::{Base64UrlUnpadded, Encoding};
43use dom_struct::dom_struct;
44use js::context::JSContext;
45use js::conversions::{
46 ConversionBehavior, ConversionResult, FromJSValConvertible, ToJSValConvertible,
47};
48use js::jsapi::{Heap, JSObject};
49use js::jsval::{ObjectOrNullValue, UndefinedValue};
50use js::realm::CurrentRealm;
51use js::rooted;
52use js::rust::wrappers2::{JS_NewObject, JS_ParseJSON};
53use js::rust::{HandleObject, MutableHandleValue, Trace};
54use js::typedarray::{ArrayBufferU8, HeapUint8Array};
55use jstraceable_derive::JSTraceable;
56use malloc_size_of_derive::MallocSizeOf;
57use script_bindings::buffer_source::{create_buffer_source, get_buffer_source_copy};
58use script_bindings::codegen::GenericBindings::CryptoKeyBinding::{
59 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
60};
61use script_bindings::codegen::GenericBindings::SubtleCryptoBinding::{
62 Algorithm as AlgorithmWithDOMString, AlgorithmIdentifier, JsonWebKey, KeyFormat,
63 SubtleCryptoMethods, Wrap as SubtleCryptoWrap,
64};
65use script_bindings::codegen::GenericUnionTypes::{
66 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
67};
68use script_bindings::conversions::{StringificationBehavior, get_property};
69use script_bindings::error::{Error, Fallible};
70use script_bindings::interfaces::{
71 PromiseHelpers, StackRootPromiseHelpers, ThreadTrustedPromiseHelpers,
72};
73use script_bindings::refcounted::Trusted;
74use script_bindings::reflector::{DomGlobalGeneric, Reflector, reflect_dom_object_with_wrap};
75use script_bindings::root::DomRoot;
76use script_bindings::str::{DOMString, serialize_jsval_to_json_utf8};
77use script_bindings::trace::RootedTraceableBox;
78use script_bindings::utils::set_dictionary_property;
79use script_bindings::{DomTypes, task};
80use servo_constellation_traits::{
81 SerializableAesKeyAlgorithm, SerializableAlgorithm, SerializableCShakeParams,
82 SerializableDigestAlgorithm, SerializableEcKeyAlgorithm, SerializableHmacKeyAlgorithm,
83 SerializableKangarooTwelveParams, SerializableKeyAlgorithm,
84 SerializableKeyAlgorithmAndDerivatives, SerializableKmacKeyAlgorithm,
85 SerializableRsaHashedKeyAlgorithm, SerializableTurboShakeParams,
86};
87use strum::{EnumString, IntoStaticStr, VariantArray};
88use zeroize::Zeroizing;
89
90use crate::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
91use crate::traits::{Equivalence, WebCryptoGlobalTrait};
92
93const NAMED_CURVE_P256: &str = "P-256";
95const NAMED_CURVE_P384: &str = "P-384";
96const NAMED_CURVE_P521: &str = "P-521";
97
98static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
99
100#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
101enum CryptoAlgorithm {
102 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
103 RsassaPkcs1V1_5,
104 #[strum(serialize = "RSA-PSS")]
105 RsaPss,
106 #[strum(serialize = "RSA-OAEP")]
107 RsaOaep,
108 #[strum(serialize = "ECDSA")]
109 Ecdsa,
110 #[strum(serialize = "ECDH")]
111 Ecdh,
112 #[strum(serialize = "Ed25519")]
113 Ed25519,
114 #[strum(serialize = "X25519")]
115 X25519,
116 #[strum(serialize = "Ed448")]
117 Ed448,
118 #[strum(serialize = "X448")]
119 X448,
120 #[strum(serialize = "AES-CTR")]
121 AesCtr,
122 #[strum(serialize = "AES-CBC")]
123 AesCbc,
124 #[strum(serialize = "AES-GCM")]
125 AesGcm,
126 #[strum(serialize = "AES-KW")]
127 AesKw,
128 #[strum(serialize = "HMAC")]
129 Hmac,
130 #[strum(serialize = "SHA-1")]
131 Sha1,
132 #[strum(serialize = "SHA-256")]
133 Sha256,
134 #[strum(serialize = "SHA-384")]
135 Sha384,
136 #[strum(serialize = "SHA-512")]
137 Sha512,
138 #[strum(serialize = "HKDF")]
139 Hkdf,
140 #[strum(serialize = "PBKDF2")]
141 Pbkdf2,
142 #[strum(serialize = "ML-KEM-512")]
143 MlKem512,
144 #[strum(serialize = "ML-KEM-768")]
145 MlKem768,
146 #[strum(serialize = "ML-KEM-1024")]
147 MlKem1024,
148 #[strum(serialize = "MLKEM768-X25519")]
149 MlKem768X25519,
150 #[strum(serialize = "ML-DSA-44")]
151 MlDsa44,
152 #[strum(serialize = "ML-DSA-65")]
153 MlDsa65,
154 #[strum(serialize = "ML-DSA-87")]
155 MlDsa87,
156 #[strum(serialize = "AES-OCB")]
157 AesOcb,
158 #[strum(serialize = "ChaCha20-Poly1305")]
159 ChaCha20Poly1305,
160 #[strum(serialize = "SHA3-256")]
161 Sha3_256,
162 #[strum(serialize = "SHA3-384")]
163 Sha3_384,
164 #[strum(serialize = "SHA3-512")]
165 Sha3_512,
166 #[strum(serialize = "cSHAKE128")]
167 CShake128,
168 #[strum(serialize = "cSHAKE256")]
169 CShake256,
170 #[strum(serialize = "TurboSHAKE128")]
171 TurboShake128,
172 #[strum(serialize = "TurboSHAKE256")]
173 TurboShake256,
174 #[strum(serialize = "KT128")]
175 Kt128,
176 #[strum(serialize = "KT256")]
177 Kt256,
178 #[strum(serialize = "KMAC128")]
179 Kmac128,
180 #[strum(serialize = "KMAC256")]
181 Kmac256,
182 #[strum(serialize = "Argon2d")]
183 Argon2D,
184 #[strum(serialize = "Argon2i")]
185 Argon2I,
186 #[strum(serialize = "Argon2id")]
187 Argon2ID,
188}
189
190impl CryptoAlgorithm {
191 fn as_str(&self) -> &'static str {
193 (*self).into()
194 }
195
196 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
197 Self::VARIANTS
198 .iter()
199 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
200 .cloned()
201 .ok_or(Error::NotSupported(Some(format!(
202 "Unsupported algorithm: {algorithm_name}"
203 ))))
204 }
205}
206
207#[dom_struct]
209pub struct SubtleCrypto<D: DomTypes> {
210 reflector_: Reflector,
211 #[no_trace = "PhantomData does not exist"]
212 phantom: PhantomData<D>,
213}
214
215impl<D> SubtleCrypto<D>
216where
217 D: Equivalence,
218 Self: DomGlobalGeneric<D>,
219{
220 fn new_inherited() -> SubtleCrypto<D> {
221 SubtleCrypto {
222 reflector_: Reflector::new(),
223 phantom: PhantomData,
224 }
225 }
226
227 pub(crate) fn new(cx: &mut JSContext, global: &D::GlobalScope) -> DomRoot<SubtleCrypto<D>> {
228 reflect_dom_object_with_wrap::<D, _, _>(
229 cx,
230 Box::new(SubtleCrypto::new_inherited()),
231 global,
232 SubtleCryptoWrap::<D>,
233 )
234 }
235
236 fn resolve_promise_with_data(
240 &self,
241 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
242 data: Zeroizing<Vec<u8>>,
243 ) {
244 let trusted_promise = promise.to_trusted();
245 self.global_from_reflector()
246 .queue_crypto_task_source(task!(resolve_data: move |cx| {
247 let promise = trusted_promise.root(cx);
248
249 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
250 match create_buffer_source::<ArrayBufferU8>(cx,
251 &data,
252 array_buffer_ptr.handle_mut(),
253 ) {
254 Ok(_) => promise.resolve_native(cx, &*array_buffer_ptr),
255 Err(_) => promise.reject_error(cx, Error::JSFailed),
256 }
257 }));
258 }
259
260 fn resolve_promise_with_jwk(
264 &self,
265 cx: &mut JSContext,
266 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
267 jwk: Box<JsonWebKey>,
268 ) {
269 let stringified_jwk = match jwk.stringify(cx) {
272 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
273 Err(error) => {
274 self.reject_promise_with_error(promise, error);
275 return;
276 },
277 };
278
279 let trusted_subtle = Trusted::new(self);
280 let trusted_promise = promise.to_trusted();
281 self.global_from_reflector()
282 .queue_crypto_task_source(task!(resolve_jwk: move |cx| {
283 let subtle = trusted_subtle.root();
284 let promise = trusted_promise.root(cx);
285
286 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
287 Ok(jwk) => {
288 rooted!(&in(cx) let mut rval = UndefinedValue());
289 jwk.to_jsval(cx, rval.handle_mut());
290 rooted!(&in(cx) let mut object = rval.to_object());
291 promise.resolve_native(cx, &*object);
292 },
293 Err(error) => {
294 subtle.reject_promise_with_error(&promise, error);
295 return;
296 },
297 }
298 }));
299 }
300
301 fn resolve_promise_with_key(
304 &self,
305 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
306 key: &CryptoKey<D>,
307 ) {
308 let trusted_key = Trusted::new(key);
309 let trusted_promise = promise.to_trusted();
310 self.global_from_reflector()
311 .queue_crypto_task_source(task!(resolve_key: move |cx| {
312 let key = trusted_key.root();
313 let promise = trusted_promise.root(cx);
314 promise.resolve_native(cx, &key);
315 }));
316 }
317
318 fn resolve_promise_with_key_pair(
321 &self,
322 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
323 key_pair: CryptoKeyPair<D>,
324 ) {
325 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
326 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
327 let trusted_promise = promise.to_trusted();
328 self.global_from_reflector()
329 .queue_crypto_task_source(task!(resolve_key: move |cx| {
330 let key_pair = CryptoKeyPair::<D> {
331 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
332 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
333 };
334 let promise = trusted_promise.root(cx);
335 promise.resolve_native(cx, &key_pair);
336 }));
337 }
338
339 fn resolve_promise_with_bool(
342 &self,
343 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
344 result: bool,
345 ) {
346 let trusted_promise = promise.to_trusted();
347 self.global_from_reflector()
348 .queue_crypto_task_source(task!(resolve_bool: move |cx| {
349 let promise = trusted_promise.root(cx);
350 promise.resolve_native(cx, &result);
351 }));
352 }
353
354 fn reject_promise_with_error(
357 &self,
358 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
359 error: Error,
360 ) {
361 let trusted_promise = promise.to_trusted();
362 self.global_from_reflector()
363 .queue_crypto_task_source(task!(reject_error: move |cx| {
364 let promise = trusted_promise.root(cx);
365 promise.reject_error(cx, error);
366 }));
367 }
368
369 fn resolve_promise_with_encapsulated_key(
373 &self,
374 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
375 encapsulated_key: EncapsulatedKey<D>,
376 ) {
377 let trusted_promise = promise.to_trusted();
378 self.global_from_reflector().queue_crypto_task_source(
379 task!(resolve_encapsulated_key: move |cx| {
380 let promise = trusted_promise.root(cx);
381 promise.resolve_native(cx, &encapsulated_key);
382 }),
383 );
384 }
385
386 fn resolve_promise_with_encapsulated_bits(
390 &self,
391 promise: &<D::Promise as PromiseHelpers<D>>::StackRoot,
392 encapsulated_bits: EncapsulatedBits,
393 ) {
394 let trusted_promise = promise.to_trusted();
395 self.global_from_reflector().queue_crypto_task_source(
396 task!(resolve_encapsulated_bits: move |cx| {
397 let promise = trusted_promise.root(cx);
398 promise.resolve_native(cx, &encapsulated_bits);
399 }),
400 );
401 }
402}
403
404impl<D> SubtleCryptoMethods<D> for SubtleCrypto<D>
405where
406 D: Equivalence,
407 Self: DomGlobalGeneric<D>,
408{
409 fn Encrypt(
411 &self,
412 cx: &mut CurrentRealm,
413 algorithm: AlgorithmIdentifier,
414 key: &CryptoKey<D>,
415 data: ArrayBufferViewOrArrayBuffer,
416 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
417 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
425 Ok(normalized_algorithm) => normalized_algorithm,
426 Err(error) => {
427 let promise = D::Promise::new_in_realm(cx);
428 promise.reject_error(cx, error);
429 return promise;
430 },
431 };
432
433 let data = Zeroizing::new(get_buffer_source_copy((&data).into()));
436
437 let promise = D::Promise::new_in_realm(cx);
440
441 let this = Trusted::new(self);
443 let trusted_promise = promise.to_trusted();
444 let trusted_key = Trusted::new(key);
445 self.global_from_reflector()
446 .queue_dom_manipulation_task_source(task!(encrypt: move |cx| {
447 let subtle = this.root();
448 let promise = &trusted_promise.root(cx);
449 let key = trusted_key.root();
450
451 if normalized_algorithm.name() != key.algorithm().name() {
459 subtle.reject_promise_with_error(promise,
460 Error::InvalidAccess(Some(
461 "Algorithm's name does not equal key algorithm name".into()
462 )));
463 return;
464 }
465
466 if !key.usages().contains(&KeyUsage::Encrypt) {
469 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
470 "Key usages does not contain 'encrypt' entry".into()
471 )));
472 return;
473 }
474
475 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
479 Ok(ciphertext) => ciphertext,
480 Err(error) => {
481 subtle.reject_promise_with_error(promise, error);
482 return;
483 },
484 };
485
486 subtle.resolve_promise_with_data(promise, ciphertext.into());
492 }));
493 promise
494 }
495
496 fn Decrypt(
498 &self,
499 cx: &mut CurrentRealm,
500 algorithm: AlgorithmIdentifier,
501 key: &CryptoKey<D>,
502 data: ArrayBufferViewOrArrayBuffer,
503 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
504 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
512 Ok(normalized_algorithm) => normalized_algorithm,
513 Err(error) => {
514 let promise = D::Promise::new_in_realm(cx);
515 promise.reject_error(cx, error);
516 return promise;
517 },
518 };
519
520 let data = get_buffer_source_copy((&data).into());
523
524 let promise = D::Promise::new_in_realm(cx);
527
528 let this = Trusted::new(self);
530 let trusted_promise = promise.to_trusted();
531 let trusted_key = Trusted::new(key);
532 self.global_from_reflector()
533 .queue_dom_manipulation_task_source(task!(decrypt: move |cx| {
534 let subtle = this.root();
535 let promise = &trusted_promise.root(cx);
536 let key = trusted_key.root();
537
538 if normalized_algorithm.name() != key.algorithm().name() {
546 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
547 "Normalized algorithm name does not equal key algorithm name".into()
548 )));
549 return;
550 }
551
552 if !key.usages().contains(&KeyUsage::Decrypt) {
555 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
556 "Key usages does not contain 'decrypt' entry".into()
557 )));
558 return;
559 }
560
561 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
565 Ok(plaintext) => Zeroizing::new(plaintext),
566 Err(error) => {
567 subtle.reject_promise_with_error(promise, error);
568 return;
569 },
570 };
571
572 subtle.resolve_promise_with_data(promise, plaintext);
578 }));
579 promise
580 }
581
582 fn Sign(
584 &self,
585 cx: &mut CurrentRealm,
586 algorithm: AlgorithmIdentifier,
587 key: &CryptoKey<D>,
588 data: ArrayBufferViewOrArrayBuffer,
589 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
590 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
598 Ok(normalized_algorithm) => normalized_algorithm,
599 Err(error) => {
600 let promise = D::Promise::new_in_realm(cx);
601 promise.reject_error(cx, error);
602 return promise;
603 },
604 };
605
606 let data = get_buffer_source_copy((&data).into());
609
610 let promise = D::Promise::new_in_realm(cx);
613
614 let this = Trusted::new(self);
616 let trusted_promise = promise.to_trusted();
617 let trusted_key = Trusted::new(key);
618 self.global_from_reflector()
619 .queue_dom_manipulation_task_source(task!(sign: move |cx| {
620 let subtle = this.root();
621 let promise = &trusted_promise.root(cx);
622 let key = trusted_key.root();
623
624 if normalized_algorithm.name() != key.algorithm().name() {
632 subtle.reject_promise_with_error(promise,Error::InvalidAccess(Some(
633 "Normalized algorithm name does not equal key algorithm name".into()
634 )));
635 return;
636 }
637
638 if !key.usages().contains(&KeyUsage::Sign) {
641 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
642 "Key usages does not contain 'sign' entry".into()
643 )));
644 return;
645 }
646
647 let signature = match normalized_algorithm.sign(&key, &data) {
650 Ok(signature) => signature,
651 Err(error) => {
652 subtle.reject_promise_with_error(promise, error);
653 return;
654 },
655 };
656
657 subtle.resolve_promise_with_data(promise, signature.into());
663 }));
664 promise
665 }
666
667 fn Verify(
669 &self,
670 cx: &mut CurrentRealm,
671 algorithm: AlgorithmIdentifier,
672 key: &CryptoKey<D>,
673 signature: ArrayBufferViewOrArrayBuffer,
674 data: ArrayBufferViewOrArrayBuffer,
675 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
676 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
684 Ok(algorithm) => algorithm,
685 Err(error) => {
686 let promise = D::Promise::new_in_realm(cx);
687 promise.reject_error(cx, error);
688 return promise;
689 },
690 };
691
692 let signature = get_buffer_source_copy((&signature).into());
695
696 let data = get_buffer_source_copy((&data).into());
699
700 let promise = D::Promise::new_in_realm(cx);
703
704 let this = Trusted::new(self);
706 let trusted_promise = promise.to_trusted();
707 let trusted_key = Trusted::new(key);
708 self.global_from_reflector()
709 .queue_dom_manipulation_task_source(task!(sign: move |cx| {
710 let subtle = this.root();
711 let promise = &trusted_promise.root(cx);
712 let key = trusted_key.root();
713
714 if normalized_algorithm.name() != key.algorithm().name() {
722 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
723 "Normalized algorithm name does not equal key algorithm name".into()
724 )));
725 return;
726 }
727
728 if !key.usages().contains(&KeyUsage::Verify) {
731 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
732 "Key usages does not contain 'verify' entry".into()
733 )));
734 return;
735 }
736
737 let result = match normalized_algorithm.verify(&key, &data, &signature) {
741 Ok(result) => result,
742 Err(error) => {
743 subtle.reject_promise_with_error(promise, error);
744 return;
745 },
746 };
747
748 subtle.resolve_promise_with_bool(promise, result);
752 }));
753 promise
754 }
755
756 fn Digest(
758 &self,
759 cx: &mut CurrentRealm,
760 algorithm: AlgorithmIdentifier,
761 data: ArrayBufferViewOrArrayBuffer,
762 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
763 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
770 Ok(normalized_algorithm) => normalized_algorithm,
771 Err(error) => {
772 let promise = D::Promise::new_in_realm(cx);
773 promise.reject_error(cx, error);
774 return promise;
775 },
776 };
777
778 let data = get_buffer_source_copy((&data).into());
781
782 let promise = D::Promise::new_in_realm(cx);
785
786 let this = Trusted::new(self);
788 let trusted_promise = promise.to_trusted();
789 self.global_from_reflector()
790 .queue_dom_manipulation_task_source(task!(digest_: move |cx| {
791 let subtle = this.root();
792 let promise = &trusted_promise.root(cx);
793
794 let digest = match normalized_algorithm.digest(&data) {
801 Ok(digest) => digest,
802 Err(error) => {
803 subtle.reject_promise_with_error(promise, error);
804 return;
805 }
806 };
807
808 subtle.resolve_promise_with_data(promise, digest.into());
814 }));
815 promise
816 }
817
818 fn GenerateKey(
820 &self,
821 cx: &mut CurrentRealm,
822 algorithm: AlgorithmIdentifier,
823 extractable: bool,
824 key_usages: Vec<KeyUsage>,
825 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
826 let promise = D::Promise::new_in_realm(cx);
833 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
834 {
835 Ok(normalized_algorithm) => normalized_algorithm,
836 Err(error) => {
837 promise.reject_error(cx, error);
838 return promise;
839 },
840 };
841
842 let trusted_subtle = Trusted::new(self);
848 let trusted_promise = promise.to_trusted();
849 self.global_from_reflector()
850 .queue_dom_manipulation_task_source(task!(generate_key: move |cx| {
851 let subtle = trusted_subtle.root();
852 let promise = &trusted_promise.root(cx);
853
854 let result = match normalized_algorithm.generate_key(
861 cx,
862 &*subtle.global_from_reflector(),
863 extractable,
864 key_usages,
865 ) {
866 Ok(result) => result,
867 Err(error) => {
868 subtle.reject_promise_with_error(promise, error);
869 return;
870 }
871 };
872
873 match &result {
881 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
882 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
883 && crpyto_key.usages().is_empty()
884 {
885 subtle.reject_promise_with_error(promise, Error::Syntax(Some(
886 "Crypto key usages is empty".into()
887 )));
888 return;
889 }
890 },
891 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
892 if crypto_key_pair
893 .privateKey
894 .as_deref()
895 .is_none_or(|private_key: &CryptoKey<D>| {
896 private_key.usages().is_empty()
897 })
898 {
899 subtle.reject_promise_with_error(promise, Error::Syntax(Some(
900 "Private key usages is an empty sequence".into()
901 )));
902 return;
903 }
904 }
905 };
906
907 match result {
913 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
914 subtle.resolve_promise_with_key(promise, &key);
915 },
916 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
917 subtle.resolve_promise_with_key_pair(promise, key_pair);
918 },
919 }
920 }));
921
922 promise
923 }
924
925 fn DeriveKey(
927 &self,
928 cx: &mut CurrentRealm,
929 algorithm: AlgorithmIdentifier,
930 base_key: &CryptoKey<D>,
931 derived_key_type: AlgorithmIdentifier,
932 extractable: bool,
933 usages: Vec<KeyUsage>,
934 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
935 let promise = D::Promise::new_in_realm(cx);
944 let normalized_algorithm =
945 match normalize_algorithm::<DeriveBitsOperation<D>>(cx, &algorithm) {
946 Ok(normalized_algorithm) => normalized_algorithm,
947 Err(error) => {
948 promise.reject_error(cx, error);
949 return promise;
950 },
951 };
952
953 let normalized_derived_key_algorithm_import =
958 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
959 Ok(normalized_algorithm) => normalized_algorithm,
960 Err(error) => {
961 promise.reject_error(cx, error);
962 return promise;
963 },
964 };
965
966 let normalized_derived_key_algorithm_length =
971 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
972 Ok(normalized_algorithm) => normalized_algorithm,
973 Err(error) => {
974 promise.reject_error(cx, error);
975 return promise;
976 },
977 };
978
979 let trusted_subtle = Trusted::new(self);
985 let trusted_base_key = Trusted::new(base_key);
986 let trusted_promise = promise.to_trusted();
987 self.global_from_reflector().queue_dom_manipulation_task_source(
988 task!(derive_key: move |cx| {
989 let subtle = trusted_subtle.root();
990 let base_key = trusted_base_key.root();
991 let promise = &trusted_promise.root(cx);
992
993 if normalized_algorithm.name() != base_key.algorithm().name() {
1001 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1002 "Normalized algorithm name does not equal name of base key algorithm".into()
1003 )));
1004 return;
1005 }
1006
1007 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
1010 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1011 "Key usages does not contain 'deriveKey' entry".into()
1012 )));
1013 return;
1014 }
1015
1016 let length = match normalized_derived_key_algorithm_length.get_key_length() {
1019 Ok(length) => length,
1020 Err(error) => {
1021 subtle.reject_promise_with_error(promise, error);
1022 return;
1023 }
1024 };
1025
1026 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
1029 Ok(secret) => Zeroizing::new(secret),
1030 Err(error) => {
1031 subtle.reject_promise_with_error(promise, error);
1032 return;
1033 }
1034 };
1035
1036 let result = match normalized_derived_key_algorithm_import.import_key(
1042 cx,
1043 &*subtle.global_from_reflector(),
1044 KeyFormat::Raw_secret,
1045 &secret,
1046 extractable,
1047 usages.clone(),
1048 ) {
1049 Ok(algorithm) => algorithm,
1050 Err(error) => {
1051 subtle.reject_promise_with_error(promise, error);
1052 return;
1053 },
1054 };
1055
1056 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1059 subtle.reject_promise_with_error(promise, Error::Syntax(Some(
1060 "Key usages is empty".into()
1061 )));
1062 return;
1063 }
1064
1065 subtle.resolve_promise_with_key(promise, &result);
1076 }),
1077 );
1078 promise
1079 }
1080
1081 fn DeriveBits(
1083 &self,
1084 cx: &mut CurrentRealm,
1085 algorithm: AlgorithmIdentifier,
1086 base_key: &CryptoKey<D>,
1087 length: Option<u32>,
1088 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1089 let promise = D::Promise::new_in_realm(cx);
1097 let normalized_algorithm =
1098 match normalize_algorithm::<DeriveBitsOperation<D>>(cx, &algorithm) {
1099 Ok(normalized_algorithm) => normalized_algorithm,
1100 Err(error) => {
1101 promise.reject_error(cx, error);
1102 return promise;
1103 },
1104 };
1105
1106 let trsuted_subtle = Trusted::new(self);
1112 let trusted_base_key = Trusted::new(base_key);
1113 let trusted_promise = promise.to_trusted();
1114 self.global_from_reflector()
1115 .queue_dom_manipulation_task_source(task!(import_key: move |cx| {
1116 let subtle = trsuted_subtle.root();
1117 let base_key = trusted_base_key.root();
1118 let promise = &trusted_promise.root(cx);
1119
1120 if normalized_algorithm.name() != base_key.algorithm().name() {
1128 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1129 "Normalized algorithm name does not equal name of base key algorithm".into()
1130 )));
1131 return;
1132 }
1133
1134 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1137 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1138 "Key usages does not contain 'deriveBits' entry".into()
1139 )));
1140 return;
1141 }
1142
1143 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1146 Ok(bits) => Zeroizing::new(bits),
1147 Err(error) => {
1148 subtle.reject_promise_with_error(promise, error);
1149 return;
1150 }
1151 };
1152
1153 subtle.resolve_promise_with_data(promise, bits);
1159 }));
1160 promise
1161 }
1162
1163 fn ImportKey(
1165 &self,
1166 cx: &mut CurrentRealm,
1167 format: KeyFormat,
1168 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1169 algorithm: AlgorithmIdentifier,
1170 extractable: bool,
1171 key_usages: Vec<KeyUsage>,
1172 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1173 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1180 Ok(algorithm) => algorithm,
1181 Err(error) => {
1182 let promise = D::Promise::new_in_realm(cx);
1183 promise.reject_error(cx, error);
1184 return promise;
1185 },
1186 };
1187
1188 let key_data = match format {
1190 KeyFormat::Jwk => {
1192 match key_data {
1193 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1194 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1195 let promise = D::Promise::new_in_realm(cx);
1198 promise.reject_error(
1199 cx,
1200 Error::Type(c"The keyData type does not match the format".to_owned()),
1201 );
1202 return promise;
1203 },
1204
1205 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1206 match jwk.stringify(cx) {
1214 Ok(stringified) => {
1215 Zeroizing::new(stringified.as_bytes(cx.no_gc()).to_vec())
1216 },
1217 Err(error) => {
1218 let promise = D::Promise::new_in_realm(cx);
1219 promise.reject_error(cx, error);
1220 return promise;
1221 },
1222 }
1223 },
1224 }
1225 },
1226 _ => {
1228 match &key_data {
1229 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1232 let promise = D::Promise::new_in_realm(cx);
1233 promise.reject_error(
1234 cx,
1235 Error::Type(c"The keyData type does not match the format".to_owned()),
1236 );
1237 return promise;
1238 },
1239
1240 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1243 Zeroizing::new(get_buffer_source_copy(view.into()))
1244 },
1245 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1246 Zeroizing::new(get_buffer_source_copy(buffer.into()))
1247 },
1248 }
1249 },
1250 };
1251
1252 let promise = D::Promise::new_in_realm(cx);
1255
1256 let this = Trusted::new(self);
1258 let trusted_promise = promise.to_trusted();
1259 self.global_from_reflector()
1260 .queue_dom_manipulation_task_source(task!(import_key: move |cx| {
1261 let subtle = this.root();
1262 let promise = &trusted_promise.root(cx);
1263
1264 let result = match normalized_algorithm.import_key(
1272 cx,
1273 &*subtle.global_from_reflector(),
1274 format,
1275 &key_data,
1276 extractable,
1277 key_usages.clone(),
1278 ) {
1279 Ok(key) => key,
1280 Err(error) => {
1281 subtle.reject_promise_with_error(promise, error);
1282 return;
1283 },
1284 };
1285
1286 if matches!(result.Type(), KeyType::Secret | KeyType::Private) &&
1289 key_usages.is_empty()
1290 {
1291 subtle.reject_promise_with_error(promise, Error::Syntax(Some(
1292 "Key usages is empty".into()
1293 )));
1294 return;
1295 }
1296
1297 subtle.resolve_promise_with_key(promise, &result);
1308 }));
1309
1310 promise
1311 }
1312
1313 fn ExportKey(
1315 &self,
1316 cx: &mut CurrentRealm,
1317 format: KeyFormat,
1318 key: &CryptoKey<D>,
1319 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1320 let promise = D::Promise::new_in_realm(cx);
1327
1328 let trusted_subtle = Trusted::new(self);
1330 let trusted_promise = promise.to_trusted();
1331 let trusted_key = Trusted::new(key);
1332 self.global_from_reflector()
1333 .queue_dom_manipulation_task_source(task!(export_key: move |cx| {
1334 let subtle = trusted_subtle.root();
1335 let promise = &trusted_promise.root(cx);
1336 let key = trusted_key.root();
1337
1338 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1349 cx,
1350 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1351 ) {
1352 Ok(normalized_algorithm) => normalized_algorithm,
1353 Err(error) => {
1354 subtle.reject_promise_with_error(promise, error);
1355 return;
1356 },
1357 };
1358
1359 if !key.Extractable() {
1362 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1363 "Key is not extractable".into()
1364 )));
1365 return;
1366 }
1367
1368 let result = match export_key_algorithm.export_key(format, &key) {
1371 Ok(exported_key) => exported_key,
1372 Err(error) => {
1373 subtle.reject_promise_with_error(promise, error);
1374 return;
1375 },
1376 };
1377
1378 match result {
1391 ExportedKey::Bytes(bytes) => {
1392 subtle.resolve_promise_with_data(promise, bytes);
1393 },
1394 ExportedKey::Jwk(jwk) => {
1395 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1396 },
1397 }
1398 }));
1399 promise
1400 }
1401
1402 fn WrapKey(
1404 &self,
1405 cx: &mut CurrentRealm,
1406 format: KeyFormat,
1407 key: &CryptoKey<D>,
1408 wrapping_key: &CryptoKey<D>,
1409 algorithm: AlgorithmIdentifier,
1410 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1411 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1421 WrapKeyAlgorithm(WrapKeyAlgorithm),
1422 EncryptAlgorithm(EncryptAlgorithm),
1423 }
1424 let normalized_algorithm = if let Ok(algorithm) =
1425 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1426 {
1427 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1428 } else {
1429 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1430 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1431 Err(error) => {
1432 let promise = D::Promise::new_in_realm(cx);
1433 promise.reject_error(cx, error);
1434 return promise;
1435 },
1436 }
1437 };
1438
1439 let promise = D::Promise::new_in_realm(cx);
1442
1443 let trusted_subtle = Trusted::new(self);
1445 let trusted_key = Trusted::new(key);
1446 let trusted_wrapping_key = Trusted::new(wrapping_key);
1447 let trusted_promise = promise.to_trusted();
1448 self.global_from_reflector()
1449 .queue_dom_manipulation_task_source(task!(wrap_key: move |cx| {
1450 let subtle = trusted_subtle.root();
1451 let key = trusted_key.root();
1452 let wrapping_key = trusted_wrapping_key.root();
1453 let promise = &trusted_promise.root(cx);
1454
1455 let normalized_algorithm_name = match &normalized_algorithm {
1463 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1464 algorithm.name()
1465 },
1466 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1467 algorithm.name()
1468 },
1469 };
1470 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1471 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1472 "Normalized algorithm name does not equal name of wrapping key algorithm"
1473 .into()
1474 )));
1475 return;
1476 }
1477
1478 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1481 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1482 "Wrapping key usages does not contain 'wrapKey' entry".into()
1483 )));
1484 return;
1485 }
1486
1487 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1493 cx,
1494 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1495 ) {
1496 Ok(normalized_algorithm) => normalized_algorithm,
1497 Err(error) => {
1498 subtle.reject_promise_with_error(promise, error);
1499 return;
1500 },
1501 };
1502
1503 if !key.Extractable() {
1506 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1507 "Key is not extractable".into()
1508 )));
1509 return;
1510 }
1511
1512 let exported_key = match export_key_algorithm.export_key(format, &key) {
1515 Ok(exported_key) => exported_key,
1516 Err(error) => {
1517 subtle.reject_promise_with_error(promise, error);
1518 return;
1519 },
1520 };
1521
1522 let bytes = match exported_key {
1534 ExportedKey::Bytes(bytes) => bytes,
1535 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1536 Ok(stringified_jwk) => {
1537 Zeroizing::new(stringified_jwk.as_bytes(cx.no_gc()).to_vec())
1538 },
1539 Err(error) => {
1540 subtle.reject_promise_with_error(promise, error);
1541 return;
1542 },
1543 },
1544 };
1545
1546 let result = match normalized_algorithm {
1558 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1559 algorithm.wrap_key(&wrapping_key, &bytes)
1560 },
1561 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1562 algorithm.encrypt(&wrapping_key, &bytes)
1563 },
1564 };
1565 let result = match result {
1566 Ok(result) => result,
1567 Err(error) => {
1568 subtle.reject_promise_with_error(promise, error);
1569 return;
1570 },
1571 };
1572
1573 subtle.resolve_promise_with_data(promise, result.into());
1579 }));
1580 promise
1581 }
1582
1583 fn UnwrapKey(
1585 &self,
1586 cx: &mut CurrentRealm,
1587 format: KeyFormat,
1588 wrapped_key: ArrayBufferViewOrArrayBuffer,
1589 unwrapping_key: &CryptoKey<D>,
1590 algorithm: AlgorithmIdentifier,
1591 unwrapped_key_algorithm: AlgorithmIdentifier,
1592 extractable: bool,
1593 usages: Vec<KeyUsage>,
1594 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1595 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1606 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1607 DecryptAlgorithm(DecryptAlgorithm),
1608 }
1609 let normalized_algorithm = if let Ok(algorithm) =
1610 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1611 {
1612 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1613 } else {
1614 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1615 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1616 Err(error) => {
1617 let promise = D::Promise::new_in_realm(cx);
1618 promise.reject_error(cx, error);
1619 return promise;
1620 },
1621 }
1622 };
1623
1624 let normalized_key_algorithm =
1628 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1629 Ok(algorithm) => algorithm,
1630 Err(error) => {
1631 let promise = D::Promise::new_in_realm(cx);
1632 promise.reject_error(cx, error);
1633 return promise;
1634 },
1635 };
1636
1637 let wrapped_key = get_buffer_source_copy((&wrapped_key).into());
1640
1641 let promise = D::Promise::new_in_realm(cx);
1644
1645 let trusted_subtle = Trusted::new(self);
1647 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1648 let trusted_promise = promise.to_trusted();
1649 self.global_from_reflector()
1650 .queue_dom_manipulation_task_source(task!(unwrap_key: move |cx| {
1651 let subtle = trusted_subtle.root();
1652 let unwrapping_key = trusted_unwrapping_key.root();
1653 let promise = &trusted_promise.root(cx);
1654
1655 let normalized_algorithm_name = match &normalized_algorithm {
1663 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1664 algorithm.name()
1665 },
1666 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1667 algorithm.name()
1668 },
1669 };
1670 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1671 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1672 "Normalized algorithm name does not equal name of unwrapping key algorithm"
1673 .into()
1674 )));
1675 return;
1676 }
1677
1678 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1681 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1682 "Unwrapping key usages does not contain 'unwrapKey' entry".into()
1683 )));
1684 return;
1685 }
1686
1687 let bytes = match normalized_algorithm {
1699 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1700 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1701 },
1702 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1703 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1704 },
1705 };
1706 let bytes = match bytes {
1707 Ok(bytes) => Zeroizing::new(bytes),
1708 Err(error) => {
1709 subtle.reject_promise_with_error(promise, error);
1710 return;
1711 },
1712 };
1713
1714 if format == KeyFormat::Jwk
1725 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1726 subtle.reject_promise_with_error(promise, error);
1727 return;
1728 }
1729 let key = bytes;
1730
1731 let result = match normalized_key_algorithm.import_key(
1735 cx,
1736 &*subtle.global_from_reflector(),
1737 format,
1738 &key,
1739 extractable,
1740 usages.clone(),
1741 ) {
1742 Ok(result) => result,
1743 Err(error) => {
1744 subtle.reject_promise_with_error(promise, error);
1745 return;
1746 },
1747 };
1748
1749 if matches!(result.Type(), KeyType::Secret | KeyType::Private) &&
1752 usages.is_empty()
1753 {
1754 subtle.reject_promise_with_error(promise, Error::Syntax(Some(
1755 "Key usages is empty".into()
1756 )));
1757 return;
1758 }
1759
1760 subtle.resolve_promise_with_key(promise, &result);
1771 }));
1772 promise
1773 }
1774
1775 fn EncapsulateKey(
1777 &self,
1778 cx: &mut CurrentRealm,
1779 encapsulation_algorithm: AlgorithmIdentifier,
1780 encapsulation_key: &CryptoKey<D>,
1781 shared_key_algorithm: AlgorithmIdentifier,
1782 extractable: bool,
1783 usages: Vec<KeyUsage>,
1784 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1785 let promise = D::Promise::new_in_realm(cx);
1795 let normalized_encapsulation_algorithm =
1796 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1797 Ok(algorithm) => algorithm,
1798 Err(error) => {
1799 promise.reject_error(cx, error);
1800 return promise;
1801 },
1802 };
1803
1804 let normalized_shared_key_algorithm =
1809 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1810 Ok(algorithm) => algorithm,
1811 Err(error) => {
1812 promise.reject_error(cx, error);
1813 return promise;
1814 },
1815 };
1816
1817 let trusted_subtle = Trusted::new(self);
1823 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1824 let trusted_promise = promise.to_trusted();
1825 self.global_from_reflector().queue_dom_manipulation_task_source(
1826 task!(encapsulate_keys: move |cx| {
1827 let subtle = trusted_subtle.root();
1828 let encapsulation_key = trusted_encapsulated_key.root();
1829 let promise = &trusted_promise.root(cx);
1830
1831 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1839 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1840 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1841 normalizedEncapsulationAlgorithm".to_string(),
1842 )));
1843 return;
1844 }
1845
1846 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1849 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1850 "[[usages]] internal slot of encapsulationKey does not contain an \
1851 entry that is \"encapsulateBits\"".to_string(),
1852 )));
1853 return;
1854 }
1855
1856 let encapsulated_bits_result =
1862 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1863 let encapsulated_bits = match encapsulated_bits_result {
1864 Ok(encapsulated_bits) => encapsulated_bits,
1865 Err(error) => {
1866 subtle.reject_promise_with_error(promise, error);
1867 return;
1868 },
1869 };
1870
1871 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1880 Some(shared_key) => shared_key,
1881 None => {
1882 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1883 "Shared key is missing in the result of the encapsulate operation"
1884 .to_string())));
1885 return;
1886 },
1887 };
1888 let shared_key_result = normalized_shared_key_algorithm.import_key(
1889 cx,
1890 &*subtle.global_from_reflector(),
1891 KeyFormat::Raw_secret,
1892 encapsulated_shared_key,
1893 extractable,
1894 usages.clone(),
1895 );
1896 let shared_key = match shared_key_result {
1897 Ok(shared_key) => shared_key,
1898 Err(error) => {
1899 subtle.reject_promise_with_error(promise, error);
1900 return;
1901 },
1902 };
1903
1904 let encapsulated_key = EncapsulatedKey {
1907 shared_key: Some(Trusted::new(&shared_key)),
1908 ciphertext:encapsulated_bits.ciphertext,
1909 };
1910
1911 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1917 })
1918 );
1919 promise
1920 }
1921
1922 fn EncapsulateBits(
1924 &self,
1925 cx: &mut CurrentRealm,
1926 encapsulation_algorithm: AlgorithmIdentifier,
1927 encapsulation_key: &CryptoKey<D>,
1928 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
1929 let promise = D::Promise::new_in_realm(cx);
1937 let normalized_encapsulation_algorithm =
1938 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1939 Ok(algorithm) => algorithm,
1940 Err(error) => {
1941 promise.reject_error(cx, error);
1942 return promise;
1943 },
1944 };
1945
1946 let trusted_subtle = Trusted::new(self);
1952 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1953 let trusted_promise = promise.to_trusted();
1954 self.global_from_reflector().queue_dom_manipulation_task_source(
1955 task!(derive_key: move |cx| {
1956 let subtle = trusted_subtle.root();
1957 let encapsulation_key = trusted_encapsulation_key.root();
1958 let promise = &trusted_promise.root(cx);
1959
1960 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1968 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1969 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1970 normalizedEncapsulationAlgorithm".to_string(),
1971 )));
1972 return;
1973 }
1974
1975 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1978 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1979 "[[usages]] internal slot of encapsulationKey does not contain an \
1980 entry that is \"encapsulateBits\"".to_string(),
1981 )));
1982 return;
1983 }
1984
1985 let encapsulated_bits =
1991 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1992 Ok(encapsulated_bits) => encapsulated_bits,
1993 Err(error) => {
1994 subtle.reject_promise_with_error(promise, error);
1995 return;
1996 },
1997 };
1998
1999 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
2005 }),
2006 );
2007 promise
2008 }
2009
2010 fn DecapsulateKey(
2012 &self,
2013 cx: &mut CurrentRealm,
2014 decapsulation_algorithm: AlgorithmIdentifier,
2015 decapsulation_key: &CryptoKey<D>,
2016 ciphertext: ArrayBufferViewOrArrayBuffer,
2017 shared_key_algorithm: AlgorithmIdentifier,
2018 extractable: bool,
2019 usages: Vec<KeyUsage>,
2020 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
2021 let normalized_decapsulation_algorithm =
2031 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2032 Ok(normalized_algorithm) => normalized_algorithm,
2033 Err(error) => {
2034 let promise = D::Promise::new_in_realm(cx);
2035 promise.reject_error(cx, error);
2036 return promise;
2037 },
2038 };
2039
2040 let normalized_shared_key_algorithm =
2045 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
2046 Ok(normalized_algorithm) => normalized_algorithm,
2047 Err(error) => {
2048 let promise = D::Promise::new_in_realm(cx);
2049 promise.reject_error(cx, error);
2050 return promise;
2051 },
2052 };
2053
2054 let ciphertext = get_buffer_source_copy((&ciphertext).into());
2057
2058 let promise = D::Promise::new_in_realm(cx);
2061
2062 let trusted_subtle = Trusted::new(self);
2064 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2065 let trusted_promise = promise.to_trusted();
2066 self.global_from_reflector()
2067 .queue_dom_manipulation_task_source(task!(decapsulate_key: move |cx| {
2068 let subtle = trusted_subtle.root();
2069 let promise = &trusted_promise.root(cx);
2070 let decapsulation_key = trusted_decapsulation_key.root();
2071
2072 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2080 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2081 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2082 normalizedDecapsulationAlgorithm".to_string()
2083 )));
2084 return;
2085 }
2086
2087 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2090 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2091 "[[usages]] internal slot of decapsulationKey does not contain an \
2092 entry that is \"decapsulateBits\"".to_string(),
2093 )));
2094 return;
2095 }
2096
2097 let decapsulated_bits_result =
2103 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2104 let decapsulated_bits = match decapsulated_bits_result {
2105 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2106 Err(error) => {
2107 subtle.reject_promise_with_error(promise, error);
2108 return;
2109 },
2110 };
2111
2112
2113 let shared_key_result = normalized_shared_key_algorithm.import_key(
2122 cx,
2123 &*subtle.global_from_reflector(),
2124 KeyFormat::Raw_secret,
2125 &decapsulated_bits,
2126 extractable,
2127 usages.clone(),
2128 );
2129 let shared_key = match shared_key_result {
2130 Ok(shared_key) => shared_key,
2131 Err(error) => {
2132 subtle.reject_promise_with_error(promise, error);
2133 return;
2134 },
2135 };
2136
2137 subtle.resolve_promise_with_key(promise, &shared_key);
2143 }));
2144 promise
2145 }
2146
2147 fn DecapsulateBits(
2149 &self,
2150 cx: &mut CurrentRealm,
2151 decapsulation_algorithm: AlgorithmIdentifier,
2152 decapsulation_key: &CryptoKey<D>,
2153 ciphertext: ArrayBufferViewOrArrayBuffer,
2154 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
2155 let normalized_decapsulation_algorithm =
2163 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2164 Ok(normalized_algorithm) => normalized_algorithm,
2165 Err(error) => {
2166 let promise = D::Promise::new_in_realm(cx);
2167 promise.reject_error(cx, error);
2168 return promise;
2169 },
2170 };
2171
2172 let ciphertext = get_buffer_source_copy((&ciphertext).into());
2175
2176 let promise = D::Promise::new_in_realm(cx);
2179
2180 let trusted_subtle = Trusted::new(self);
2182 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2183 let trusted_promise = promise.to_trusted();
2184 self.global_from_reflector()
2185 .queue_dom_manipulation_task_source(task!(decapsulate_bits: move |cx| {
2186 let subtle = trusted_subtle.root();
2187 let promise = &trusted_promise.root(cx);
2188 let decapsulation_key = trusted_decapsulation_key.root();
2189
2190 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2198 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2199 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2200 normalizedDecapsulationAlgorithm".to_string()
2201 )));
2202 return;
2203 }
2204
2205 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2208 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2209 "[[usages]] internal slot of decapsulationKey does not contain an \
2210 entry that is \"decapsulateBits\"".to_string(),
2211 )));
2212 return;
2213 }
2214
2215 let decapsulated_bits_result =
2221 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2222 let decapsulated_bits = match decapsulated_bits_result {
2223 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2224 Err(error) => {
2225 subtle.reject_promise_with_error(promise, error);
2226 return;
2227 },
2228 };
2229
2230 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2236 }));
2237 promise
2238 }
2239
2240 fn GetPublicKey(
2242 &self,
2243 cx: &mut CurrentRealm,
2244 key: &CryptoKey<D>,
2245 usages: Vec<KeyUsage>,
2246 ) -> <D::Promise as PromiseHelpers<D>>::StackRoot {
2247 let algorithm = key.algorithm();
2252
2253 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2260 cx,
2261 &AlgorithmIdentifier::String(DOMString::from_static(algorithm.name().as_str())),
2262 ) {
2263 Ok(normalized_algorithm) => normalized_algorithm,
2264 Err(error) => {
2265 let promise = D::Promise::new_in_realm(cx);
2266 promise.reject_error(cx, error);
2267 return promise;
2268 },
2269 };
2270
2271 let promise = D::Promise::new_in_realm(cx);
2274
2275 let trusted_subtle = Trusted::new(self);
2277 let trusted_promise = promise.to_trusted();
2278 let trusted_key = Trusted::new(key);
2279 self.global_from_reflector()
2280 .queue_dom_manipulation_task_source(task!(get_public_key: move |cx| {
2281 let subtle = trusted_subtle.root();
2282 let promise = &trusted_promise.root(cx);
2283 let key = trusted_key.root();
2284
2285 if let Err(error) = key.ensure_type(KeyType::Private) {
2292 subtle.reject_promise_with_error(promise, error);
2293 return;
2294 }
2295
2296 let result = match get_public_key_algorithm.get_public_key(
2310 cx,
2311 &*subtle.global_from_reflector(),
2312 &key,
2313 key.algorithm(),
2314 usages.clone(),
2315 ) {
2316 Ok(public_key) => public_key,
2317 Err(error) => {
2318 subtle.reject_promise_with_error(promise, error);
2319 return;
2320 },
2321 };
2322
2323 subtle.resolve_promise_with_key(promise, &result);
2329 }));
2330 promise
2331 }
2332
2333 fn Supports(
2335 cx: &mut JSContext,
2336 _global: &D::GlobalScope,
2337 operation: DOMString,
2338 algorithm: AlgorithmIdentifier,
2339 length: Option<u32>,
2340 ) -> bool {
2341 let operation = &*operation.str();
2346 if !matches!(
2347 operation,
2348 "encrypt" |
2349 "decrypt" |
2350 "sign" |
2351 "verify" |
2352 "digest" |
2353 "generateKey" |
2354 "deriveKey" |
2355 "deriveBits" |
2356 "importKey" |
2357 "exportKey" |
2358 "wrapKey" |
2359 "unwrapKey" |
2360 "encapsulateKey" |
2361 "encapsulateBits" |
2362 "decapsulateKey" |
2363 "decapsulateBits" |
2364 "getPublicKey"
2365 ) {
2366 return false;
2367 }
2368
2369 check_support_for_algorithm::<D>(cx, operation, &algorithm, length)
2372 }
2373
2374 fn Supports_(
2376 cx: &mut JSContext,
2377 _global: &D::GlobalScope,
2378 operation: DOMString,
2379 algorithm: AlgorithmIdentifier,
2380 additional_algorithm: AlgorithmIdentifier,
2381 ) -> bool {
2382 let mut operation = &*operation.str();
2387 if !matches!(
2388 operation,
2389 "encrypt" |
2390 "decrypt" |
2391 "sign" |
2392 "verify" |
2393 "digest" |
2394 "generateKey" |
2395 "deriveKey" |
2396 "deriveBits" |
2397 "importKey" |
2398 "exportKey" |
2399 "wrapKey" |
2400 "unwrapKey" |
2401 "encapsulateKey" |
2402 "encapsulateBits" |
2403 "decapsulateKey" |
2404 "decapsulateBits" |
2405 "getPublicKey"
2406 ) {
2407 return false;
2408 }
2409
2410 if matches!(operation, "deriveKey" | "unwrapKey") &&
2418 !check_support_for_algorithm::<D>(cx, "importKey", &additional_algorithm, None)
2419 {
2420 return false;
2421 }
2422 if operation == "wrapKey" &&
2423 !check_support_for_algorithm::<D>(cx, "exportKey", &additional_algorithm, None)
2424 {
2425 return false;
2426 }
2427
2428 if matches!(operation, "encapsulateKey" | "decapsulateKey") {
2430 let Ok(normalized_algorithm) =
2434 normalize_algorithm::<GetSharedKeyLengthOperation>(cx, &algorithm)
2435 else {
2436 return false;
2437 };
2438
2439 let shared_key_length = normalized_algorithm.get_shared_key_length();
2442
2443 let Ok(normalized_additional_algorithm) =
2447 normalize_algorithm::<ImportKeyOperation>(cx, &additional_algorithm)
2448 else {
2449 return false;
2450 };
2451
2452 if !normalized_additional_algorithm.determine_support_from_operation_steps(None) {
2460 return false;
2461 }
2462
2463 if normalized_additional_algorithm.will_throw_for_key_data_length(shared_key_length) {
2467 return false;
2468 }
2469 }
2470
2471 let mut length = None;
2473
2474 if operation == "deriveKey" {
2476 if !check_support_for_algorithm::<D>(cx, "get key length", &additional_algorithm, None)
2479 {
2480 return false;
2481 }
2482
2483 let Ok(normalized_additional_algorithm) =
2486 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2487 else {
2488 return false;
2489 };
2490
2491 match normalized_additional_algorithm.get_key_length() {
2494 Ok(key_length) => {
2495 length = key_length;
2496 },
2497 Err(_) => return false,
2498 };
2499
2500 operation = "deriveBits";
2502 }
2503
2504 check_support_for_algorithm::<D>(cx, operation, &algorithm, length)
2507 }
2508}
2509
2510fn check_support_for_algorithm<D: Equivalence>(
2512 cx: &mut JSContext,
2513 mut operation: &str,
2514 algorithm: &AlgorithmIdentifier,
2515 length: Option<u32>,
2516) -> bool {
2517 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2519 operation = "encapsulate";
2520 }
2521
2522 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2524 operation = "decapsulate";
2525 }
2526
2527 if operation == "getPublicKey" {
2529 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2533 else {
2534 return false;
2535 };
2536
2537 return normalize_algorithm::<GetPublicKeyOperation>(
2544 cx,
2545 &AlgorithmIdentifier::String(DOMString::from_static(
2546 normalized_algorithm.name().as_str(),
2547 )),
2548 )
2549 .is_ok();
2550 }
2551
2552 match operation {
2563 "encrypt" => {
2564 normalize_and_determine_support::<EncryptOperation, D>(cx, operation, algorithm, length)
2565 },
2566 "decrypt" => {
2567 normalize_and_determine_support::<DecryptOperation, D>(cx, operation, algorithm, length)
2568 },
2569 "sign" => {
2570 normalize_and_determine_support::<SignOperation, D>(cx, operation, algorithm, length)
2571 },
2572 "verify" => {
2573 normalize_and_determine_support::<VerifyOperation, D>(cx, operation, algorithm, length)
2574 },
2575 "digest" => {
2576 normalize_and_determine_support::<DigestOperation, D>(cx, operation, algorithm, length)
2577 },
2578 "deriveBits" => normalize_and_determine_support::<DeriveBitsOperation<D>, D>(
2579 cx, operation, algorithm, length,
2580 ),
2581 "wrapKey" => {
2582 normalize_and_determine_support::<WrapKeyOperation, D>(cx, operation, algorithm, length)
2583 },
2584 "unwrapKey" => normalize_and_determine_support::<UnwrapKeyOperation, D>(
2585 cx, operation, algorithm, length,
2586 ),
2587 "generateKey" => normalize_and_determine_support::<GenerateKeyOperation, D>(
2588 cx, operation, algorithm, length,
2589 ),
2590 "importKey" => normalize_and_determine_support::<ImportKeyOperation, D>(
2591 cx, operation, algorithm, length,
2592 ),
2593 "exportKey" => normalize_and_determine_support::<ExportKeyOperation, D>(
2594 cx, operation, algorithm, length,
2595 ),
2596 "get key length" => normalize_and_determine_support::<GetKeyLengthOperation, D>(
2597 cx, operation, algorithm, length,
2598 ),
2599 "encapsulate" => normalize_and_determine_support::<EncapsulateOperation, D>(
2600 cx, operation, algorithm, length,
2601 ),
2602 "decapsulate" => normalize_and_determine_support::<DecapsulateOperation, D>(
2603 cx, operation, algorithm, length,
2604 ),
2605 _ => false,
2606 }
2607}
2608
2609fn normalize_and_determine_support<T: Operation, D: Equivalence>(
2612 cx: &mut JSContext,
2613 op: &str,
2614 algorithm: &AlgorithmIdentifier,
2615 length: Option<u32>,
2616) -> bool {
2617 if let Ok(normalized_algorithm) = normalize_algorithm::<T>(cx, algorithm) {
2618 normalized_algorithm.determine_support_from_operation_steps(length)
2619 } else {
2620 match op {
2621 "wrapKey" => check_support_for_algorithm::<D>(cx, "encrypt", algorithm, length),
2622 "unwrapKey" => check_support_for_algorithm::<D>(cx, "decrypt", algorithm, length),
2623 _ => false,
2624 }
2625 }
2626}
2627
2628trait TryFromWithCxAndName<T>: Sized {
2630 type Error;
2631
2632 fn try_from_with_cx_and_name(
2633 cx: &mut JSContext,
2634 algorithm_name: CryptoAlgorithm,
2635 value: T,
2636 ) -> Result<Self, Self::Error>;
2637}
2638
2639trait TryIntoWithCxAndName<T>: Sized {
2641 type Error;
2642
2643 fn try_into_with_cx_and_name(
2644 self,
2645 cx: &mut JSContext,
2646 algorithm_name: CryptoAlgorithm,
2647 ) -> Result<T, Self::Error>;
2648}
2649
2650impl<T, U> TryIntoWithCxAndName<U> for T
2651where
2652 U: TryFromWithCxAndName<T>,
2653{
2654 type Error = U::Error;
2655
2656 fn try_into_with_cx_and_name(
2657 self,
2658 cx: &mut JSContext,
2659 algorithm_name: CryptoAlgorithm,
2660 ) -> Result<U, Self::Error> {
2661 U::try_from_with_cx_and_name(cx, algorithm_name, self)
2662 }
2663}
2664
2665#[derive(Clone, MallocSizeOf)]
2685struct Algorithm {
2686 name: CryptoAlgorithm,
2688}
2689
2690impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Algorithm {
2691 type Error = Error;
2692
2693 fn try_from_with_cx_and_name(
2694 _cx: &mut JSContext,
2695 algorithm_name: CryptoAlgorithm,
2696 _object: HandleObject<'a>,
2697 ) -> Result<Self, Self::Error> {
2698 Ok(Algorithm {
2699 name: algorithm_name,
2700 })
2701 }
2702}
2703
2704impl TryFrom<SerializableAlgorithm> for Algorithm {
2705 type Error = ();
2706
2707 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2708 Ok(Algorithm {
2709 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2710 })
2711 }
2712}
2713
2714impl From<&Algorithm> for SerializableAlgorithm {
2715 fn from(value: &Algorithm) -> Self {
2716 SerializableAlgorithm {
2717 name: value.name.as_str().into(),
2718 }
2719 }
2720}
2721
2722#[derive(Clone, MallocSizeOf)]
2724pub(crate) struct KeyAlgorithm {
2725 name: CryptoAlgorithm,
2727}
2728
2729impl ToJSValConvertible for KeyAlgorithm {
2730 #[expect(unsafe_code)]
2731 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
2732 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2733
2734 rooted!(&in(cx) let mut name_js = UndefinedValue());
2735 self.name.as_str().to_jsval(cx, name_js.handle_mut());
2736 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2737 .expect("Failed to set name property of KeyAlgorithm");
2738
2739 rval.set(ObjectOrNullValue(object.get()));
2740 }
2741}
2742
2743impl TryFrom<SerializableKeyAlgorithm> for KeyAlgorithm {
2744 type Error = ();
2745
2746 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2747 Ok(KeyAlgorithm {
2748 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2749 })
2750 }
2751}
2752
2753impl From<&KeyAlgorithm> for SerializableKeyAlgorithm {
2754 fn from(value: &KeyAlgorithm) -> Self {
2755 SerializableKeyAlgorithm {
2756 name: value.name.as_str().into(),
2757 }
2758 }
2759}
2760
2761#[derive(Clone, MallocSizeOf)]
2763pub(crate) struct RsaHashedKeyGenParams {
2764 name: CryptoAlgorithm,
2766
2767 modulus_length: u32,
2769
2770 public_exponent: Vec<u8>,
2772
2773 hash: DigestAlgorithm,
2775}
2776
2777impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedKeyGenParams {
2778 type Error = Error;
2779
2780 fn try_from_with_cx_and_name(
2781 cx: &mut JSContext,
2782 algorithm_name: CryptoAlgorithm,
2783 object: HandleObject,
2784 ) -> Result<Self, Self::Error> {
2785 let hash = get_required_parameter(cx, object, c"hash", ())?;
2786
2787 Ok(RsaHashedKeyGenParams {
2788 name: algorithm_name,
2789 modulus_length: get_required_parameter(
2790 cx,
2791 object,
2792 c"modulusLength",
2793 ConversionBehavior::EnforceRange,
2794 )?,
2795 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2796 cx,
2797 object,
2798 c"publicExponent",
2799 (),
2800 )?
2801 .to_vec()
2802 .unwrap_or_default(),
2803 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2804 })
2805 }
2806}
2807
2808impl RsaHashedKeyGenParams {
2809 fn validate_parameters(&self) -> Result<(), Error> {
2811 let modulus_length = self.modulus_length;
2813
2814 let public_exponent = &self.public_exponent;
2817
2818 let is_less_than_3 = |public_exponent: &[u8]| {
2821 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2822 byte_iterator.next().is_none_or(|byte| *byte < 3) && byte_iterator.count() == 0
2823 };
2824 let is_even =
2825 |public_exponent: &[u8]| public_exponent.last().is_none_or(|byte| byte % 2 == 0);
2826 let upper_bound_first_byte = (1u8 << (modulus_length % 8)).wrapping_sub(1);
2827 let upper_bound_length_in_bytes = modulus_length.div_ceil(8) as usize;
2828 let is_greater_than_upper_bound = |public_exponent: &[u8]| {
2829 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2830 byte_iterator
2831 .next()
2832 .is_some_and(|byte| *byte > upper_bound_first_byte) &&
2833 byte_iterator.count() + 1 >= upper_bound_length_in_bytes
2834 };
2835 let is_equal_to_upper_bound = |public_exponent: &[u8]| {
2836 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2837 byte_iterator
2838 .next()
2839 .is_some_and(|byte| *byte == upper_bound_first_byte) &&
2840 byte_iterator.clone().all(|byte| *byte == 255) &&
2841 byte_iterator.count() + 1 == upper_bound_length_in_bytes
2842 };
2843 if modulus_length < 4 ||
2844 is_less_than_3(public_exponent) ||
2845 is_even(public_exponent) ||
2846 is_greater_than_upper_bound(public_exponent) ||
2847 is_equal_to_upper_bound(public_exponent)
2848 {
2849 return Err(Error::Operation(Some(
2850 "Invalid RsaHashedKeyGenParams".into(),
2851 )));
2852 }
2853
2854 Ok(())
2855 }
2856}
2857
2858#[derive(Clone, MallocSizeOf)]
2860pub(crate) struct RsaHashedKeyAlgorithm {
2861 name: CryptoAlgorithm,
2863
2864 modulus_length: u32,
2866
2867 public_exponent: Vec<u8>,
2869
2870 hash: DigestAlgorithm,
2872}
2873
2874impl ToJSValConvertible for RsaHashedKeyAlgorithm {
2875 #[expect(unsafe_code)]
2876 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
2877 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2878
2879 rooted!(&in(cx) let mut name_js = UndefinedValue());
2880 self.name.as_str().to_jsval(cx, name_js.handle_mut());
2881 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2882 .expect("Failed to set name property of RsaHashedKeyAlgorithm");
2883
2884 rooted!(&in(cx) let mut modulus_length_js = UndefinedValue());
2885 self.modulus_length
2886 .to_jsval(cx, modulus_length_js.handle_mut());
2887 set_dictionary_property(
2888 cx,
2889 object.handle(),
2890 c"modulusLength",
2891 modulus_length_js.handle(),
2892 )
2893 .expect("Failed to set modulusLength property of RsaHashedKeyAlgorithm");
2894
2895 rooted!(&in(cx) let mut public_exponent_js = UndefinedValue());
2896 rooted!(&in(cx) let mut public_exponent_js_object = ptr::null_mut::<JSObject>());
2897 let public_exponent = create_buffer_source::<ArrayBufferU8>(
2898 cx,
2899 &self.public_exponent,
2900 public_exponent_js_object.handle_mut(),
2901 )
2902 .expect("Failed to convert publicExponent to Uint8Array");
2903 public_exponent.to_jsval(cx, public_exponent_js.handle_mut());
2904 set_dictionary_property(
2905 cx,
2906 object.handle(),
2907 c"publicExponent",
2908 public_exponent_js.handle(),
2909 )
2910 .expect("Failed to set publicExponent property of RsaHashedKeyAlgorithm");
2911
2912 rooted!(&in(cx) let mut hash_js = UndefinedValue());
2913 let hash = KeyAlgorithm {
2914 name: self.hash.name(),
2915 };
2916 hash.to_jsval(cx, hash_js.handle_mut());
2917 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
2918 .expect("Failed to set hash property of RsaHashedKeyAlgorithm");
2919
2920 rval.set(ObjectOrNullValue(object.get()));
2921 }
2922}
2923
2924impl TryFrom<SerializableRsaHashedKeyAlgorithm> for RsaHashedKeyAlgorithm {
2925 type Error = ();
2926
2927 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
2928 Ok(RsaHashedKeyAlgorithm {
2929 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2930 modulus_length: value.modulus_length,
2931 public_exponent: value.public_exponent,
2932 hash: value.hash.try_into()?,
2933 })
2934 }
2935}
2936
2937impl From<&RsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
2938 fn from(value: &RsaHashedKeyAlgorithm) -> Self {
2939 SerializableRsaHashedKeyAlgorithm {
2940 name: value.name.as_str().into(),
2941 modulus_length: value.modulus_length,
2942 public_exponent: value.public_exponent.clone(),
2943 hash: (&value.hash).into(),
2944 }
2945 }
2946}
2947
2948#[derive(Clone, MallocSizeOf)]
2950struct RsaHashedImportParams {
2951 name: CryptoAlgorithm,
2953
2954 hash: DigestAlgorithm,
2956}
2957
2958impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedImportParams {
2959 type Error = Error;
2960
2961 fn try_from_with_cx_and_name(
2962 cx: &mut JSContext,
2963 algorithm_name: CryptoAlgorithm,
2964 object: HandleObject,
2965 ) -> Result<Self, Self::Error> {
2966 let hash = get_required_parameter(cx, object, c"hash", ())?;
2967
2968 Ok(RsaHashedImportParams {
2969 name: algorithm_name,
2970 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2971 })
2972 }
2973}
2974
2975#[derive(Clone, MallocSizeOf)]
2977struct RsaPssParams {
2978 name: CryptoAlgorithm,
2980
2981 salt_length: u32,
2983}
2984
2985impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaPssParams {
2986 type Error = Error;
2987
2988 fn try_from_with_cx_and_name(
2989 cx: &mut JSContext,
2990 algorithm_name: CryptoAlgorithm,
2991 object: HandleObject,
2992 ) -> Result<Self, Self::Error> {
2993 Ok(RsaPssParams {
2994 name: algorithm_name,
2995 salt_length: get_required_parameter(
2996 cx,
2997 object,
2998 c"saltLength",
2999 ConversionBehavior::EnforceRange,
3000 )?,
3001 })
3002 }
3003}
3004
3005#[derive(Clone, MallocSizeOf)]
3007struct RsaOaepParams {
3008 name: CryptoAlgorithm,
3010
3011 label: Option<Vec<u8>>,
3013}
3014
3015impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaOaepParams {
3016 type Error = Error;
3017
3018 fn try_from_with_cx_and_name(
3019 cx: &mut JSContext,
3020 algorithm_name: CryptoAlgorithm,
3021 object: HandleObject<'a>,
3022 ) -> Result<Self, Self::Error> {
3023 Ok(RsaOaepParams {
3024 name: algorithm_name,
3025 label: get_optional_buffer_source(cx, object, c"label")?,
3026 })
3027 }
3028}
3029
3030#[derive(Clone, MallocSizeOf)]
3032struct EcdsaParams {
3033 name: CryptoAlgorithm,
3035
3036 hash: DigestAlgorithm,
3038}
3039
3040impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcdsaParams {
3041 type Error = Error;
3042
3043 fn try_from_with_cx_and_name(
3044 cx: &mut JSContext,
3045 algorithm_name: CryptoAlgorithm,
3046 object: HandleObject<'a>,
3047 ) -> Result<Self, Self::Error> {
3048 let hash = get_required_parameter(cx, object, c"hash", ())?;
3049
3050 Ok(EcdsaParams {
3051 name: algorithm_name,
3052 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3053 })
3054 }
3055}
3056
3057#[derive(Clone, MallocSizeOf)]
3059struct EcKeyGenParams {
3060 name: CryptoAlgorithm,
3062
3063 named_curve: String,
3065}
3066
3067impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyGenParams {
3068 type Error = Error;
3069
3070 fn try_from_with_cx_and_name(
3071 cx: &mut JSContext,
3072 algorithm_name: CryptoAlgorithm,
3073 object: HandleObject<'a>,
3074 ) -> Result<Self, Self::Error> {
3075 Ok(EcKeyGenParams {
3076 name: algorithm_name,
3077 named_curve: String::from(get_required_parameter::<DOMString>(
3078 cx,
3079 object,
3080 c"namedCurve",
3081 StringificationBehavior::Default,
3082 )?),
3083 })
3084 }
3085}
3086
3087#[derive(Clone, MallocSizeOf)]
3089pub(crate) struct EcKeyAlgorithm {
3090 name: CryptoAlgorithm,
3092
3093 named_curve: String,
3095}
3096
3097impl ToJSValConvertible for EcKeyAlgorithm {
3098 #[expect(unsafe_code)]
3099 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
3100 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3101
3102 rooted!(&in(cx) let mut name_js = UndefinedValue());
3103 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3104 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3105 .expect("Failed to set name property of EcKeyAlgorithm");
3106
3107 rooted!(&in(cx) let mut named_curve_js = UndefinedValue());
3108 self.named_curve.to_jsval(cx, named_curve_js.handle_mut());
3109 set_dictionary_property(cx, object.handle(), c"namedCurve", named_curve_js.handle())
3110 .expect("Failed to set namedCurve property of EcKeyAlgorithm");
3111
3112 rval.set(ObjectOrNullValue(object.get()));
3113 }
3114}
3115
3116impl TryFrom<SerializableEcKeyAlgorithm> for EcKeyAlgorithm {
3117 type Error = ();
3118
3119 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3120 Ok(EcKeyAlgorithm {
3121 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3122 named_curve: value.named_curve,
3123 })
3124 }
3125}
3126
3127impl From<&EcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3128 fn from(value: &EcKeyAlgorithm) -> Self {
3129 SerializableEcKeyAlgorithm {
3130 name: value.name.as_str().into(),
3131 named_curve: value.named_curve.clone(),
3132 }
3133 }
3134}
3135
3136#[derive(Clone, MallocSizeOf)]
3138struct EcKeyImportParams {
3139 name: CryptoAlgorithm,
3141
3142 named_curve: String,
3144}
3145
3146impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyImportParams {
3147 type Error = Error;
3148
3149 fn try_from_with_cx_and_name(
3150 cx: &mut JSContext,
3151 algorithm_name: CryptoAlgorithm,
3152 object: HandleObject<'a>,
3153 ) -> Result<Self, Self::Error> {
3154 Ok(EcKeyImportParams {
3155 name: algorithm_name,
3156 named_curve: String::from(get_required_parameter::<DOMString>(
3157 cx,
3158 object,
3159 c"namedCurve",
3160 StringificationBehavior::Default,
3161 )?),
3162 })
3163 }
3164}
3165
3166#[derive(Clone, MallocSizeOf)]
3168struct EcdhKeyDeriveParams<D: DomTypes> {
3169 name: CryptoAlgorithm,
3171
3172 public: Trusted<CryptoKey<D>>,
3174}
3175
3176impl<'a, D: DomTypes> TryFromWithCxAndName<HandleObject<'a>> for EcdhKeyDeriveParams<D> {
3177 type Error = Error;
3178
3179 fn try_from_with_cx_and_name(
3180 cx: &mut JSContext,
3181 algorithm_name: CryptoAlgorithm,
3182 object: HandleObject<'a>,
3183 ) -> Result<Self, Self::Error> {
3184 let public = get_required_parameter::<DomRoot<CryptoKey<D>>>(cx, object, c"public", ())?;
3185
3186 Ok(EcdhKeyDeriveParams {
3187 name: algorithm_name,
3188 public: Trusted::new(&public),
3189 })
3190 }
3191}
3192
3193#[derive(Clone, MallocSizeOf)]
3195struct AesCtrParams {
3196 name: CryptoAlgorithm,
3198
3199 counter: Vec<u8>,
3201
3202 length: u8,
3204}
3205
3206impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCtrParams {
3207 type Error = Error;
3208
3209 fn try_from_with_cx_and_name(
3210 cx: &mut JSContext,
3211 algorithm_name: CryptoAlgorithm,
3212 object: HandleObject<'a>,
3213 ) -> Result<Self, Self::Error> {
3214 Ok(AesCtrParams {
3215 name: algorithm_name,
3216 counter: get_required_buffer_source(cx, object, c"counter")?,
3217 length: get_required_parameter(
3218 cx,
3219 object,
3220 c"length",
3221 ConversionBehavior::EnforceRange,
3222 )?,
3223 })
3224 }
3225}
3226
3227#[derive(Clone, MallocSizeOf)]
3229pub(crate) struct AesKeyAlgorithm {
3230 name: CryptoAlgorithm,
3232
3233 length: u16,
3235}
3236
3237impl ToJSValConvertible for AesKeyAlgorithm {
3238 #[expect(unsafe_code)]
3239 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
3240 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3241
3242 rooted!(&in(cx) let mut name_js = UndefinedValue());
3243 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3244 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3245 .expect("Failed to set name property of AesKeyAlgorithm");
3246
3247 rooted!(&in(cx) let mut length_js = UndefinedValue());
3248 self.length.to_jsval(cx, length_js.handle_mut());
3249 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3250 .expect("Failed to set length property of AesKeyAlgorithm");
3251
3252 rval.set(ObjectOrNullValue(object.get()));
3253 }
3254}
3255
3256impl TryFrom<SerializableAesKeyAlgorithm> for AesKeyAlgorithm {
3257 type Error = ();
3258
3259 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3260 Ok(AesKeyAlgorithm {
3261 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3262 length: value.length,
3263 })
3264 }
3265}
3266
3267impl From<&AesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3268 fn from(value: &AesKeyAlgorithm) -> Self {
3269 SerializableAesKeyAlgorithm {
3270 name: value.name.as_str().into(),
3271 length: value.length,
3272 }
3273 }
3274}
3275
3276#[derive(Clone, MallocSizeOf)]
3278struct AesKeyGenParams {
3279 name: CryptoAlgorithm,
3281
3282 length: u16,
3284}
3285
3286impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesKeyGenParams {
3287 type Error = Error;
3288
3289 fn try_from_with_cx_and_name(
3290 cx: &mut JSContext,
3291 algorithm_name: CryptoAlgorithm,
3292 object: HandleObject<'a>,
3293 ) -> Result<Self, Self::Error> {
3294 Ok(AesKeyGenParams {
3295 name: algorithm_name,
3296 length: get_required_parameter(
3297 cx,
3298 object,
3299 c"length",
3300 ConversionBehavior::EnforceRange,
3301 )?,
3302 })
3303 }
3304}
3305
3306#[derive(Clone, MallocSizeOf)]
3308struct AesDerivedKeyParams {
3309 name: CryptoAlgorithm,
3311
3312 length: u16,
3314}
3315
3316impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesDerivedKeyParams {
3317 type Error = Error;
3318
3319 fn try_from_with_cx_and_name(
3320 cx: &mut JSContext,
3321 algorithm_name: CryptoAlgorithm,
3322 object: HandleObject<'a>,
3323 ) -> Result<Self, Self::Error> {
3324 Ok(AesDerivedKeyParams {
3325 name: algorithm_name,
3326 length: get_required_parameter(
3327 cx,
3328 object,
3329 c"length",
3330 ConversionBehavior::EnforceRange,
3331 )?,
3332 })
3333 }
3334}
3335
3336#[derive(Clone, MallocSizeOf)]
3338struct AesCbcParams {
3339 name: CryptoAlgorithm,
3341
3342 iv: Vec<u8>,
3344}
3345
3346impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCbcParams {
3347 type Error = Error;
3348
3349 fn try_from_with_cx_and_name(
3350 cx: &mut JSContext,
3351 algorithm_name: CryptoAlgorithm,
3352 object: HandleObject<'a>,
3353 ) -> Result<Self, Self::Error> {
3354 Ok(AesCbcParams {
3355 name: algorithm_name,
3356 iv: get_required_buffer_source(cx, object, c"iv")?,
3357 })
3358 }
3359}
3360
3361#[derive(Clone, MallocSizeOf)]
3363struct AesGcmParams {
3364 name: CryptoAlgorithm,
3366
3367 iv: Vec<u8>,
3369
3370 additional_data: Option<Vec<u8>>,
3372
3373 tag_length: Option<u8>,
3375}
3376
3377impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesGcmParams {
3378 type Error = Error;
3379
3380 fn try_from_with_cx_and_name(
3381 cx: &mut JSContext,
3382 algorithm_name: CryptoAlgorithm,
3383 object: HandleObject<'a>,
3384 ) -> Result<Self, Self::Error> {
3385 Ok(AesGcmParams {
3386 name: algorithm_name,
3387 iv: get_required_buffer_source(cx, object, c"iv")?,
3388 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3389 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3390 })
3391 }
3392}
3393
3394#[derive(Clone, MallocSizeOf)]
3396struct HmacImportParams {
3397 name: CryptoAlgorithm,
3399
3400 hash: DigestAlgorithm,
3402
3403 length: Option<u32>,
3405}
3406
3407impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacImportParams {
3408 type Error = Error;
3409
3410 fn try_from_with_cx_and_name(
3411 cx: &mut JSContext,
3412 algorithm_name: CryptoAlgorithm,
3413 object: HandleObject<'a>,
3414 ) -> Result<Self, Self::Error> {
3415 let hash = get_required_parameter(cx, object, c"hash", ())?;
3416
3417 Ok(HmacImportParams {
3418 name: algorithm_name,
3419 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3420 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3421 })
3422 }
3423}
3424
3425#[derive(Clone, MallocSizeOf)]
3427pub(crate) struct HmacKeyAlgorithm {
3428 name: CryptoAlgorithm,
3430
3431 hash: DigestAlgorithm,
3433
3434 length: u32,
3436}
3437
3438impl ToJSValConvertible for HmacKeyAlgorithm {
3439 #[expect(unsafe_code)]
3440 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
3441 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3442
3443 rooted!(&in(cx) let mut name_js = UndefinedValue());
3444 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3445 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3446 .expect("Failed to set name property of HmacKeyAlgorithm");
3447
3448 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3449 let hash = KeyAlgorithm {
3450 name: self.hash.name(),
3451 };
3452 hash.to_jsval(cx, hash_js.handle_mut());
3453 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3454 .expect("Failed to set hash property of HmacKeyAlgorithm");
3455
3456 rooted!(&in(cx) let mut length_js = UndefinedValue());
3457 self.length.to_jsval(cx, length_js.handle_mut());
3458 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3459 .expect("Failed to set length property of HmacKeyAlgorithm");
3460
3461 rval.set(ObjectOrNullValue(object.get()));
3462 }
3463}
3464
3465impl TryFrom<SerializableHmacKeyAlgorithm> for HmacKeyAlgorithm {
3466 type Error = ();
3467
3468 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3469 Ok(HmacKeyAlgorithm {
3470 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3471 hash: value.hash.try_into()?,
3472 length: value.length,
3473 })
3474 }
3475}
3476
3477impl From<&HmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3478 fn from(value: &HmacKeyAlgorithm) -> Self {
3479 SerializableHmacKeyAlgorithm {
3480 name: value.name.as_str().into(),
3481 hash: (&value.hash).into(),
3482 length: value.length,
3483 }
3484 }
3485}
3486
3487#[derive(Clone, MallocSizeOf)]
3489struct HmacKeyGenParams {
3490 name: CryptoAlgorithm,
3492
3493 hash: DigestAlgorithm,
3495
3496 length: Option<u32>,
3498}
3499
3500impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacKeyGenParams {
3501 type Error = Error;
3502
3503 fn try_from_with_cx_and_name(
3504 cx: &mut JSContext,
3505 algorithm_name: CryptoAlgorithm,
3506 object: HandleObject<'a>,
3507 ) -> Result<Self, Self::Error> {
3508 let hash = get_required_parameter(cx, object, c"hash", ())?;
3509
3510 Ok(HmacKeyGenParams {
3511 name: algorithm_name,
3512 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3513 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3514 })
3515 }
3516}
3517
3518#[derive(Clone, MallocSizeOf)]
3520pub(crate) struct HkdfParams {
3521 name: CryptoAlgorithm,
3523
3524 hash: DigestAlgorithm,
3526
3527 salt: Vec<u8>,
3529
3530 info: Vec<u8>,
3532}
3533
3534impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HkdfParams {
3535 type Error = Error;
3536
3537 fn try_from_with_cx_and_name(
3538 cx: &mut JSContext,
3539 algorithm_name: CryptoAlgorithm,
3540 object: HandleObject<'a>,
3541 ) -> Result<Self, Self::Error> {
3542 let hash = get_required_parameter(cx, object, c"hash", ())?;
3543
3544 Ok(HkdfParams {
3545 name: algorithm_name,
3546 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3547 salt: get_required_buffer_source(cx, object, c"salt")?,
3548 info: get_required_buffer_source(cx, object, c"info")?,
3549 })
3550 }
3551}
3552
3553#[derive(Clone, MallocSizeOf)]
3555pub(crate) struct Pbkdf2Params {
3556 name: CryptoAlgorithm,
3558
3559 salt: Vec<u8>,
3561
3562 iterations: u32,
3564
3565 hash: DigestAlgorithm,
3567}
3568
3569impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Pbkdf2Params {
3570 type Error = Error;
3571
3572 fn try_from_with_cx_and_name(
3573 cx: &mut JSContext,
3574 algorithm_name: CryptoAlgorithm,
3575 object: HandleObject<'a>,
3576 ) -> Result<Self, Self::Error> {
3577 let hash = get_required_parameter(cx, object, c"hash", ())?;
3578
3579 Ok(Pbkdf2Params {
3580 name: algorithm_name,
3581 salt: get_required_buffer_source(cx, object, c"salt")?,
3582 iterations: get_required_parameter(
3583 cx,
3584 object,
3585 c"iterations",
3586 ConversionBehavior::EnforceRange,
3587 )?,
3588 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3589 })
3590 }
3591}
3592
3593#[derive(Clone, MallocSizeOf)]
3595struct ContextParams {
3596 name: CryptoAlgorithm,
3598
3599 context: Option<Vec<u8>>,
3601}
3602
3603impl<'a> TryFromWithCxAndName<HandleObject<'a>> for ContextParams {
3604 type Error = Error;
3605
3606 fn try_from_with_cx_and_name(
3607 cx: &mut JSContext,
3608 algorithm_name: CryptoAlgorithm,
3609 object: HandleObject<'a>,
3610 ) -> Result<Self, Self::Error> {
3611 Ok(ContextParams {
3612 name: algorithm_name,
3613 context: get_optional_buffer_source(cx, object, c"context")?,
3614 })
3615 }
3616}
3617
3618#[derive(Clone, MallocSizeOf)]
3620struct AeadParams {
3621 name: CryptoAlgorithm,
3623
3624 iv: Vec<u8>,
3626
3627 additional_data: Option<Vec<u8>>,
3629
3630 tag_length: Option<u8>,
3632}
3633
3634impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AeadParams {
3635 type Error = Error;
3636
3637 fn try_from_with_cx_and_name(
3638 cx: &mut JSContext,
3639 algorithm_name: CryptoAlgorithm,
3640 object: HandleObject<'a>,
3641 ) -> Result<Self, Self::Error> {
3642 Ok(AeadParams {
3643 name: algorithm_name,
3644 iv: get_required_buffer_source(cx, object, c"iv")?,
3645 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3646 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3647 })
3648 }
3649}
3650
3651#[derive(Clone, MallocSizeOf)]
3653struct CShakeParams {
3654 name: CryptoAlgorithm,
3656
3657 output_length: u32,
3659
3660 function_name: Option<Vec<u8>>,
3662
3663 customization: Option<Vec<u8>>,
3665}
3666
3667impl<'a> TryFromWithCxAndName<HandleObject<'a>> for CShakeParams {
3668 type Error = Error;
3669
3670 fn try_from_with_cx_and_name(
3671 cx: &mut JSContext,
3672 algorithm_name: CryptoAlgorithm,
3673 object: HandleObject<'a>,
3674 ) -> Result<Self, Self::Error> {
3675 Ok(CShakeParams {
3676 name: algorithm_name,
3677 output_length: get_required_parameter(
3678 cx,
3679 object,
3680 c"outputLength",
3681 ConversionBehavior::EnforceRange,
3682 )?,
3683 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3684 customization: get_optional_buffer_source(cx, object, c"customization")?,
3685 })
3686 }
3687}
3688
3689impl TryFrom<SerializableCShakeParams> for CShakeParams {
3690 type Error = ();
3691
3692 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3693 Ok(CShakeParams {
3694 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3695 output_length: value.output_length,
3696 function_name: value.function_name,
3697 customization: value.customization,
3698 })
3699 }
3700}
3701
3702impl From<&CShakeParams> for SerializableCShakeParams {
3703 fn from(value: &CShakeParams) -> Self {
3704 SerializableCShakeParams {
3705 name: value.name.as_str().into(),
3706 output_length: value.output_length,
3707 function_name: value.function_name.clone(),
3708 customization: value.customization.clone(),
3709 }
3710 }
3711}
3712
3713#[derive(Clone, MallocSizeOf)]
3715struct TurboShakeParams {
3716 name: CryptoAlgorithm,
3718
3719 output_length: u32,
3721
3722 domain_separation: Option<u8>,
3724}
3725
3726impl<'a> TryFromWithCxAndName<HandleObject<'a>> for TurboShakeParams {
3727 type Error = Error;
3728
3729 fn try_from_with_cx_and_name(
3730 cx: &mut JSContext,
3731 algorithm_name: CryptoAlgorithm,
3732 object: HandleObject<'a>,
3733 ) -> Result<Self, Self::Error> {
3734 Ok(TurboShakeParams {
3735 name: algorithm_name,
3736 output_length: get_required_parameter(
3737 cx,
3738 object,
3739 c"outputLength",
3740 ConversionBehavior::EnforceRange,
3741 )?,
3742 domain_separation: get_property(
3743 cx,
3744 object,
3745 c"domainSeparation",
3746 ConversionBehavior::EnforceRange,
3747 )?,
3748 })
3749 }
3750}
3751
3752impl TryFrom<SerializableTurboShakeParams> for TurboShakeParams {
3753 type Error = ();
3754
3755 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3756 Ok(TurboShakeParams {
3757 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3758 output_length: value.output_length,
3759 domain_separation: value.domain_separation,
3760 })
3761 }
3762}
3763
3764impl From<&TurboShakeParams> for SerializableTurboShakeParams {
3765 fn from(value: &TurboShakeParams) -> Self {
3766 SerializableTurboShakeParams {
3767 name: value.name.as_str().into(),
3768 output_length: value.output_length,
3769 domain_separation: value.domain_separation,
3770 }
3771 }
3772}
3773
3774#[derive(Clone, MallocSizeOf)]
3776struct KangarooTwelveParams {
3777 name: CryptoAlgorithm,
3779
3780 output_length: u32,
3782
3783 customization: Option<Vec<u8>>,
3785}
3786
3787impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KangarooTwelveParams {
3788 type Error = Error;
3789
3790 fn try_from_with_cx_and_name(
3791 cx: &mut JSContext,
3792 algorithm_name: CryptoAlgorithm,
3793 object: HandleObject<'a>,
3794 ) -> Result<Self, Self::Error> {
3795 Ok(KangarooTwelveParams {
3796 name: algorithm_name,
3797 output_length: get_required_parameter(
3798 cx,
3799 object,
3800 c"outputLength",
3801 ConversionBehavior::EnforceRange,
3802 )?,
3803 customization: get_optional_buffer_source(cx, object, c"customization")?,
3804 })
3805 }
3806}
3807
3808impl TryFrom<SerializableKangarooTwelveParams> for KangarooTwelveParams {
3809 type Error = ();
3810
3811 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
3812 Ok(KangarooTwelveParams {
3813 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3814 output_length: value.output_length,
3815 customization: value.customization,
3816 })
3817 }
3818}
3819
3820impl From<&KangarooTwelveParams> for SerializableKangarooTwelveParams {
3821 fn from(value: &KangarooTwelveParams) -> Self {
3822 SerializableKangarooTwelveParams {
3823 name: value.name.as_str().into(),
3824 output_length: value.output_length,
3825 customization: value.customization.clone(),
3826 }
3827 }
3828}
3829
3830#[derive(Clone, MallocSizeOf)]
3832struct KmacKeyGenParams {
3833 name: CryptoAlgorithm,
3835
3836 length: Option<u32>,
3838}
3839
3840impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacKeyGenParams {
3841 type Error = Error;
3842
3843 fn try_from_with_cx_and_name(
3844 cx: &mut JSContext,
3845 algorithm_name: CryptoAlgorithm,
3846 object: HandleObject,
3847 ) -> Result<Self, Self::Error> {
3848 Ok(KmacKeyGenParams {
3849 name: algorithm_name,
3850 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3851 })
3852 }
3853}
3854
3855#[derive(Clone, MallocSizeOf)]
3857struct KmacImportParams {
3858 name: CryptoAlgorithm,
3860
3861 length: Option<u32>,
3863}
3864
3865impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacImportParams {
3866 type Error = Error;
3867
3868 fn try_from_with_cx_and_name(
3869 cx: &mut JSContext,
3870 algorithm_name: CryptoAlgorithm,
3871 object: HandleObject,
3872 ) -> Result<Self, Self::Error> {
3873 Ok(KmacImportParams {
3874 name: algorithm_name,
3875 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3876 })
3877 }
3878}
3879
3880#[derive(Clone, MallocSizeOf)]
3882pub(crate) struct KmacKeyAlgorithm {
3883 name: CryptoAlgorithm,
3885
3886 length: u32,
3888}
3889
3890impl ToJSValConvertible for KmacKeyAlgorithm {
3891 #[expect(unsafe_code)]
3892 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
3893 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3894
3895 rooted!(&in(cx) let mut name_js = UndefinedValue());
3896 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3897 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3898 .expect("Failed to set name property of KmacKeyAlgorithm");
3899
3900 rooted!(&in(cx) let mut length_js = UndefinedValue());
3901 self.length.to_jsval(cx, length_js.handle_mut());
3902 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3903 .expect("Failed to set length property of KmacKeyAlgorithm");
3904
3905 rval.set(ObjectOrNullValue(object.get()));
3906 }
3907}
3908
3909impl TryFrom<SerializableKmacKeyAlgorithm> for KmacKeyAlgorithm {
3910 type Error = ();
3911
3912 fn try_from(value: SerializableKmacKeyAlgorithm) -> Result<Self, Self::Error> {
3913 Ok(KmacKeyAlgorithm {
3914 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3915 length: value.length,
3916 })
3917 }
3918}
3919
3920impl From<&KmacKeyAlgorithm> for SerializableKmacKeyAlgorithm {
3921 fn from(value: &KmacKeyAlgorithm) -> Self {
3922 SerializableKmacKeyAlgorithm {
3923 name: value.name.as_str().into(),
3924 length: value.length,
3925 }
3926 }
3927}
3928
3929struct KmacParams {
3931 name: CryptoAlgorithm,
3933
3934 output_length: u32,
3936
3937 customization: Option<Vec<u8>>,
3939}
3940
3941impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacParams {
3942 type Error = Error;
3943
3944 fn try_from_with_cx_and_name(
3945 cx: &mut JSContext,
3946 algorithm_name: CryptoAlgorithm,
3947 object: HandleObject<'a>,
3948 ) -> Result<Self, Self::Error> {
3949 Ok(KmacParams {
3950 name: algorithm_name,
3951 output_length: get_required_parameter(
3952 cx,
3953 object,
3954 c"outputLength",
3955 ConversionBehavior::EnforceRange,
3956 )?,
3957 customization: get_optional_buffer_source(cx, object, c"customization")?,
3958 })
3959 }
3960}
3961
3962#[derive(Clone, MallocSizeOf)]
3964struct Argon2Params {
3965 name: CryptoAlgorithm,
3967
3968 nonce: Vec<u8>,
3970
3971 parallelism: u32,
3973
3974 memory: u32,
3976
3977 passes: u32,
3979
3980 version: Option<u8>,
3982
3983 secret_value: Option<Vec<u8>>,
3985
3986 associated_data: Option<Vec<u8>>,
3988}
3989
3990impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Argon2Params {
3991 type Error = Error;
3992
3993 fn try_from_with_cx_and_name(
3994 cx: &mut JSContext,
3995 algorithm_name: CryptoAlgorithm,
3996 object: HandleObject<'a>,
3997 ) -> Result<Self, Self::Error> {
3998 Ok(Argon2Params {
3999 name: algorithm_name,
4000 nonce: get_required_buffer_source(cx, object, c"nonce")?,
4001 parallelism: get_required_parameter(
4002 cx,
4003 object,
4004 c"parallelism",
4005 ConversionBehavior::EnforceRange,
4006 )?,
4007 memory: get_required_parameter(
4008 cx,
4009 object,
4010 c"memory",
4011 ConversionBehavior::EnforceRange,
4012 )?,
4013 passes: get_required_parameter(
4014 cx,
4015 object,
4016 c"passes",
4017 ConversionBehavior::EnforceRange,
4018 )?,
4019 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
4020 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
4021 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
4022 })
4023 }
4024}
4025
4026struct EncapsulatedKey<D: DomTypes> {
4028 shared_key: Option<Trusted<CryptoKey<D>>>,
4030
4031 ciphertext: Option<Vec<u8>>,
4033}
4034
4035impl<D: DomTypes> ToJSValConvertible for EncapsulatedKey<D> {
4036 #[expect(unsafe_code)]
4037 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
4038 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4039
4040 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
4041 self.shared_key
4042 .as_ref()
4043 .map(|shared_key| shared_key.root())
4044 .to_jsval(cx, shared_key_js.handle_mut());
4045 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
4046 .expect("Failed to set sharedKey property of EncapsulatedKey");
4047
4048 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
4049 self.ciphertext
4050 .as_ref()
4051 .map(|ciphertext| {
4052 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
4053 create_buffer_source::<ArrayBufferU8>(
4054 cx,
4055 ciphertext,
4056 ciphertext_js_object.handle_mut(),
4057 )
4058 .expect("Failed to convert ciphertext to ArrayBufferU8")
4059 })
4060 .to_jsval(cx, ciphertext_js.handle_mut());
4061 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4062 .expect("Failed to set ciphertext property of EncapsulatedKey");
4063
4064 rval.set(ObjectOrNullValue(object.get()));
4065 }
4066}
4067
4068struct EncapsulatedBits {
4070 shared_key: Option<Zeroizing<Vec<u8>>>,
4072
4073 ciphertext: Option<Vec<u8>>,
4075}
4076
4077impl ToJSValConvertible for EncapsulatedBits {
4078 #[expect(unsafe_code)]
4079 fn to_jsval(&self, cx: &mut JSContext, mut rval: MutableHandleValue) {
4080 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4081
4082 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
4083 self.shared_key
4084 .as_ref()
4085 .map(|shared_key| {
4086 rooted!(&in(cx) let mut shared_key_js_object = ptr::null_mut::<JSObject>());
4087 create_buffer_source::<ArrayBufferU8>(
4088 cx,
4089 shared_key,
4090 shared_key_js_object.handle_mut(),
4091 )
4092 .expect("Failed to convert shared_key to ArrayBufferU8")
4093 })
4094 .to_jsval(cx, shared_key_js.handle_mut());
4095 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
4096 .expect("Failed to set sharedKey property of EncapsulatedBits");
4097
4098 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
4099 self.ciphertext
4100 .as_ref()
4101 .map(|ciphertext| {
4102 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
4103 create_buffer_source::<ArrayBufferU8>(
4104 cx,
4105 ciphertext,
4106 ciphertext_js_object.handle_mut(),
4107 )
4108 .expect("Failed to convert ciphertext to ArrayBufferU8")
4109 })
4110 .to_jsval(cx, ciphertext_js.handle_mut());
4111 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4112 .expect("Failed to set ciphertext property of EncapsulatedBits");
4113
4114 rval.set(ObjectOrNullValue(object.get()));
4115 }
4116}
4117
4118#[derive(Clone, MallocSizeOf)]
4120struct SubtleEd448Params {
4121 name: CryptoAlgorithm,
4123
4124 context: Option<Vec<u8>>,
4126}
4127
4128impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEd448Params {
4129 type Error = Error;
4130
4131 fn try_from_with_cx_and_name(
4132 cx: &mut JSContext,
4133 algorithm_name: CryptoAlgorithm,
4134 object: HandleObject<'a>,
4135 ) -> Result<Self, Self::Error> {
4136 Ok(SubtleEd448Params {
4137 name: algorithm_name,
4138 context: get_optional_buffer_source(cx, object, c"context")?,
4139 })
4140 }
4141}
4142
4143fn get_required_parameter<T: FromJSValConvertible>(
4145 cx: &mut JSContext,
4146 object: HandleObject,
4147 parameter: &std::ffi::CStr,
4148 option: T::Config,
4149) -> Fallible<T> {
4150 get_property::<T>(cx, object, parameter, option)?
4151 .ok_or(Error::Type(c"Missing required parameter".into()))
4152}
4153
4154fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4156 cx: &mut JSContext,
4157 object: HandleObject,
4158 parameter: &std::ffi::CStr,
4159 option: T::Config,
4160) -> Fallible<RootedTraceableBox<T>> {
4161 get_property::<T>(cx, object, parameter, option)?
4162 .map(RootedTraceableBox::new)
4163 .ok_or(Error::Type(c"Missing required parameter".into()))
4164}
4165
4166fn get_optional_buffer_source(
4170 cx: &mut JSContext,
4171 object: HandleObject,
4172 parameter: &std::ffi::CStr,
4173) -> Fallible<Option<Vec<u8>>> {
4174 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4175 Ok(buffer_source
4176 .as_ref()
4177 .map(|buffer| get_buffer_source_copy(buffer.into())))
4178}
4179
4180fn get_required_buffer_source(
4184 cx: &mut JSContext,
4185 object: HandleObject,
4186 parameter: &std::ffi::CStr,
4187) -> Fallible<Vec<u8>> {
4188 get_optional_buffer_source(cx, object, parameter)?
4189 .ok_or(Error::Type(c"Missing required parameter".into()))
4190}
4191
4192enum ExportedKey {
4196 Bytes(Zeroizing<Vec<u8>>),
4197 Jwk(Box<JsonWebKey>),
4198}
4199
4200impl ExportedKey {
4201 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4202 ExportedKey::Bytes(Zeroizing::new(bytes))
4203 }
4204
4205 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4206 ExportedKey::Jwk(Box::new(jwk))
4207 }
4208}
4209
4210#[derive(Clone, MallocSizeOf)]
4214#[expect(clippy::enum_variant_names)]
4215pub(crate) enum KeyAlgorithmAndDerivatives {
4216 KeyAlgorithm(KeyAlgorithm),
4217 RsaHashedKeyAlgorithm(RsaHashedKeyAlgorithm),
4218 EcKeyAlgorithm(EcKeyAlgorithm),
4219 AesKeyAlgorithm(AesKeyAlgorithm),
4220 HmacKeyAlgorithm(HmacKeyAlgorithm),
4221 KmacKeyAlgorithm(KmacKeyAlgorithm),
4222}
4223
4224impl KeyAlgorithmAndDerivatives {
4225 fn name(&self) -> CryptoAlgorithm {
4226 match self {
4227 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4228 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4229 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4230 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4231 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4232 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => algorithm.name,
4233 }
4234 }
4235}
4236
4237impl ToJSValConvertible for KeyAlgorithmAndDerivatives {
4238 fn to_jsval(&self, cx: &mut JSContext, rval: MutableHandleValue) {
4239 match self {
4240 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4241 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4242 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4243 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4244 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4245 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4246 }
4247 }
4248}
4249
4250impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4251 type Error = ();
4252
4253 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4254 match value {
4255 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4256 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4257 ),
4258 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4259 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4260 ),
4261 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4262 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4263 ),
4264 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4265 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4266 ),
4267 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4268 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4269 ),
4270 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => Ok(
4271 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.try_into()?),
4272 ),
4273 }
4274 }
4275}
4276
4277impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4278 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4279 match value {
4280 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4281 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4282 },
4283 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4284 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4285 },
4286 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4287 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4288 },
4289 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4290 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4291 },
4292 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4293 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4294 },
4295 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => {
4296 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.into())
4297 },
4298 }
4299 }
4300}
4301
4302#[derive(Clone, Copy)]
4303enum JwkStringField {
4304 X,
4305 Y,
4306 D,
4307 N,
4308 E,
4309 P,
4310 Q,
4311 DP,
4312 DQ,
4313 QI,
4314 K,
4315 Priv,
4316 Pub,
4317}
4318
4319impl Display for JwkStringField {
4320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4321 let field_name = match self {
4322 JwkStringField::X => "x",
4323 JwkStringField::Y => "y",
4324 JwkStringField::D => "d",
4325 JwkStringField::N => "n",
4326 JwkStringField::E => "e",
4327 JwkStringField::P => "q",
4328 JwkStringField::Q => "q",
4329 JwkStringField::DP => "dp",
4330 JwkStringField::DQ => "dq",
4331 JwkStringField::QI => "qi",
4332 JwkStringField::K => "k",
4333 JwkStringField::Priv => "priv",
4334 JwkStringField::Pub => "pub",
4335 };
4336 write!(f, "{}", field_name)
4337 }
4338}
4339
4340trait JsonWebKeyExt {
4341 fn parse(cx: &mut JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4342 fn stringify(&self, cx: &mut JSContext) -> Result<Zeroizing<DOMString>, Error>;
4343 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4344 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4345 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4346 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4347 fn decode_optional_string_field(
4348 &self,
4349 field: JwkStringField,
4350 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4351 fn decode_required_string_field(
4352 &self,
4353 field: JwkStringField,
4354 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4355 fn decode_primes_from_oth_field(
4356 &self,
4357 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4358 ) -> Result<(), Error>;
4359}
4360
4361impl JsonWebKeyExt for JsonWebKey {
4362 #[expect(unsafe_code)]
4364 fn parse(cx: &mut JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4365 let json = String::from_utf8_lossy(data);
4370
4371 let json: Vec<_> = json.encode_utf16().collect();
4373
4374 rooted!(&in(cx) let mut result = UndefinedValue());
4378 unsafe {
4379 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4380 return Err(Error::JSFailed);
4381 }
4382 }
4383
4384 let key = match JsonWebKey::new(cx, result.handle()) {
4386 Ok(ConversionResult::Success(key)) => key,
4387 Ok(ConversionResult::Failure(error)) => {
4388 return Err(Error::Type(error.into_owned()));
4389 },
4390 Err(()) => {
4391 return Err(Error::JSFailed);
4392 },
4393 };
4394
4395 if key.kty.is_none() {
4397 return Err(Error::Data(Some(
4398 "'kty' field of key is not defined".into(),
4399 )));
4400 }
4401
4402 Ok(key)
4404 }
4405
4406 fn stringify(&self, cx: &mut JSContext) -> Result<Zeroizing<DOMString>, Error> {
4412 rooted!(&in(cx) let mut data = UndefinedValue());
4413 self.to_jsval(cx, data.handle_mut());
4414 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4415 }
4416
4417 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4418 let mut usages = vec![];
4419 for op in self.key_ops.as_ref().ok_or(Error::Data(Some(
4420 "'key_ops' member is not present in the JSON Web Key".into(),
4421 )))? {
4422 usages.push(
4423 KeyUsage::from_str(&op.str())
4424 .map_err(|_| Error::Data(Some("Unknown key usage".into())))?,
4425 );
4426 }
4427 Ok(usages)
4428 }
4429
4430 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4434 if let Some(ref key_ops) = self.key_ops {
4436 if key_ops
4439 .iter()
4440 .collect::<std::collections::HashSet<_>>()
4441 .len() <
4442 key_ops.len()
4443 {
4444 return Err(Error::Data(Some(
4445 "Duplicate key operation values are present in array".into(),
4446 )));
4447 }
4448 if let Some(ref use_) = self.use_ &&
4451 key_ops.iter().any(|op| op != use_)
4452 {
4453 return Err(Error::Data(Some(
4454 "Key operations are not consistent with intended use for Json Web Key".into(),
4455 )));
4456 }
4457
4458 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4460 if !specified_usages
4461 .iter()
4462 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4463 {
4464 return Err(Error::Data(Some(
4465 "Key operations do not contain all of the specified usage values".into(),
4466 )));
4467 }
4468 }
4469
4470 Ok(())
4471 }
4472
4473 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4475 self.key_ops = Some(
4476 usages
4477 .iter()
4478 .map(|usage| DOMString::from(usage.as_str()))
4479 .collect(),
4480 );
4481 }
4482
4483 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4486 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4487 match field {
4488 JwkStringField::X => self.x = Some(encoded_data),
4489 JwkStringField::Y => self.y = Some(encoded_data),
4490 JwkStringField::D => self.d = Some(encoded_data),
4491 JwkStringField::N => self.n = Some(encoded_data),
4492 JwkStringField::E => self.e = Some(encoded_data),
4493 JwkStringField::P => self.p = Some(encoded_data),
4494 JwkStringField::Q => self.q = Some(encoded_data),
4495 JwkStringField::DP => self.dp = Some(encoded_data),
4496 JwkStringField::DQ => self.dq = Some(encoded_data),
4497 JwkStringField::QI => self.qi = Some(encoded_data),
4498 JwkStringField::K => self.k = Some(encoded_data),
4499 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4500 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4501 }
4502 }
4503
4504 fn decode_optional_string_field(
4507 &self,
4508 field: JwkStringField,
4509 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4510 let field_string = match field {
4511 JwkStringField::X => &self.x,
4512 JwkStringField::Y => &self.y,
4513 JwkStringField::D => &self.d,
4514 JwkStringField::N => &self.n,
4515 JwkStringField::E => &self.e,
4516 JwkStringField::P => &self.p,
4517 JwkStringField::Q => &self.q,
4518 JwkStringField::DP => &self.dp,
4519 JwkStringField::DQ => &self.dq,
4520 JwkStringField::QI => &self.qi,
4521 JwkStringField::K => &self.k,
4522 JwkStringField::Priv => &self.priv_,
4523 JwkStringField::Pub => &self.pub_,
4524 };
4525
4526 field_string
4527 .as_ref()
4528 .map(|field_string| {
4529 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4530 })
4531 .transpose()
4532 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4533 }
4534
4535 fn decode_required_string_field(
4538 &self,
4539 field: JwkStringField,
4540 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4541 self.decode_optional_string_field(field)?
4542 .ok_or(Error::Data(Some(format!(
4543 "The {} field is not present in jwk",
4544 field
4545 ))))
4546 }
4547
4548 fn decode_primes_from_oth_field(
4557 &self,
4558 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4559 ) -> Result<(), Error> {
4560 if self.oth.is_some() &&
4561 (self.p.is_none() ||
4562 self.q.is_none() ||
4563 self.dp.is_none() ||
4564 self.dq.is_none() ||
4565 self.qi.is_none())
4566 {
4567 return Err(Error::Data(Some(
4568 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4569 )));
4570 }
4571
4572 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4573 let r = Base64UrlUnpadded::decode_vec(
4574 &rsa_other_prime_info
4575 .r
4576 .as_ref()
4577 .ok_or(Error::Data(Some(
4578 "The r field is not present in one of the entry of oth field in jwk"
4579 .to_string(),
4580 )))?
4581 .str(),
4582 )
4583 .map_err(|_| {
4584 Error::Data(Some(
4585 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4586 ))
4587 })?;
4588 primes.push(Zeroizing::new(r));
4589
4590 let _d = Base64UrlUnpadded::decode_vec(
4591 &rsa_other_prime_info
4592 .d
4593 .as_ref()
4594 .ok_or(Error::Data(Some(
4595 "The d field is not present in one of the entry of oth field in jwk"
4596 .to_string(),
4597 )))?
4598 .str(),
4599 )
4600 .map_err(|_| {
4601 Error::Data(Some(
4602 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4603 ))
4604 })?;
4605
4606 let _t = Base64UrlUnpadded::decode_vec(
4607 &rsa_other_prime_info
4608 .t
4609 .as_ref()
4610 .ok_or(Error::Data(Some(
4611 "The t field is not present in one of the entry of oth field in jwk"
4612 .to_string(),
4613 )))?
4614 .str(),
4615 )
4616 .map_err(|_| {
4617 Error::Data(Some(
4618 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4619 ))
4620 })?;
4621 }
4622
4623 Ok(())
4624 }
4625}
4626
4627fn normalize_algorithm<Op: Operation>(
4629 cx: &mut JSContext,
4630 algorithm: &AlgorithmIdentifier,
4631) -> Result<Op::RegisteredAlgorithm, Error> {
4632 match algorithm {
4633 AlgorithmIdentifier::String(name) => {
4635 let algorithm = AlgorithmWithDOMString {
4642 name: name.to_owned(),
4643 };
4644 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4645 algorithm.to_jsval(cx, algorithm_value.handle_mut());
4646 let algorithm_object = RootedTraceableBox::new(Heap::default());
4647 algorithm_object.set(algorithm_value.to_object());
4648 normalize_algorithm::<Op>(cx, &AlgorithmIdentifier::Object(algorithm_object))
4649 },
4650 AlgorithmIdentifier::Object(object) => {
4652 let algorithm_name = get_required_parameter::<DOMString>(
4660 cx,
4661 object.handle(),
4662 c"name",
4663 StringificationBehavior::Default,
4664 )?;
4665
4666 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4707 let normalized_algorithm =
4708 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4709
4710 Ok(normalized_algorithm)
4712 },
4713 }
4714}
4715
4716trait Operation {
4775 type RegisteredAlgorithm: NormalizedAlgorithm;
4776}
4777
4778trait NormalizedAlgorithm: Sized {
4779 fn from_object(
4781 cx: &mut JSContext,
4782 algorithm_name: CryptoAlgorithm,
4783 object: HandleObject,
4784 ) -> Fallible<Self>;
4785
4786 fn name(&self) -> CryptoAlgorithm;
4788
4789 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
4794 debug_assert!(
4835 false,
4836 "determine_support_from_operation_steps() is not implemented \
4837 for this normalized algorithm."
4838 );
4839 false
4840 }
4841}
4842
4843struct EncryptOperation {}
4845
4846impl Operation for EncryptOperation {
4847 type RegisteredAlgorithm = EncryptAlgorithm;
4848}
4849
4850enum EncryptAlgorithm {
4853 RsaOaep(RsaOaepParams),
4854 AesCtr(AesCtrParams),
4855 AesCbc(AesCbcParams),
4856 AesGcm(AesGcmParams),
4857 AesOcb(AeadParams),
4858 ChaCha20Poly1305(AeadParams),
4859}
4860
4861impl NormalizedAlgorithm for EncryptAlgorithm {
4862 fn from_object(
4863 cx: &mut JSContext,
4864 algorithm_name: CryptoAlgorithm,
4865 object: HandleObject,
4866 ) -> Fallible<Self> {
4867 match algorithm_name {
4868 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4869 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4870 )),
4871 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4872 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4873 )),
4874 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4875 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4876 )),
4877 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4878 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4879 )),
4880 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4881 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4882 )),
4883 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4884 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4885 )),
4886 _ => Err(Error::NotSupported(Some(format!(
4887 "{} does not support \"encrypt\" operation",
4888 algorithm_name.as_str()
4889 )))),
4890 }
4891 }
4892
4893 fn name(&self) -> CryptoAlgorithm {
4894 match self {
4895 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4896 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4897 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4898 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4899 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4900 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4901 }
4902 }
4903
4904 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
4905 match self {
4906 EncryptAlgorithm::RsaOaep(_) => true,
4907 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
4908 normalized_algorithm.counter.len() == 16 &&
4909 normalized_algorithm.length != 0 &&
4910 normalized_algorithm.length <= 128
4911 },
4912 EncryptAlgorithm::AesCbc(normalized_algorithm) => normalized_algorithm.iv.len() == 16,
4913 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
4914 normalized_algorithm.iv.len() <= u64::MAX as usize &&
4915 normalized_algorithm
4916 .additional_data
4917 .as_ref()
4918 .is_none_or(|additional_data| additional_data.len() <= u64::MAX as usize) &&
4919 normalized_algorithm.tag_length.is_none_or(|length| {
4920 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
4921 })
4922 },
4923 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
4924 normalized_algorithm.iv.len() <= 15 &&
4925 normalized_algorithm
4926 .tag_length
4927 .is_none_or(|length| matches!(length, 64 | 96 | 128))
4928 },
4929 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
4930 normalized_algorithm.iv.len() == 12 &&
4931 normalized_algorithm
4932 .tag_length
4933 .is_none_or(|length| length == 128)
4934 },
4935 }
4936 }
4937}
4938
4939impl EncryptAlgorithm {
4940 fn encrypt<D: Equivalence>(
4941 &self,
4942 key: &CryptoKey<D>,
4943 plaintext: &[u8],
4944 ) -> Result<Vec<u8>, Error> {
4945 match self {
4946 EncryptAlgorithm::RsaOaep(algorithm) => {
4947 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4948 },
4949 EncryptAlgorithm::AesCtr(algorithm) => {
4950 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4951 },
4952 EncryptAlgorithm::AesCbc(algorithm) => {
4953 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4954 },
4955 EncryptAlgorithm::AesGcm(algorithm) => {
4956 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4957 },
4958 EncryptAlgorithm::AesOcb(algorithm) => {
4959 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4960 },
4961 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4962 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4963 },
4964 }
4965 }
4966}
4967
4968struct DecryptOperation {}
4970
4971impl Operation for DecryptOperation {
4972 type RegisteredAlgorithm = DecryptAlgorithm;
4973}
4974
4975enum DecryptAlgorithm {
4978 RsaOaep(RsaOaepParams),
4979 AesCtr(AesCtrParams),
4980 AesCbc(AesCbcParams),
4981 AesGcm(AesGcmParams),
4982 AesOcb(AeadParams),
4983 ChaCha20Poly1305(AeadParams),
4984}
4985
4986impl NormalizedAlgorithm for DecryptAlgorithm {
4987 fn from_object(
4988 cx: &mut JSContext,
4989 algorithm_name: CryptoAlgorithm,
4990 object: HandleObject,
4991 ) -> Fallible<Self> {
4992 match algorithm_name {
4993 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4994 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4995 )),
4996 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4997 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4998 )),
4999 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
5000 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5001 )),
5002 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
5003 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5004 )),
5005 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
5006 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5007 )),
5008 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
5009 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5010 )),
5011 _ => Err(Error::NotSupported(Some(format!(
5012 "{} does not support \"decrypt\" operation",
5013 algorithm_name.as_str()
5014 )))),
5015 }
5016 }
5017
5018 fn name(&self) -> CryptoAlgorithm {
5019 match self {
5020 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
5021 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
5022 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
5023 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
5024 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
5025 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5026 }
5027 }
5028
5029 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5030 match self {
5031 DecryptAlgorithm::RsaOaep(_) => true,
5032 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
5033 normalized_algorithm.counter.len() == 16 &&
5034 normalized_algorithm.length != 0 &&
5035 normalized_algorithm.length <= 128
5036 },
5037 DecryptAlgorithm::AesCbc(normalized_algorithm) => normalized_algorithm.iv.len() == 16,
5038 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
5039 normalized_algorithm
5040 .tag_length
5041 .as_ref()
5042 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
5043 normalized_algorithm.iv.len() <= u64::MAX as usize &&
5044 normalized_algorithm
5045 .additional_data
5046 .as_ref()
5047 .is_none_or(|additional_data| additional_data.len() <= u64::MAX as usize)
5048 },
5049 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
5050 normalized_algorithm.iv.len() <= 15 &&
5051 normalized_algorithm
5052 .tag_length
5053 .as_ref()
5054 .is_none_or(|length| matches!(length, 64 | 96 | 128))
5055 },
5056 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
5057 normalized_algorithm.iv.len() == 12 &&
5058 normalized_algorithm
5059 .tag_length
5060 .as_ref()
5061 .is_none_or(|length| *length == 128)
5062 },
5063 }
5064 }
5065}
5066
5067impl DecryptAlgorithm {
5068 fn decrypt<D: Equivalence>(
5069 &self,
5070 key: &CryptoKey<D>,
5071 ciphertext: &[u8],
5072 ) -> Result<Vec<u8>, Error> {
5073 match self {
5074 DecryptAlgorithm::RsaOaep(algorithm) => {
5075 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
5076 },
5077 DecryptAlgorithm::AesCtr(algorithm) => {
5078 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
5079 },
5080 DecryptAlgorithm::AesCbc(algorithm) => {
5081 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
5082 },
5083 DecryptAlgorithm::AesGcm(algorithm) => {
5084 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
5085 },
5086 DecryptAlgorithm::AesOcb(algorithm) => {
5087 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
5088 },
5089 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
5090 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
5091 },
5092 }
5093 }
5094}
5095
5096struct SignOperation {}
5098
5099impl Operation for SignOperation {
5100 type RegisteredAlgorithm = SignAlgorithm;
5101}
5102
5103enum SignAlgorithm {
5106 RsassaPkcs1V1_5(Algorithm),
5107 RsaPss(RsaPssParams),
5108 Ecdsa(EcdsaParams),
5109 Ed25519(Algorithm),
5110 Ed448(SubtleEd448Params),
5111 Hmac(Algorithm),
5112 MlDsa(ContextParams),
5113 Kmac(KmacParams),
5114}
5115
5116impl NormalizedAlgorithm for SignAlgorithm {
5117 fn from_object(
5118 cx: &mut JSContext,
5119 algorithm_name: CryptoAlgorithm,
5120 object: HandleObject,
5121 ) -> Fallible<Self> {
5122 match algorithm_name {
5123 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
5124 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5125 )),
5126 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
5127 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5128 )),
5129 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
5130 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5131 )),
5132 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
5133 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5134 )),
5135 CryptoAlgorithm::Ed448 => Ok(SignAlgorithm::Ed448(
5136 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5137 )),
5138 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
5139 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5140 )),
5141 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5142 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5143 ),
5144 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(SignAlgorithm::Kmac(
5145 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5146 )),
5147 _ => Err(Error::NotSupported(Some(format!(
5148 "{} does not support \"sign\" operation",
5149 algorithm_name.as_str()
5150 )))),
5151 }
5152 }
5153
5154 fn name(&self) -> CryptoAlgorithm {
5155 match self {
5156 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5157 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
5158 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
5159 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
5160 SignAlgorithm::Ed448(algorithm) => algorithm.name,
5161 SignAlgorithm::Hmac(algorithm) => algorithm.name,
5162 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
5163 SignAlgorithm::Kmac(algorithm) => algorithm.name,
5164 }
5165 }
5166
5167 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5168 match self {
5169 SignAlgorithm::RsassaPkcs1V1_5(_) |
5170 SignAlgorithm::RsaPss(_) |
5171 SignAlgorithm::Ecdsa(_) |
5172 SignAlgorithm::Ed25519(_) => true,
5173 SignAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
5174 .context
5175 .as_ref()
5176 .is_none_or(|context| context.len() <= 255),
5177 SignAlgorithm::Hmac(_) => true,
5178 SignAlgorithm::MlDsa(normalized_algorithm) => normalized_algorithm
5179 .context
5180 .as_ref()
5181 .is_none_or(|context| context.len() <= 255),
5182 SignAlgorithm::Kmac(_) => true,
5183 }
5184 }
5185}
5186
5187impl SignAlgorithm {
5188 fn sign<D: Equivalence>(&self, key: &CryptoKey<D>, message: &[u8]) -> Result<Vec<u8>, Error> {
5189 match self {
5190 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5191 rsassa_pkcs1_v1_5_operation::sign(key, message)
5192 },
5193 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
5194 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
5195 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
5196 SignAlgorithm::Ed448(algorithm) => ed448_operation::sign(algorithm, key, message),
5197 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
5198 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
5199 SignAlgorithm::Kmac(algorithm) => kmac_operation::sign(algorithm, key, message),
5200 }
5201 }
5202}
5203
5204struct VerifyOperation {}
5206
5207impl Operation for VerifyOperation {
5208 type RegisteredAlgorithm = VerifyAlgorithm;
5209}
5210
5211enum VerifyAlgorithm {
5214 RsassaPkcs1V1_5(Algorithm),
5215 RsaPss(RsaPssParams),
5216 Ecdsa(EcdsaParams),
5217 Ed25519(Algorithm),
5218 Ed448(SubtleEd448Params),
5219 Hmac(Algorithm),
5220 MlDsa(ContextParams),
5221 Kmac(KmacParams),
5222}
5223
5224impl NormalizedAlgorithm for VerifyAlgorithm {
5225 fn from_object(
5226 cx: &mut JSContext,
5227 algorithm_name: CryptoAlgorithm,
5228 object: HandleObject,
5229 ) -> Fallible<Self> {
5230 match algorithm_name {
5231 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
5232 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5233 )),
5234 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
5235 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5236 )),
5237 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
5238 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5239 )),
5240 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
5241 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5242 )),
5243 CryptoAlgorithm::Ed448 => Ok(VerifyAlgorithm::Ed448(
5244 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5245 )),
5246 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
5247 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5248 )),
5249 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5250 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5251 ),
5252 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(VerifyAlgorithm::Kmac(
5253 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5254 )),
5255 _ => Err(Error::NotSupported(Some(format!(
5256 "{} does not support \"verify\" operation",
5257 algorithm_name.as_str()
5258 )))),
5259 }
5260 }
5261
5262 fn name(&self) -> CryptoAlgorithm {
5263 match self {
5264 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5265 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
5266 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5267 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
5268 VerifyAlgorithm::Ed448(algorithm) => algorithm.name,
5269 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
5270 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
5271 VerifyAlgorithm::Kmac(algorithm) => algorithm.name,
5272 }
5273 }
5274
5275 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5276 match self {
5277 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
5278 VerifyAlgorithm::RsaPss(_) |
5279 VerifyAlgorithm::Ecdsa(_) |
5280 VerifyAlgorithm::Ed25519(_) => true,
5281 VerifyAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
5282 .context
5283 .as_ref()
5284 .is_none_or(|context| context.len() <= 255),
5285 VerifyAlgorithm::Hmac(_) => true,
5286 VerifyAlgorithm::MlDsa(normalized_algorithm) => normalized_algorithm
5287 .context
5288 .as_ref()
5289 .is_none_or(|context| context.len() <= 255),
5290 VerifyAlgorithm::Kmac(_) => true,
5291 }
5292 }
5293}
5294
5295impl VerifyAlgorithm {
5296 fn verify<D: Equivalence>(
5297 &self,
5298 key: &CryptoKey<D>,
5299 message: &[u8],
5300 signature: &[u8],
5301 ) -> Result<bool, Error> {
5302 match self {
5303 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5304 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
5305 },
5306 VerifyAlgorithm::RsaPss(algorithm) => {
5307 rsa_pss_operation::verify(algorithm, key, message, signature)
5308 },
5309 VerifyAlgorithm::Ecdsa(algorithm) => {
5310 ecdsa_operation::verify(algorithm, key, message, signature)
5311 },
5312 VerifyAlgorithm::Ed25519(_algorithm) => {
5313 ed25519_operation::verify(key, message, signature)
5314 },
5315 VerifyAlgorithm::Ed448(algorithm) => {
5316 ed448_operation::verify(algorithm, key, message, signature)
5317 },
5318 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
5319 VerifyAlgorithm::MlDsa(algorithm) => {
5320 ml_dsa_operation::verify(algorithm, key, message, signature)
5321 },
5322 VerifyAlgorithm::Kmac(algorithm) => {
5323 kmac_operation::verify(algorithm, key, message, signature)
5324 },
5325 }
5326 }
5327}
5328
5329struct DigestOperation {}
5331
5332impl Operation for DigestOperation {
5333 type RegisteredAlgorithm = DigestAlgorithm;
5334}
5335
5336#[derive(Clone, MallocSizeOf)]
5339enum DigestAlgorithm {
5340 Sha(Algorithm),
5341 Sha3(Algorithm),
5342 CShake(CShakeParams),
5343 TurboShake(TurboShakeParams),
5344 KangarooTwelve(KangarooTwelveParams),
5345}
5346
5347impl NormalizedAlgorithm for DigestAlgorithm {
5348 fn from_object(
5349 cx: &mut JSContext,
5350 algorithm_name: CryptoAlgorithm,
5351 object: HandleObject,
5352 ) -> Fallible<Self> {
5353 match algorithm_name {
5354 CryptoAlgorithm::Sha1 |
5355 CryptoAlgorithm::Sha256 |
5356 CryptoAlgorithm::Sha384 |
5357 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
5358 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5359 )),
5360 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5361 Ok(DigestAlgorithm::Sha3(
5362 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5363 ))
5364 },
5365 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5366 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5367 )),
5368 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5369 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5370 ),
5371 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5372 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5373 )),
5374 _ => Err(Error::NotSupported(Some(format!(
5375 "{} does not support \"digest\" operation",
5376 algorithm_name.as_str()
5377 )))),
5378 }
5379 }
5380
5381 fn name(&self) -> CryptoAlgorithm {
5382 match self {
5383 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5384 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5385 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5386 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5387 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5388 }
5389 }
5390
5391 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5392 match self {
5393 DigestAlgorithm::Sha(_) |
5394 DigestAlgorithm::Sha3(_) |
5395 DigestAlgorithm::CShake(_) |
5396 DigestAlgorithm::TurboShake(_) => true,
5397 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
5398 normalized_algorithm.output_length != 0 &&
5399 normalized_algorithm.output_length.is_multiple_of(8)
5400 },
5401 }
5402 }
5403}
5404
5405impl DigestAlgorithm {
5406 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5407 match self {
5408 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5409 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5410 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5411 DigestAlgorithm::TurboShake(algorithm) => {
5412 turboshake_operation::digest(algorithm, message)
5413 },
5414 DigestAlgorithm::KangarooTwelve(algorithm) => {
5415 kangarootwelve_operation::digest(algorithm, message)
5416 },
5417 }
5418 }
5419}
5420
5421impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5422 type Error = ();
5423
5424 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5425 match value {
5426 SerializableDigestAlgorithm::Sha(algorithm) => {
5427 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5428 },
5429 SerializableDigestAlgorithm::Sha3(algorithm) => {
5430 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5431 },
5432 SerializableDigestAlgorithm::CShake(algorithm) => {
5433 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5434 },
5435 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5436 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5437 },
5438 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5439 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5440 },
5441 }
5442 }
5443}
5444
5445impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5446 fn from(value: &DigestAlgorithm) -> Self {
5447 match value {
5448 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5449 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5450 DigestAlgorithm::CShake(algorithm) => {
5451 SerializableDigestAlgorithm::CShake(algorithm.into())
5452 },
5453 DigestAlgorithm::TurboShake(algorithm) => {
5454 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5455 },
5456 DigestAlgorithm::KangarooTwelve(algorithm) => {
5457 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5458 },
5459 }
5460 }
5461}
5462
5463struct DeriveBitsOperation<D: Equivalence> {
5465 phantom: PhantomData<D>,
5466}
5467
5468impl<D: Equivalence> Operation for DeriveBitsOperation<D> {
5469 type RegisteredAlgorithm = DeriveBitsAlgorithm<D>;
5470}
5471
5472enum DeriveBitsAlgorithm<D: Equivalence> {
5475 Ecdh(EcdhKeyDeriveParams<D>),
5476 X25519(EcdhKeyDeriveParams<D>),
5477 X448(EcdhKeyDeriveParams<D>),
5478 Hkdf(HkdfParams),
5479 Pbkdf2(Pbkdf2Params),
5480 Argon2(Argon2Params),
5481}
5482
5483impl<D: Equivalence> NormalizedAlgorithm for DeriveBitsAlgorithm<D> {
5484 fn from_object(
5485 cx: &mut JSContext,
5486 algorithm_name: CryptoAlgorithm,
5487 object: HandleObject,
5488 ) -> Fallible<Self> {
5489 match algorithm_name {
5490 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5491 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5492 )),
5493 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5494 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5495 )),
5496 CryptoAlgorithm::X448 => Ok(DeriveBitsAlgorithm::X448(
5497 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5498 )),
5499 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5500 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5501 )),
5502 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5503 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5504 )),
5505 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5506 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5507 ),
5508 _ => Err(Error::NotSupported(Some(format!(
5509 "{} does not support \"deriveBits\" operation",
5510 algorithm_name.as_str()
5511 )))),
5512 }
5513 }
5514
5515 fn name(&self) -> CryptoAlgorithm {
5516 match self {
5517 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5518 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5519 DeriveBitsAlgorithm::X448(algorithm) => algorithm.name,
5520 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5521 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5522 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5523 }
5524 }
5525
5526 fn determine_support_from_operation_steps(&self, length: Option<u32>) -> bool {
5527 match self {
5528 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => {
5529 let public_key = normalized_algorithm.public.root();
5530 let Ok(maximum_length) = ecdh_operation::maximum_length(&public_key) else {
5531 return false;
5532 };
5533 public_key.Type() == KeyType::Public &&
5534 public_key.algorithm().name() == normalized_algorithm.name &&
5535 length.is_none_or(|length| length <= maximum_length)
5536 },
5537 DeriveBitsAlgorithm::X25519(normalized_algorithm) => {
5538 let public_key = normalized_algorithm.public.root();
5539 public_key.Type() == KeyType::Public &&
5540 public_key.algorithm().name() == normalized_algorithm.name &&
5541 length.is_none_or(|length| length <= 256)
5542 },
5543 DeriveBitsAlgorithm::X448(_) => {
5544 length.is_none_or(|length| x448_operation::SECRET_LENGTH as u32 * 8 >= length)
5545 },
5546 DeriveBitsAlgorithm::Hkdf(normalized_algorithm) => {
5547 let hash_length = match normalized_algorithm.hash.name() {
5548 CryptoAlgorithm::Sha1 => 160,
5549 CryptoAlgorithm::Sha256 => 256,
5550 CryptoAlgorithm::Sha384 => 384,
5551 CryptoAlgorithm::Sha512 => 512,
5552 _ => return false,
5553 };
5554 length.is_some_and(|length| length % 8 == 0 && length <= 255 * hash_length)
5555 },
5556 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
5557 length.is_some_and(|length| length % 8 == 0) && normalized_algorithm.iterations != 0
5558 },
5559 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
5560 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
5561 normalized_algorithm
5562 .version
5563 .is_none_or(|version| version == 19) &&
5564 normalized_algorithm.parallelism != 0 &&
5565 normalized_algorithm.parallelism <= 16777215 &&
5566 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
5567 normalized_algorithm.passes != 0
5568 },
5569 }
5570 }
5571}
5572
5573impl<D: Equivalence> DeriveBitsAlgorithm<D> {
5574 fn derive_bits(&self, key: &CryptoKey<D>, length: Option<u32>) -> Result<Vec<u8>, Error> {
5575 match self {
5576 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5577 ecdh_operation::derive_bits(algorithm, key, length)
5578 },
5579 DeriveBitsAlgorithm::X25519(algorithm) => {
5580 x25519_operation::derive_bits(algorithm, key, length)
5581 },
5582 DeriveBitsAlgorithm::X448(algorithm) => {
5583 x448_operation::derive_bits(algorithm, key, length)
5584 },
5585 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5586 hkdf_operation::derive_bits(algorithm, key, length)
5587 },
5588 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5589 pbkdf2_operation::derive_bits(algorithm, key, length)
5590 },
5591 DeriveBitsAlgorithm::Argon2(algorithm) => {
5592 argon2_operation::derive_bits(algorithm, key, length)
5593 },
5594 }
5595 }
5596}
5597
5598struct WrapKeyOperation {}
5600
5601impl Operation for WrapKeyOperation {
5602 type RegisteredAlgorithm = WrapKeyAlgorithm;
5603}
5604
5605enum WrapKeyAlgorithm {
5608 AesKw(Algorithm),
5609}
5610
5611impl NormalizedAlgorithm for WrapKeyAlgorithm {
5612 fn from_object(
5613 cx: &mut JSContext,
5614 algorithm_name: CryptoAlgorithm,
5615 object: HandleObject,
5616 ) -> Fallible<Self> {
5617 match algorithm_name {
5618 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5619 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5620 )),
5621 _ => Err(Error::NotSupported(Some(format!(
5622 "{} does not support \"wrapKey\" operation",
5623 algorithm_name.as_str()
5624 )))),
5625 }
5626 }
5627
5628 fn name(&self) -> CryptoAlgorithm {
5629 match self {
5630 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5631 }
5632 }
5633
5634 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5635 match self {
5636 WrapKeyAlgorithm::AesKw(_) => true,
5637 }
5638 }
5639}
5640
5641impl WrapKeyAlgorithm {
5642 fn wrap_key<D: Equivalence>(
5643 &self,
5644 key: &CryptoKey<D>,
5645 plaintext: &[u8],
5646 ) -> Result<Vec<u8>, Error> {
5647 match self {
5648 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5649 }
5650 }
5651}
5652
5653struct UnwrapKeyOperation {}
5655
5656impl Operation for UnwrapKeyOperation {
5657 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5658}
5659
5660enum UnwrapKeyAlgorithm {
5663 AesKw(Algorithm),
5664}
5665
5666impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5667 fn from_object(
5668 cx: &mut JSContext,
5669 algorithm_name: CryptoAlgorithm,
5670 object: HandleObject,
5671 ) -> Fallible<Self> {
5672 match algorithm_name {
5673 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5674 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5675 )),
5676 _ => Err(Error::NotSupported(Some(format!(
5677 "{} does not support \"unwrapKey\" operation",
5678 algorithm_name.as_str()
5679 )))),
5680 }
5681 }
5682
5683 fn name(&self) -> CryptoAlgorithm {
5684 match self {
5685 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5686 }
5687 }
5688
5689 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5690 match self {
5691 UnwrapKeyAlgorithm::AesKw(_) => true,
5692 }
5693 }
5694}
5695
5696impl UnwrapKeyAlgorithm {
5697 fn unwrap_key<D: Equivalence>(
5698 &self,
5699 key: &CryptoKey<D>,
5700 ciphertext: &[u8],
5701 ) -> Result<Vec<u8>, Error> {
5702 match self {
5703 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5704 }
5705 }
5706}
5707
5708struct GenerateKeyOperation {}
5710
5711impl Operation for GenerateKeyOperation {
5712 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5713}
5714
5715enum GenerateKeyAlgorithm {
5718 RsassaPkcs1V1_5(RsaHashedKeyGenParams),
5719 RsaPss(RsaHashedKeyGenParams),
5720 RsaOaep(RsaHashedKeyGenParams),
5721 Ecdsa(EcKeyGenParams),
5722 Ecdh(EcKeyGenParams),
5723 Ed25519(Algorithm),
5724 X25519(Algorithm),
5725 Ed448(Algorithm),
5726 X448(Algorithm),
5727 AesCtr(AesKeyGenParams),
5728 AesCbc(AesKeyGenParams),
5729 AesGcm(AesKeyGenParams),
5730 AesKw(AesKeyGenParams),
5731 Hmac(HmacKeyGenParams),
5732 MlKem(Algorithm),
5733 HybridKem(Algorithm),
5734 MlDsa(Algorithm),
5735 AesOcb(AesKeyGenParams),
5736 ChaCha20Poly1305(Algorithm),
5737 Kmac(KmacKeyGenParams),
5738}
5739
5740impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5741 fn from_object(
5742 cx: &mut JSContext,
5743 algorithm_name: CryptoAlgorithm,
5744 object: HandleObject,
5745 ) -> Fallible<Self> {
5746 match algorithm_name {
5747 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5748 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5749 )),
5750 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5751 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5752 )),
5753 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5754 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5755 )),
5756 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5757 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5758 )),
5759 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5760 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5761 )),
5762 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5763 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5764 )),
5765 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5766 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5767 )),
5768 CryptoAlgorithm::Ed448 => Ok(GenerateKeyAlgorithm::Ed448(
5769 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5770 )),
5771 CryptoAlgorithm::X448 => Ok(GenerateKeyAlgorithm::X448(
5772 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5773 )),
5774 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5775 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5776 )),
5777 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5778 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5779 )),
5780 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5781 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5782 )),
5783 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5784 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5785 )),
5786 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5787 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5788 )),
5789 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5790 Ok(GenerateKeyAlgorithm::MlKem(
5791 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5792 ))
5793 },
5794 CryptoAlgorithm::MlKem768X25519 => Ok(GenerateKeyAlgorithm::HybridKem(
5795 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5796 )),
5797 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5798 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5799 ),
5800 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5801 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5802 )),
5803 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5804 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5805 )),
5806 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GenerateKeyAlgorithm::Kmac(
5807 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5808 )),
5809 _ => Err(Error::NotSupported(Some(format!(
5810 "{} does not support \"generateKey\" operation",
5811 algorithm_name.as_str()
5812 )))),
5813 }
5814 }
5815
5816 fn name(&self) -> CryptoAlgorithm {
5817 match self {
5818 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5819 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5820 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5821 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5822 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5823 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5824 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5825 GenerateKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5826 GenerateKeyAlgorithm::X448(algorithm) => algorithm.name,
5827 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5828 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5829 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5830 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5831 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5832 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5833 GenerateKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
5834 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5835 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5836 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5837 GenerateKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5838 }
5839 }
5840
5841 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5842 match self {
5843 GenerateKeyAlgorithm::RsassaPkcs1V1_5(normalized_algorithm) |
5844 GenerateKeyAlgorithm::RsaPss(normalized_algorithm) |
5845 GenerateKeyAlgorithm::RsaOaep(normalized_algorithm) => {
5846 normalized_algorithm.validate_parameters().is_ok()
5847 },
5848 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
5849 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
5850 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
5851 },
5852 GenerateKeyAlgorithm::Ed25519(_) |
5853 GenerateKeyAlgorithm::X25519(_) |
5854 GenerateKeyAlgorithm::Ed448(_) |
5855 GenerateKeyAlgorithm::X448(_) => true,
5856 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
5857 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
5858 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
5859 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
5860 matches!(normalized_algorithm.length, 128 | 192 | 256)
5861 },
5862 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
5863 normalized_algorithm.length.is_none_or(|length| length != 0)
5864 },
5865 GenerateKeyAlgorithm::MlKem(_) |
5866 GenerateKeyAlgorithm::HybridKem(_) |
5867 GenerateKeyAlgorithm::MlDsa(_) => true,
5868 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
5869 matches!(normalized_algorithm.length, 128 | 192 | 256)
5870 },
5871 GenerateKeyAlgorithm::ChaCha20Poly1305(_) | GenerateKeyAlgorithm::Kmac(_) => true,
5872 }
5873 }
5874}
5875
5876impl GenerateKeyAlgorithm {
5877 fn generate_key<D: Equivalence>(
5878 &self,
5879 cx: &mut JSContext,
5880 global: &D::GlobalScope,
5881 extractable: bool,
5882 usages: Vec<KeyUsage>,
5883 ) -> Result<CryptoKeyOrCryptoKeyPair<D>, Error> {
5884 match self {
5885 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5886 rsassa_pkcs1_v1_5_operation::generate_key(
5887 cx,
5888 global,
5889 algorithm,
5890 extractable,
5891 usages,
5892 )
5893 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5894 },
5895 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5896 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5897 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5898 },
5899 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5900 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5901 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5902 },
5903 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5904 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5905 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5906 },
5907 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5908 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5909 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5910 },
5911 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5912 ed25519_operation::generate_key(cx, global, extractable, usages)
5913 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5914 },
5915 GenerateKeyAlgorithm::X25519(_algorithm) => {
5916 x25519_operation::generate_key(cx, global, extractable, usages)
5917 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5918 },
5919 GenerateKeyAlgorithm::Ed448(_algorithm) => {
5920 ed448_operation::generate_key(cx, global, extractable, usages)
5921 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5922 },
5923 GenerateKeyAlgorithm::X448(_algorithm) => {
5924 x448_operation::generate_key(cx, global, extractable, usages)
5925 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5926 },
5927 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5928 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5929 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5930 },
5931 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5932 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5933 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5934 },
5935 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5936 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5937 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5938 },
5939 GenerateKeyAlgorithm::AesKw(algorithm) => {
5940 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5941 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5942 },
5943 GenerateKeyAlgorithm::Hmac(algorithm) => {
5944 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5945 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5946 },
5947 GenerateKeyAlgorithm::MlKem(algorithm) => {
5948 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5949 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5950 },
5951 GenerateKeyAlgorithm::HybridKem(algorithm) => {
5952 hybrid_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5953 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5954 },
5955 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5956 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5957 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5958 },
5959 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5960 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5961 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5962 },
5963 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5964 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5965 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5966 },
5967 GenerateKeyAlgorithm::Kmac(algorithm) => {
5968 kmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5969 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5970 },
5971 }
5972 }
5973}
5974
5975struct ImportKeyOperation {}
5977
5978impl Operation for ImportKeyOperation {
5979 type RegisteredAlgorithm = ImportKeyAlgorithm;
5980}
5981
5982enum ImportKeyAlgorithm {
5985 RsassaPkcs1V1_5(RsaHashedImportParams),
5986 RsaPss(RsaHashedImportParams),
5987 RsaOaep(RsaHashedImportParams),
5988 Ecdsa(EcKeyImportParams),
5989 Ecdh(EcKeyImportParams),
5990 Ed25519(Algorithm),
5991 X25519(Algorithm),
5992 Ed448(Algorithm),
5993 X448(Algorithm),
5994 AesCtr(Algorithm),
5995 AesCbc(Algorithm),
5996 AesGcm(Algorithm),
5997 AesKw(Algorithm),
5998 Hmac(HmacImportParams),
5999 Hkdf(Algorithm),
6000 Pbkdf2(Algorithm),
6001 MlKem(Algorithm),
6002 HybridKem(Algorithm),
6003 MlDsa(Algorithm),
6004 AesOcb(Algorithm),
6005 ChaCha20Poly1305(Algorithm),
6006 Kmac(KmacImportParams),
6007 Argon2(Algorithm),
6008}
6009
6010impl NormalizedAlgorithm for ImportKeyAlgorithm {
6011 fn from_object(
6012 cx: &mut JSContext,
6013 algorithm_name: CryptoAlgorithm,
6014 object: HandleObject,
6015 ) -> Fallible<Self> {
6016 match algorithm_name {
6017 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
6018 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6019 )),
6020 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
6021 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6022 )),
6023 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
6024 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6025 )),
6026 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
6027 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6028 )),
6029 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
6030 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6031 )),
6032 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
6033 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6034 )),
6035 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
6036 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6037 )),
6038 CryptoAlgorithm::Ed448 => Ok(ImportKeyAlgorithm::Ed448(
6039 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6040 )),
6041 CryptoAlgorithm::X448 => Ok(ImportKeyAlgorithm::X448(
6042 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6043 )),
6044 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
6045 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6046 )),
6047 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
6048 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6049 )),
6050 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
6051 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6052 )),
6053 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
6054 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6055 )),
6056 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
6057 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6058 )),
6059 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
6060 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6061 )),
6062 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
6063 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6064 )),
6065 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6066 Ok(ImportKeyAlgorithm::MlKem(
6067 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6068 ))
6069 },
6070 CryptoAlgorithm::MlKem768X25519 => Ok(ImportKeyAlgorithm::HybridKem(
6071 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6072 )),
6073 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6074 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6075 ),
6076 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
6077 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6078 )),
6079 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
6080 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6081 )),
6082 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ImportKeyAlgorithm::Kmac(
6083 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6084 )),
6085 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
6086 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6087 ),
6088 _ => Err(Error::NotSupported(Some(format!(
6089 "{} does not support \"importKey\" operation",
6090 algorithm_name.as_str()
6091 )))),
6092 }
6093 }
6094
6095 fn name(&self) -> CryptoAlgorithm {
6096 match self {
6097 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6098 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6099 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6100 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6101 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6102 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6103 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6104 ImportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6105 ImportKeyAlgorithm::X448(algorithm) => algorithm.name,
6106 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6107 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6108 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6109 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6110 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6111 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
6112 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6113 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6114 ImportKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
6115 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6116 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6117 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6118 ImportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6119 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
6120 }
6121 }
6122
6123 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6124 match self {
6125 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6126 ImportKeyAlgorithm::RsaPss(_) |
6127 ImportKeyAlgorithm::RsaOaep(_) => true,
6128 ImportKeyAlgorithm::Ecdsa(normalized_algorithm) |
6129 ImportKeyAlgorithm::Ecdh(normalized_algorithm) => {
6130 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
6131 },
6132 ImportKeyAlgorithm::Ed25519(_) |
6133 ImportKeyAlgorithm::X25519(_) |
6134 ImportKeyAlgorithm::Ed448(_) |
6135 ImportKeyAlgorithm::X448(_) |
6136 ImportKeyAlgorithm::AesCtr(_) |
6137 ImportKeyAlgorithm::AesCbc(_) |
6138 ImportKeyAlgorithm::AesGcm(_) |
6139 ImportKeyAlgorithm::AesKw(_) => true,
6140 ImportKeyAlgorithm::Hmac(normalized_algorithm) => {
6141 normalized_algorithm.length.is_none_or(|length| length != 0)
6142 },
6143 ImportKeyAlgorithm::Hkdf(_) |
6144 ImportKeyAlgorithm::Pbkdf2(_) |
6145 ImportKeyAlgorithm::MlKem(_) |
6146 ImportKeyAlgorithm::HybridKem(_) |
6147 ImportKeyAlgorithm::MlDsa(_) |
6148 ImportKeyAlgorithm::AesOcb(_) |
6149 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
6150 ImportKeyAlgorithm::Kmac(_) |
6151 ImportKeyAlgorithm::Argon2(_) => true,
6152 }
6153 }
6154}
6155
6156impl ImportKeyAlgorithm {
6157 fn import_key<D: Equivalence>(
6158 &self,
6159 cx: &mut JSContext,
6160 global: &D::GlobalScope,
6161 format: KeyFormat,
6162 key_data: &[u8],
6163 extractable: bool,
6164 usages: Vec<KeyUsage>,
6165 ) -> Result<DomRoot<CryptoKey<D>>, Error> {
6166 match self {
6167 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
6168 rsassa_pkcs1_v1_5_operation::import_key(
6169 cx,
6170 global,
6171 algorithm,
6172 format,
6173 key_data,
6174 extractable,
6175 usages,
6176 )
6177 },
6178 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
6179 cx,
6180 global,
6181 algorithm,
6182 format,
6183 key_data,
6184 extractable,
6185 usages,
6186 ),
6187 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
6188 cx,
6189 global,
6190 algorithm,
6191 format,
6192 key_data,
6193 extractable,
6194 usages,
6195 ),
6196 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
6197 cx,
6198 global,
6199 algorithm,
6200 format,
6201 key_data,
6202 extractable,
6203 usages,
6204 ),
6205 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
6206 cx,
6207 global,
6208 algorithm,
6209 format,
6210 key_data,
6211 extractable,
6212 usages,
6213 ),
6214 ImportKeyAlgorithm::Ed25519(_algorithm) => {
6215 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6216 },
6217 ImportKeyAlgorithm::X25519(_algorithm) => {
6218 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6219 },
6220 ImportKeyAlgorithm::Ed448(_algorithm) => {
6221 ed448_operation::import_key(cx, global, format, key_data, extractable, usages)
6222 },
6223 ImportKeyAlgorithm::X448(_algorithm) => {
6224 x448_operation::import_key(cx, global, format, key_data, extractable, usages)
6225 },
6226 ImportKeyAlgorithm::AesCtr(_algorithm) => {
6227 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
6228 },
6229 ImportKeyAlgorithm::AesCbc(_algorithm) => {
6230 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
6231 },
6232 ImportKeyAlgorithm::AesGcm(_algorithm) => {
6233 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
6234 },
6235 ImportKeyAlgorithm::AesKw(_algorithm) => {
6236 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
6237 },
6238 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
6239 cx,
6240 global,
6241 algorithm,
6242 format,
6243 key_data,
6244 extractable,
6245 usages,
6246 ),
6247 ImportKeyAlgorithm::Hkdf(_algorithm) => {
6248 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
6249 },
6250 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
6251 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
6252 },
6253 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
6254 cx,
6255 global,
6256 algorithm,
6257 format,
6258 key_data,
6259 extractable,
6260 usages,
6261 ),
6262 ImportKeyAlgorithm::HybridKem(algorithm) => hybrid_kem_operation::import_key(
6263 cx,
6264 global,
6265 algorithm,
6266 format,
6267 key_data,
6268 extractable,
6269 usages,
6270 ),
6271 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
6272 cx,
6273 global,
6274 algorithm,
6275 format,
6276 key_data,
6277 extractable,
6278 usages,
6279 ),
6280 ImportKeyAlgorithm::AesOcb(_algorithm) => {
6281 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
6282 },
6283 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6284 chacha20_poly1305_operation::import_key(
6285 cx,
6286 global,
6287 format,
6288 key_data,
6289 extractable,
6290 usages,
6291 )
6292 },
6293 ImportKeyAlgorithm::Kmac(algorithm) => kmac_operation::import_key(
6294 cx,
6295 global,
6296 algorithm,
6297 format,
6298 key_data,
6299 extractable,
6300 usages,
6301 ),
6302 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
6303 cx,
6304 global,
6305 algorithm,
6306 format,
6307 key_data,
6308 extractable,
6309 usages,
6310 ),
6311 }
6312 }
6313
6314 fn will_throw_for_key_data_length(&self, key_data_length: u32) -> bool {
6318 match self {
6319 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6320 ImportKeyAlgorithm::RsaPss(_) |
6321 ImportKeyAlgorithm::RsaOaep(_) |
6322 ImportKeyAlgorithm::Ecdsa(_) |
6323 ImportKeyAlgorithm::Ecdh(_) |
6324 ImportKeyAlgorithm::Ed25519(_) |
6325 ImportKeyAlgorithm::X25519(_) |
6326 ImportKeyAlgorithm::Ed448(_) |
6327 ImportKeyAlgorithm::X448(_) => true,
6328 ImportKeyAlgorithm::AesCtr(_) |
6329 ImportKeyAlgorithm::AesCbc(_) |
6330 ImportKeyAlgorithm::AesGcm(_) |
6331 ImportKeyAlgorithm::AesKw(_) => !matches!(key_data_length, 128 | 192 | 256),
6332 ImportKeyAlgorithm::Hmac(algorithm) => {
6333 key_data_length == 0 ||
6334 algorithm.length.is_some_and(|length| {
6335 length > key_data_length || length + 8 <= key_data_length
6336 })
6337 },
6338 ImportKeyAlgorithm::Hkdf(_) | ImportKeyAlgorithm::Pbkdf2(_) => false,
6339 ImportKeyAlgorithm::MlKem(_) |
6340 ImportKeyAlgorithm::HybridKem(_) |
6341 ImportKeyAlgorithm::MlDsa(_) => true,
6342 ImportKeyAlgorithm::AesOcb(_) => !matches!(key_data_length, 128 | 192 | 256),
6343 ImportKeyAlgorithm::ChaCha20Poly1305(_) => key_data_length != 256,
6344 ImportKeyAlgorithm::Kmac(algorithm) => algorithm
6345 .length
6346 .is_some_and(|length| length > key_data_length || length + 8 <= key_data_length),
6347 ImportKeyAlgorithm::Argon2(_) => false,
6348 }
6349 }
6350}
6351
6352struct ExportKeyOperation {}
6354
6355impl Operation for ExportKeyOperation {
6356 type RegisteredAlgorithm = ExportKeyAlgorithm;
6357}
6358
6359enum ExportKeyAlgorithm {
6362 RsassaPkcs1V1_5(Algorithm),
6363 RsaPss(Algorithm),
6364 RsaOaep(Algorithm),
6365 Ecdsa(Algorithm),
6366 Ecdh(Algorithm),
6367 Ed25519(Algorithm),
6368 X25519(Algorithm),
6369 Ed448(Algorithm),
6370 X448(Algorithm),
6371 AesCtr(Algorithm),
6372 AesCbc(Algorithm),
6373 AesGcm(Algorithm),
6374 AesKw(Algorithm),
6375 Hmac(Algorithm),
6376 MlKem(Algorithm),
6377 HybridKem(Algorithm),
6378 MlDsa(Algorithm),
6379 AesOcb(Algorithm),
6380 ChaCha20Poly1305(Algorithm),
6381 Kmac(Algorithm),
6382}
6383
6384impl NormalizedAlgorithm for ExportKeyAlgorithm {
6385 fn from_object(
6386 cx: &mut JSContext,
6387 algorithm_name: CryptoAlgorithm,
6388 object: HandleObject,
6389 ) -> Fallible<Self> {
6390 match algorithm_name {
6391 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
6392 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6393 )),
6394 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
6395 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6396 )),
6397 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
6398 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6399 )),
6400 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
6401 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6402 )),
6403 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
6404 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6405 )),
6406 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
6407 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6408 )),
6409 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
6410 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6411 )),
6412 CryptoAlgorithm::Ed448 => Ok(ExportKeyAlgorithm::Ed448(
6413 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6414 )),
6415 CryptoAlgorithm::X448 => Ok(ExportKeyAlgorithm::X448(
6416 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6417 )),
6418 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
6419 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6420 )),
6421 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
6422 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6423 )),
6424 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
6425 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6426 )),
6427 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
6428 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6429 )),
6430 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
6431 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6432 )),
6433 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6434 Ok(ExportKeyAlgorithm::MlKem(
6435 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6436 ))
6437 },
6438 CryptoAlgorithm::MlKem768X25519 => Ok(ExportKeyAlgorithm::HybridKem(
6439 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6440 )),
6441 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6442 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6443 ),
6444 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
6445 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6446 )),
6447 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
6448 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6449 )),
6450 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ExportKeyAlgorithm::Kmac(
6451 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6452 )),
6453 _ => Err(Error::NotSupported(Some(format!(
6454 "{} does not support \"exportKey\" operation",
6455 algorithm_name.as_str()
6456 )))),
6457 }
6458 }
6459
6460 fn name(&self) -> CryptoAlgorithm {
6461 match self {
6462 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6463 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6464 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6465 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6466 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6467 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6468 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6469 ExportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6470 ExportKeyAlgorithm::X448(algorithm) => algorithm.name,
6471 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6472 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6473 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6474 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6475 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6476 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6477 ExportKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
6478 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6479 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6480 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6481 ExportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6482 }
6483 }
6484
6485 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6486 match self {
6487 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6488 ExportKeyAlgorithm::RsaPss(_) |
6489 ExportKeyAlgorithm::RsaOaep(_) |
6490 ExportKeyAlgorithm::Ecdsa(_) |
6491 ExportKeyAlgorithm::Ecdh(_) |
6492 ExportKeyAlgorithm::Ed25519(_) |
6493 ExportKeyAlgorithm::X25519(_) |
6494 ExportKeyAlgorithm::Ed448(_) |
6495 ExportKeyAlgorithm::X448(_) |
6496 ExportKeyAlgorithm::AesCtr(_) |
6497 ExportKeyAlgorithm::AesCbc(_) |
6498 ExportKeyAlgorithm::AesGcm(_) |
6499 ExportKeyAlgorithm::AesKw(_) |
6500 ExportKeyAlgorithm::Hmac(_) |
6501 ExportKeyAlgorithm::MlKem(_) |
6502 ExportKeyAlgorithm::HybridKem(_) |
6503 ExportKeyAlgorithm::MlDsa(_) |
6504 ExportKeyAlgorithm::AesOcb(_) |
6505 ExportKeyAlgorithm::ChaCha20Poly1305(_) |
6506 ExportKeyAlgorithm::Kmac(_) => true,
6507 }
6508 }
6509}
6510
6511impl ExportKeyAlgorithm {
6512 fn export_key<D: Equivalence>(
6513 &self,
6514 format: KeyFormat,
6515 key: &CryptoKey<D>,
6516 ) -> Result<ExportedKey, Error> {
6517 match self {
6518 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
6519 rsassa_pkcs1_v1_5_operation::export_key(format, key)
6520 },
6521 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
6522 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
6523 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
6524 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
6525 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
6526 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
6527 ExportKeyAlgorithm::Ed448(_algorithm) => ed448_operation::export_key(format, key),
6528 ExportKeyAlgorithm::X448(_algorithm) => x448_operation::export_key(format, key),
6529 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
6530 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
6531 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
6532 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
6533 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
6534 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
6535 ExportKeyAlgorithm::HybridKem(_algorithm) => {
6536 hybrid_kem_operation::export_key(format, key)
6537 },
6538 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
6539 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
6540 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6541 chacha20_poly1305_operation::export_key(format, key)
6542 },
6543 ExportKeyAlgorithm::Kmac(_algorithm) => kmac_operation::export_key(format, key),
6544 }
6545 }
6546}
6547
6548struct GetKeyLengthOperation {}
6550
6551impl Operation for GetKeyLengthOperation {
6552 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
6553}
6554
6555enum GetKeyLengthAlgorithm {
6558 AesCtr(AesDerivedKeyParams),
6559 AesCbc(AesDerivedKeyParams),
6560 AesGcm(AesDerivedKeyParams),
6561 AesKw(AesDerivedKeyParams),
6562 Hmac(HmacImportParams),
6563 Hkdf(Algorithm),
6564 Pbkdf2(Algorithm),
6565 AesOcb(AesDerivedKeyParams),
6566 ChaCha20Poly1305(Algorithm),
6567 Kmac(KmacImportParams),
6568 Argon2(Algorithm),
6569}
6570
6571impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
6572 fn from_object(
6573 cx: &mut JSContext,
6574 algorithm_name: CryptoAlgorithm,
6575 object: HandleObject,
6576 ) -> Fallible<Self> {
6577 match algorithm_name {
6578 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
6579 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6580 )),
6581 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
6582 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6583 )),
6584 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
6585 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6586 )),
6587 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
6588 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6589 )),
6590 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
6591 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6592 )),
6593 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
6594 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6595 )),
6596 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
6597 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6598 )),
6599 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
6600 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6601 )),
6602 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
6603 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6604 )),
6605 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GetKeyLengthAlgorithm::Kmac(
6606 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6607 )),
6608 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
6609 Ok(GetKeyLengthAlgorithm::Argon2(
6610 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6611 ))
6612 },
6613 _ => Err(Error::NotSupported(Some(format!(
6614 "{} does not support \"get key length\" operation",
6615 algorithm_name.as_str()
6616 )))),
6617 }
6618 }
6619
6620 fn name(&self) -> CryptoAlgorithm {
6621 match self {
6622 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
6623 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
6624 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
6625 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
6626 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
6627 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
6628 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6629 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
6630 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6631 GetKeyLengthAlgorithm::Kmac(algorithm) => algorithm.name,
6632 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
6633 }
6634 }
6635
6636 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6637 match self {
6638 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
6639 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
6640 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
6641 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
6642 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
6643 },
6644 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
6645 normalized_derived_key_algorithm
6646 .length
6647 .is_none_or(|length| length != 0)
6648 },
6649 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
6650 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
6651 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
6652 },
6653 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) |
6654 GetKeyLengthAlgorithm::Kmac(_) |
6655 GetKeyLengthAlgorithm::Argon2(_) => true,
6656 }
6657 }
6658}
6659
6660impl GetKeyLengthAlgorithm {
6661 fn get_key_length(&self) -> Result<Option<u32>, Error> {
6662 match self {
6663 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
6664 aes_ctr_operation::get_key_length(algorithm)
6665 },
6666 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
6667 aes_cbc_operation::get_key_length(algorithm)
6668 },
6669 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
6670 aes_gcm_operation::get_key_length(algorithm)
6671 },
6672 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
6673 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
6674 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
6675 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
6676 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
6677 aes_ocb_operation::get_key_length(algorithm)
6678 },
6679 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
6680 chacha20_poly1305_operation::get_key_length()
6681 },
6682 GetKeyLengthAlgorithm::Kmac(algorithm) => kmac_operation::get_key_length(algorithm),
6683 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
6684 }
6685 }
6686}
6687
6688struct EncapsulateOperation {}
6690
6691impl Operation for EncapsulateOperation {
6692 type RegisteredAlgorithm = EncapsulateAlgorithm;
6693}
6694
6695enum EncapsulateAlgorithm {
6698 MlKem(Algorithm),
6699 HybridKem(Algorithm),
6700}
6701
6702impl NormalizedAlgorithm for EncapsulateAlgorithm {
6703 fn from_object(
6704 cx: &mut JSContext,
6705 algorithm_name: CryptoAlgorithm,
6706 object: HandleObject,
6707 ) -> Fallible<Self> {
6708 match algorithm_name {
6709 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6710 Ok(EncapsulateAlgorithm::MlKem(
6711 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6712 ))
6713 },
6714 CryptoAlgorithm::MlKem768X25519 => Ok(EncapsulateAlgorithm::HybridKem(
6715 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6716 )),
6717 _ => Err(Error::NotSupported(Some(format!(
6718 "{} does not support \"encapsulate\" operation",
6719 algorithm_name.as_str()
6720 )))),
6721 }
6722 }
6723
6724 fn name(&self) -> CryptoAlgorithm {
6725 match self {
6726 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6727 EncapsulateAlgorithm::HybridKem(algorithm) => algorithm.name,
6728 }
6729 }
6730
6731 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6732 match self {
6733 EncapsulateAlgorithm::MlKem(_) | EncapsulateAlgorithm::HybridKem(_) => true,
6734 }
6735 }
6736}
6737
6738impl EncapsulateAlgorithm {
6739 fn encapsulate<D: Equivalence>(&self, key: &CryptoKey<D>) -> Result<EncapsulatedBits, Error> {
6740 match self {
6741 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6742 EncapsulateAlgorithm::HybridKem(algorithm) => {
6743 hybrid_kem_operation::encapsulate(algorithm, key)
6744 },
6745 }
6746 }
6747}
6748
6749struct DecapsulateOperation {}
6751
6752impl Operation for DecapsulateOperation {
6753 type RegisteredAlgorithm = DecapsulateAlgorithm;
6754}
6755
6756enum DecapsulateAlgorithm {
6759 MlKem(Algorithm),
6760 HybridKem(Algorithm),
6761}
6762
6763impl NormalizedAlgorithm for DecapsulateAlgorithm {
6764 fn from_object(
6765 cx: &mut JSContext,
6766 algorithm_name: CryptoAlgorithm,
6767 object: HandleObject,
6768 ) -> Fallible<Self> {
6769 match algorithm_name {
6770 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6771 Ok(DecapsulateAlgorithm::MlKem(
6772 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6773 ))
6774 },
6775 CryptoAlgorithm::MlKem768X25519 => Ok(DecapsulateAlgorithm::HybridKem(
6776 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6777 )),
6778 _ => Err(Error::NotSupported(Some(format!(
6779 "{} does not support \"decapsulate\" operation",
6780 algorithm_name.as_str()
6781 )))),
6782 }
6783 }
6784
6785 fn name(&self) -> CryptoAlgorithm {
6786 match self {
6787 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6788 DecapsulateAlgorithm::HybridKem(algorithm) => algorithm.name,
6789 }
6790 }
6791
6792 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6793 match self {
6794 DecapsulateAlgorithm::MlKem(_) | DecapsulateAlgorithm::HybridKem(_) => true,
6795 }
6796 }
6797}
6798
6799impl DecapsulateAlgorithm {
6800 fn decapsulate<D: Equivalence>(
6801 &self,
6802 key: &CryptoKey<D>,
6803 ciphertext: &[u8],
6804 ) -> Result<Vec<u8>, Error> {
6805 match self {
6806 DecapsulateAlgorithm::MlKem(algorithm) => {
6807 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6808 },
6809 DecapsulateAlgorithm::HybridKem(algorithm) => {
6810 hybrid_kem_operation::decapsulate(algorithm, key, ciphertext)
6811 },
6812 }
6813 }
6814}
6815
6816struct GetSharedKeyLengthOperation {}
6818
6819impl Operation for GetSharedKeyLengthOperation {
6820 type RegisteredAlgorithm = GetSharedKeyLengthAlgorithm;
6821}
6822
6823enum GetSharedKeyLengthAlgorithm {
6826 MlKem(Algorithm),
6827 HybridKem(Algorithm),
6828}
6829
6830impl NormalizedAlgorithm for GetSharedKeyLengthAlgorithm {
6831 fn from_object(
6832 cx: &mut JSContext,
6833 algorithm_name: CryptoAlgorithm,
6834 object: HandleObject,
6835 ) -> Fallible<Self> {
6836 match algorithm_name {
6837 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6838 Ok(GetSharedKeyLengthAlgorithm::MlKem(
6839 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6840 ))
6841 },
6842 CryptoAlgorithm::MlKem768X25519 => Ok(GetSharedKeyLengthAlgorithm::HybridKem(
6843 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6844 )),
6845 _ => Err(Error::NotSupported(Some(format!(
6846 "{} does not support \"get shared key length\" operation",
6847 algorithm_name.as_str()
6848 )))),
6849 }
6850 }
6851
6852 fn name(&self) -> CryptoAlgorithm {
6853 match self {
6854 GetSharedKeyLengthAlgorithm::MlKem(algorithm) => algorithm.name,
6855 GetSharedKeyLengthAlgorithm::HybridKem(algorithm) => algorithm.name,
6856 }
6857 }
6858}
6859
6860impl GetSharedKeyLengthAlgorithm {
6861 fn get_shared_key_length(&self) -> u32 {
6862 match self {
6863 GetSharedKeyLengthAlgorithm::MlKem(_algorithm) => {
6864 ml_kem_operation::get_shared_key_length()
6865 },
6866 GetSharedKeyLengthAlgorithm::HybridKem(_algorithm) => {
6867 hybrid_kem_operation::get_shared_key_length()
6868 },
6869 }
6870 }
6871}
6872
6873struct GetPublicKeyOperation {}
6875
6876impl Operation for GetPublicKeyOperation {
6877 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6878}
6879
6880enum GetPublicKeyAlgorithm {
6883 RsassaPkcs1v1_5(Algorithm),
6884 RsaPss(Algorithm),
6885 RsaOaep(Algorithm),
6886 Ecdsa(Algorithm),
6887 Ecdh(Algorithm),
6888 Ed25519(Algorithm),
6889 X25519(Algorithm),
6890 Ed448(Algorithm),
6891 X448(Algorithm),
6892 MlKem(Algorithm),
6893 HybridKem(Algorithm),
6894 MlDsa(Algorithm),
6895}
6896
6897impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6898 fn from_object(
6899 cx: &mut JSContext,
6900 algorithm_name: CryptoAlgorithm,
6901 object: HandleObject,
6902 ) -> Fallible<Self> {
6903 match algorithm_name {
6904 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6905 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6906 )),
6907 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6908 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6909 )),
6910 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6911 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6912 )),
6913 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6914 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6915 )),
6916 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6917 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6918 )),
6919 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6920 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6921 )),
6922 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6923 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6924 )),
6925 CryptoAlgorithm::Ed448 => Ok(GetPublicKeyAlgorithm::Ed448(
6926 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6927 )),
6928 CryptoAlgorithm::X448 => Ok(GetPublicKeyAlgorithm::X448(
6929 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6930 )),
6931 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6932 Ok(GetPublicKeyAlgorithm::MlKem(
6933 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6934 ))
6935 },
6936 CryptoAlgorithm::MlKem768X25519 => Ok(GetPublicKeyAlgorithm::HybridKem(
6937 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6938 )),
6939 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6940 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6941 ),
6942 _ => Err(Error::NotSupported(Some(format!(
6943 "{} does not support \"getPublicKey\" operation",
6944 algorithm_name.as_str()
6945 )))),
6946 }
6947 }
6948
6949 fn name(&self) -> CryptoAlgorithm {
6950 match self {
6951 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6952 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6953 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6954 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6955 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6956 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6957 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6958 GetPublicKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6959 GetPublicKeyAlgorithm::X448(algorithm) => algorithm.name,
6960 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6961 GetPublicKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
6962 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6963 }
6964 }
6965}
6966
6967impl GetPublicKeyAlgorithm {
6968 fn get_public_key<D: Equivalence>(
6969 &self,
6970 cx: &mut JSContext,
6971 global: &D::GlobalScope,
6972 key: &CryptoKey<D>,
6973 algorithm: &KeyAlgorithmAndDerivatives,
6974 usages: Vec<KeyUsage>,
6975 ) -> Result<DomRoot<CryptoKey<D>>, Error> {
6976 match self {
6977 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6978 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6979 },
6980 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6981 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6982 },
6983 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6984 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6985 },
6986 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6987 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6988 },
6989 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6990 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6991 },
6992 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6993 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6994 },
6995 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6996 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6997 },
6998 GetPublicKeyAlgorithm::Ed448(_algorithm) => {
6999 ed448_operation::get_public_key(cx, global, key, algorithm, usages)
7000 },
7001 GetPublicKeyAlgorithm::X448(_algorithm) => {
7002 x448_operation::get_public_key(cx, global, key, algorithm, usages)
7003 },
7004 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
7005 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
7006 },
7007 GetPublicKeyAlgorithm::HybridKem(_algorithm) => {
7008 hybrid_kem_operation::get_public_key(cx, global, key, algorithm, usages)
7009 },
7010 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
7011 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
7012 },
7013 }
7014 }
7015}