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