1#![cfg_attr(crown, allow(crown::jscontext_first_arg))]
6
7mod aes_cbc_operation;
8mod aes_common;
9mod aes_ctr_operation;
10mod aes_gcm_operation;
11mod aes_kw_operation;
12mod aes_ocb_operation;
13mod argon2_operation;
14mod chacha20_poly1305_operation;
15mod cshake_operation;
16mod ec_common;
17mod ecdh_operation;
18mod ecdsa_operation;
19mod ed25519_operation;
20mod ed448_operation;
21mod hkdf_operation;
22mod hmac_operation;
23mod hybrid_kem_operation;
24mod kangarootwelve_operation;
25mod kmac_operation;
26mod ml_dsa_operation;
27mod ml_kem_operation;
28mod pbkdf2_operation;
29mod rsa_common;
30mod rsa_oaep_operation;
31mod rsa_pss_operation;
32mod rsassa_pkcs1_v1_5_operation;
33mod sha3_operation;
34mod sha_operation;
35mod turboshake_operation;
36mod x25519_operation;
37mod x448_operation;
38
39use std::fmt::Display;
40use std::ptr;
41use std::str::FromStr;
42
43use base64ct::{Base64UrlUnpadded, Encoding};
44use dom_struct::dom_struct;
45use js::conversions::{ConversionBehavior, ConversionResult, FromJSValConvertible};
46use js::jsapi::{Heap, JSObject};
47use js::jsval::{ObjectOrNullValue, UndefinedValue};
48use js::realm::CurrentRealm;
49use js::rust::wrappers2::{JS_NewObject, JS_ParseJSON};
50use js::rust::{HandleObject, MutableHandleValue, Trace};
51use js::typedarray::{ArrayBufferU8, HeapUint8Array};
52use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
53use servo_constellation_traits::{
54 SerializableAesKeyAlgorithm, SerializableAlgorithm, SerializableCShakeParams,
55 SerializableDigestAlgorithm, SerializableEcKeyAlgorithm, SerializableHmacKeyAlgorithm,
56 SerializableKangarooTwelveParams, SerializableKeyAlgorithm,
57 SerializableKeyAlgorithmAndDerivatives, SerializableKmacKeyAlgorithm,
58 SerializableRsaHashedKeyAlgorithm, SerializableTurboShakeParams,
59};
60use strum::{EnumString, IntoStaticStr, VariantArray};
61use zeroize::Zeroizing;
62
63use crate::dom::bindings::buffer_source::{create_buffer_source, get_buffer_source_copy};
64use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
65 CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
66};
67use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
68 Algorithm as AlgorithmWithDOMString, AlgorithmIdentifier, JsonWebKey, KeyFormat,
69 SubtleCryptoMethods,
70};
71use crate::dom::bindings::codegen::UnionTypes::{
72 ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
73};
74use crate::dom::bindings::conversions::{
75 StringificationBehavior, ToJSValConvertible, get_property,
76};
77use crate::dom::bindings::error::{Error, Fallible};
78use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
79use crate::dom::bindings::reflector::DomGlobal;
80use crate::dom::bindings::root::DomRoot;
81use crate::dom::bindings::str::{DOMString, serialize_jsval_to_json_utf8};
82use crate::dom::bindings::trace::RootedTraceableBox;
83use crate::dom::bindings::utils::set_dictionary_property;
84use crate::dom::cryptokey::{CryptoKey, CryptoKeyOrCryptoKeyPair};
85use crate::dom::globalscope::GlobalScope;
86use crate::dom::promise::{Promise, RootedPromise};
87
88const NAMED_CURVE_P256: &str = "P-256";
90const NAMED_CURVE_P384: &str = "P-384";
91const NAMED_CURVE_P521: &str = "P-521";
92
93static SUPPORTED_CURVES: &[&str] = &[NAMED_CURVE_P256, NAMED_CURVE_P384, NAMED_CURVE_P521];
94
95#[derive(EnumString, VariantArray, IntoStaticStr, PartialEq, Clone, Copy, MallocSizeOf)]
96enum CryptoAlgorithm {
97 #[strum(serialize = "RSASSA-PKCS1-v1_5")]
98 RsassaPkcs1V1_5,
99 #[strum(serialize = "RSA-PSS")]
100 RsaPss,
101 #[strum(serialize = "RSA-OAEP")]
102 RsaOaep,
103 #[strum(serialize = "ECDSA")]
104 Ecdsa,
105 #[strum(serialize = "ECDH")]
106 Ecdh,
107 #[strum(serialize = "Ed25519")]
108 Ed25519,
109 #[strum(serialize = "X25519")]
110 X25519,
111 #[strum(serialize = "Ed448")]
112 Ed448,
113 #[strum(serialize = "X448")]
114 X448,
115 #[strum(serialize = "AES-CTR")]
116 AesCtr,
117 #[strum(serialize = "AES-CBC")]
118 AesCbc,
119 #[strum(serialize = "AES-GCM")]
120 AesGcm,
121 #[strum(serialize = "AES-KW")]
122 AesKw,
123 #[strum(serialize = "HMAC")]
124 Hmac,
125 #[strum(serialize = "SHA-1")]
126 Sha1,
127 #[strum(serialize = "SHA-256")]
128 Sha256,
129 #[strum(serialize = "SHA-384")]
130 Sha384,
131 #[strum(serialize = "SHA-512")]
132 Sha512,
133 #[strum(serialize = "HKDF")]
134 Hkdf,
135 #[strum(serialize = "PBKDF2")]
136 Pbkdf2,
137 #[strum(serialize = "ML-KEM-512")]
138 MlKem512,
139 #[strum(serialize = "ML-KEM-768")]
140 MlKem768,
141 #[strum(serialize = "ML-KEM-1024")]
142 MlKem1024,
143 #[strum(serialize = "MLKEM768-X25519")]
144 MlKem768X25519,
145 #[strum(serialize = "ML-DSA-44")]
146 MlDsa44,
147 #[strum(serialize = "ML-DSA-65")]
148 MlDsa65,
149 #[strum(serialize = "ML-DSA-87")]
150 MlDsa87,
151 #[strum(serialize = "AES-OCB")]
152 AesOcb,
153 #[strum(serialize = "ChaCha20-Poly1305")]
154 ChaCha20Poly1305,
155 #[strum(serialize = "SHA3-256")]
156 Sha3_256,
157 #[strum(serialize = "SHA3-384")]
158 Sha3_384,
159 #[strum(serialize = "SHA3-512")]
160 Sha3_512,
161 #[strum(serialize = "cSHAKE128")]
162 CShake128,
163 #[strum(serialize = "cSHAKE256")]
164 CShake256,
165 #[strum(serialize = "TurboSHAKE128")]
166 TurboShake128,
167 #[strum(serialize = "TurboSHAKE256")]
168 TurboShake256,
169 #[strum(serialize = "KT128")]
170 Kt128,
171 #[strum(serialize = "KT256")]
172 Kt256,
173 #[strum(serialize = "KMAC128")]
174 Kmac128,
175 #[strum(serialize = "KMAC256")]
176 Kmac256,
177 #[strum(serialize = "Argon2d")]
178 Argon2D,
179 #[strum(serialize = "Argon2i")]
180 Argon2I,
181 #[strum(serialize = "Argon2id")]
182 Argon2ID,
183}
184
185impl CryptoAlgorithm {
186 fn as_str(&self) -> &'static str {
188 (*self).into()
189 }
190
191 fn from_str_ignore_case(algorithm_name: &str) -> Fallible<CryptoAlgorithm> {
192 Self::VARIANTS
193 .iter()
194 .find(|algorithm| algorithm.as_str().eq_ignore_ascii_case(algorithm_name))
195 .cloned()
196 .ok_or(Error::NotSupported(Some(format!(
197 "Unsupported algorithm: {algorithm_name}"
198 ))))
199 }
200}
201
202#[dom_struct]
204pub(crate) struct SubtleCrypto {
205 reflector_: Reflector,
206}
207
208impl SubtleCrypto {
209 fn new_inherited() -> SubtleCrypto {
210 SubtleCrypto {
211 reflector_: Reflector::new(),
212 }
213 }
214
215 pub(crate) fn new(
216 cx: &mut js::context::JSContext,
217 global: &GlobalScope,
218 ) -> DomRoot<SubtleCrypto> {
219 reflect_dom_object_with_cx(Box::new(SubtleCrypto::new_inherited()), global, cx)
220 }
221
222 fn resolve_promise_with_data(&self, promise: &RootedPromise, data: Zeroizing<Vec<u8>>) {
226 let trusted_promise = TrustedPromise::from(promise);
227 self.global()
228 .task_manager()
229 .crypto_task_source()
230 .queue(task!(resolve_data: move |cx| {
231 let promise = trusted_promise.root(cx);
232
233 rooted!(&in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
234 match create_buffer_source::<ArrayBufferU8>(cx,
235 &data,
236 array_buffer_ptr.handle_mut(),
237 ) {
238 Ok(_) => promise.resolve_native(cx, &*array_buffer_ptr),
239 Err(_) => promise.reject_error(cx, Error::JSFailed),
240 }
241 }));
242 }
243
244 fn resolve_promise_with_jwk(
248 &self,
249 cx: &mut js::context::JSContext,
250 promise: &RootedPromise,
251 jwk: Box<JsonWebKey>,
252 ) {
253 let stringified_jwk = match jwk.stringify(cx) {
256 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.to_string()),
257 Err(error) => {
258 self.reject_promise_with_error(promise, error);
259 return;
260 },
261 };
262
263 let trusted_subtle = Trusted::new(self);
264 let trusted_promise = TrustedPromise::from(promise);
265 self.global()
266 .task_manager()
267 .crypto_task_source()
268 .queue(task!(resolve_jwk: move |cx| {
269 let subtle = trusted_subtle.root();
270 let promise = trusted_promise.root(cx);
271
272 match JsonWebKey::parse(cx, stringified_jwk.as_bytes()) {
273 Ok(jwk) => {
274 rooted!(&in(cx) let mut rval = UndefinedValue());
275 jwk.to_jsval(cx, rval.handle_mut());
276 rooted!(&in(cx) let mut object = rval.to_object());
277 promise.resolve_native(cx, &*object);
278 },
279 Err(error) => {
280 subtle.reject_promise_with_error(&promise, error);
281 return;
282 },
283 }
284 }));
285 }
286
287 fn resolve_promise_with_key(&self, promise: &RootedPromise, key: &CryptoKey) {
290 let trusted_key = Trusted::new(key);
291 let trusted_promise = TrustedPromise::from(promise);
292 self.global()
293 .task_manager()
294 .crypto_task_source()
295 .queue(task!(resolve_key: move |cx| {
296 let key = trusted_key.root();
297 let promise = trusted_promise.root(cx);
298 promise.resolve_native(cx, &key);
299 }));
300 }
301
302 fn resolve_promise_with_key_pair(&self, promise: &RootedPromise, key_pair: CryptoKeyPair) {
305 let trusted_private_key = key_pair.privateKey.map(|key| Trusted::new(&*key));
306 let trusted_public_key = key_pair.publicKey.map(|key| Trusted::new(&*key));
307 let trusted_promise = TrustedPromise::from(promise);
308 self.global()
309 .task_manager()
310 .crypto_task_source()
311 .queue(task!(resolve_key: move |cx| {
312 let key_pair = CryptoKeyPair {
313 privateKey: trusted_private_key.map(|trusted_key| trusted_key.root()),
314 publicKey: trusted_public_key.map(|trusted_key| trusted_key.root()),
315 };
316 let promise = trusted_promise.root(cx);
317 promise.resolve_native(cx, &key_pair);
318 }));
319 }
320
321 fn resolve_promise_with_bool(&self, promise: &RootedPromise, result: bool) {
324 let trusted_promise = TrustedPromise::from(promise);
325 self.global()
326 .task_manager()
327 .crypto_task_source()
328 .queue(task!(resolve_bool: move |cx| {
329 let promise = trusted_promise.root(cx);
330 promise.resolve_native(cx, &result);
331 }));
332 }
333
334 fn reject_promise_with_error(&self, promise: &RootedPromise, error: Error) {
337 let trusted_promise = TrustedPromise::from(promise);
338 self.global()
339 .task_manager()
340 .crypto_task_source()
341 .queue(task!(reject_error: move |cx| {
342 let promise = trusted_promise.root(cx);
343 promise.reject_error(cx, error);
344 }));
345 }
346
347 fn resolve_promise_with_encapsulated_key(
351 &self,
352 promise: &RootedPromise,
353 encapsulated_key: EncapsulatedKey,
354 ) {
355 let trusted_promise = TrustedPromise::from(promise);
356 self.global().task_manager().crypto_task_source().queue(
357 task!(resolve_encapsulated_key: move |cx| {
358 let promise = trusted_promise.root(cx);
359 promise.resolve_native(cx, &encapsulated_key);
360 }),
361 );
362 }
363
364 fn resolve_promise_with_encapsulated_bits(
368 &self,
369 promise: &RootedPromise,
370 encapsulated_bits: EncapsulatedBits,
371 ) {
372 let trusted_promise = TrustedPromise::from(promise);
373 self.global().task_manager().crypto_task_source().queue(
374 task!(resolve_encapsulated_bits: move |cx| {
375 let promise = trusted_promise.root(cx);
376 promise.resolve_native(cx, &encapsulated_bits);
377 }),
378 );
379 }
380}
381
382impl SubtleCryptoMethods<crate::DomTypeHolder> for SubtleCrypto {
383 fn Encrypt(
385 &self,
386 cx: &mut CurrentRealm,
387 algorithm: AlgorithmIdentifier,
388 key: &CryptoKey,
389 data: ArrayBufferViewOrArrayBuffer,
390 ) -> RootedPromise {
391 let normalized_algorithm = match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
399 Ok(normalized_algorithm) => normalized_algorithm,
400 Err(error) => {
401 let promise = Promise::new_in_realm_rooted(cx);
402 promise.reject_error(cx, error);
403 return promise;
404 },
405 };
406
407 let data = Zeroizing::new(get_buffer_source_copy((&data).into()));
410
411 let promise = Promise::new_in_realm_rooted(cx);
414
415 let this = Trusted::new(self);
417 let trusted_promise = TrustedPromise::from(&promise);
418 let trusted_key = Trusted::new(key);
419 self.global()
420 .task_manager()
421 .dom_manipulation_task_source()
422 .queue(task!(encrypt: move |cx| {
423 let subtle = this.root();
424 let promise = &trusted_promise.root(cx);
425 let key = trusted_key.root();
426
427 if normalized_algorithm.name() != key.algorithm().name() {
435 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Algorithm's name does not equal key algorithm name".into())));
436 return;
437 }
438
439 if !key.usages().contains(&KeyUsage::Encrypt) {
442 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'encrypt' entry".into())));
443 return;
444 }
445
446 let ciphertext = match normalized_algorithm.encrypt(&key, &data) {
450 Ok(ciphertext) => ciphertext,
451 Err(error) => {
452 subtle.reject_promise_with_error(promise, error);
453 return;
454 },
455 };
456
457 subtle.resolve_promise_with_data(promise, ciphertext.into());
463 }));
464 promise
465 }
466
467 fn Decrypt(
469 &self,
470 cx: &mut CurrentRealm,
471 algorithm: AlgorithmIdentifier,
472 key: &CryptoKey,
473 data: ArrayBufferViewOrArrayBuffer,
474 ) -> RootedPromise {
475 let normalized_algorithm = match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
483 Ok(normalized_algorithm) => normalized_algorithm,
484 Err(error) => {
485 let promise = Promise::new_in_realm_rooted(cx);
486 promise.reject_error(cx, error);
487 return promise;
488 },
489 };
490
491 let data = get_buffer_source_copy((&data).into());
494
495 let promise = Promise::new_in_realm_rooted(cx);
498
499 let this = Trusted::new(self);
501 let trusted_promise = TrustedPromise::from(&promise);
502 let trusted_key = Trusted::new(key);
503 self.global()
504 .task_manager()
505 .dom_manipulation_task_source()
506 .queue(task!(decrypt: move |cx| {
507 let subtle = this.root();
508 let promise = &trusted_promise.root(cx);
509 let key = trusted_key.root();
510
511 if normalized_algorithm.name() != key.algorithm().name() {
519 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
520 return;
521 }
522
523 if !key.usages().contains(&KeyUsage::Decrypt) {
526 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'decrypt' entry".into())));
527 return;
528 }
529
530 let plaintext = match normalized_algorithm.decrypt(&key, &data) {
534 Ok(plaintext) => Zeroizing::new(plaintext),
535 Err(error) => {
536 subtle.reject_promise_with_error(promise, error);
537 return;
538 },
539 };
540
541 subtle.resolve_promise_with_data(promise, plaintext);
547 }));
548 promise
549 }
550
551 fn Sign(
553 &self,
554 cx: &mut CurrentRealm,
555 algorithm: AlgorithmIdentifier,
556 key: &CryptoKey,
557 data: ArrayBufferViewOrArrayBuffer,
558 ) -> RootedPromise {
559 let normalized_algorithm = match normalize_algorithm::<SignOperation>(cx, &algorithm) {
567 Ok(normalized_algorithm) => normalized_algorithm,
568 Err(error) => {
569 let promise = Promise::new_in_realm_rooted(cx);
570 promise.reject_error(cx, error);
571 return promise;
572 },
573 };
574
575 let data = get_buffer_source_copy((&data).into());
578
579 let promise = Promise::new_in_realm_rooted(cx);
582
583 let this = Trusted::new(self);
585 let trusted_promise = TrustedPromise::from(&promise);
586 let trusted_key = Trusted::new(key);
587 self.global()
588 .task_manager()
589 .dom_manipulation_task_source()
590 .queue(task!(sign: move |cx| {
591 let subtle = this.root();
592 let promise = &trusted_promise.root(cx);
593 let key = trusted_key.root();
594
595 if normalized_algorithm.name() != key.algorithm().name() {
603 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
604 return;
605 }
606
607 if !key.usages().contains(&KeyUsage::Sign) {
610 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'sign' entry".into())));
611 return;
612 }
613
614 let signature = match normalized_algorithm.sign(&key, &data) {
617 Ok(signature) => signature,
618 Err(error) => {
619 subtle.reject_promise_with_error(promise, error);
620 return;
621 },
622 };
623
624 subtle.resolve_promise_with_data(promise, signature.into());
630 }));
631 promise
632 }
633
634 fn Verify(
636 &self,
637 cx: &mut CurrentRealm,
638 algorithm: AlgorithmIdentifier,
639 key: &CryptoKey,
640 signature: ArrayBufferViewOrArrayBuffer,
641 data: ArrayBufferViewOrArrayBuffer,
642 ) -> RootedPromise {
643 let normalized_algorithm = match normalize_algorithm::<VerifyOperation>(cx, &algorithm) {
651 Ok(algorithm) => algorithm,
652 Err(error) => {
653 let promise = Promise::new_in_realm_rooted(cx);
654 promise.reject_error(cx, error);
655 return promise;
656 },
657 };
658
659 let signature = get_buffer_source_copy((&signature).into());
662
663 let data = get_buffer_source_copy((&data).into());
666
667 let promise = Promise::new_in_realm_rooted(cx);
670
671 let this = Trusted::new(self);
673 let trusted_promise = TrustedPromise::from(&promise);
674 let trusted_key = Trusted::new(key);
675 self.global()
676 .task_manager()
677 .dom_manipulation_task_source()
678 .queue(task!(sign: move |cx| {
679 let subtle = this.root();
680 let promise = &trusted_promise.root(cx);
681 let key = trusted_key.root();
682
683 if normalized_algorithm.name() != key.algorithm().name() {
691 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal key algorithm name".into())));
692 return;
693 }
694
695 if !key.usages().contains(&KeyUsage::Verify) {
698 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'verify' entry".into())));
699 return;
700 }
701
702 let result = match normalized_algorithm.verify(&key, &data, &signature) {
706 Ok(result) => result,
707 Err(error) => {
708 subtle.reject_promise_with_error(promise, error);
709 return;
710 },
711 };
712
713 subtle.resolve_promise_with_bool(promise, result);
717 }));
718 promise
719 }
720
721 fn Digest(
723 &self,
724 cx: &mut CurrentRealm,
725 algorithm: AlgorithmIdentifier,
726 data: ArrayBufferViewOrArrayBuffer,
727 ) -> RootedPromise {
728 let normalized_algorithm = match normalize_algorithm::<DigestOperation>(cx, &algorithm) {
735 Ok(normalized_algorithm) => normalized_algorithm,
736 Err(error) => {
737 let promise = Promise::new_in_realm_rooted(cx);
738 promise.reject_error(cx, error);
739 return promise;
740 },
741 };
742
743 let data = get_buffer_source_copy((&data).into());
746
747 let promise = Promise::new_in_realm_rooted(cx);
750
751 let this = Trusted::new(self);
753 let trusted_promise = TrustedPromise::from(&promise);
754 self.global()
755 .task_manager()
756 .dom_manipulation_task_source()
757 .queue(task!(digest_: move |cx| {
758 let subtle = this.root();
759 let promise = &trusted_promise.root(cx);
760
761 let digest = match normalized_algorithm.digest(&data) {
768 Ok(digest) => digest,
769 Err(error) => {
770 subtle.reject_promise_with_error(promise, error);
771 return;
772 }
773 };
774
775 subtle.resolve_promise_with_data(promise, digest.into());
781 }));
782 promise
783 }
784
785 fn GenerateKey(
787 &self,
788 cx: &mut CurrentRealm,
789 algorithm: AlgorithmIdentifier,
790 extractable: bool,
791 key_usages: Vec<KeyUsage>,
792 ) -> RootedPromise {
793 let promise = Promise::new_in_realm_rooted(cx);
800 let normalized_algorithm = match normalize_algorithm::<GenerateKeyOperation>(cx, &algorithm)
801 {
802 Ok(normalized_algorithm) => normalized_algorithm,
803 Err(error) => {
804 promise.reject_error(cx, error);
805 return promise;
806 },
807 };
808
809 let trusted_subtle = Trusted::new(self);
815 let trusted_promise = TrustedPromise::from(&promise);
816 self.global()
817 .task_manager()
818 .dom_manipulation_task_source()
819 .queue(task!(generate_key: move |cx| {
820 let subtle = trusted_subtle.root();
821 let promise = &trusted_promise.root(cx);
822
823 let result = match normalized_algorithm.generate_key(
830 cx,
831 &subtle.global(),
832 extractable,
833 key_usages,
834 ) {
835 Ok(result) => result,
836 Err(error) => {
837 subtle.reject_promise_with_error(promise, error);
838 return;
839 }
840 };
841
842 match &result {
850 CryptoKeyOrCryptoKeyPair::CryptoKey(crpyto_key) => {
851 if matches!(crpyto_key.Type(), KeyType::Secret | KeyType::Private)
852 && crpyto_key.usages().is_empty()
853 {
854 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Crypto key usages is empty".into())));
855 return;
856 }
857 },
858 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(crypto_key_pair) => {
859 if crypto_key_pair
860 .privateKey
861 .as_ref()
862 .is_none_or(|private_key| private_key.usages().is_empty())
863 {
864 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Private key usages is an empty sequence".into())));
865 return;
866 }
867 }
868 };
869
870 match result {
876 CryptoKeyOrCryptoKeyPair::CryptoKey(key) => {
877 subtle.resolve_promise_with_key(promise, &key);
878 },
879 CryptoKeyOrCryptoKeyPair::CryptoKeyPair(key_pair) => {
880 subtle.resolve_promise_with_key_pair(promise, key_pair);
881 },
882 }
883 }));
884
885 promise
886 }
887
888 fn DeriveKey(
890 &self,
891 cx: &mut CurrentRealm,
892 algorithm: AlgorithmIdentifier,
893 base_key: &CryptoKey,
894 derived_key_type: AlgorithmIdentifier,
895 extractable: bool,
896 usages: Vec<KeyUsage>,
897 ) -> RootedPromise {
898 let promise = Promise::new_in_realm_rooted(cx);
907 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
908 {
909 Ok(normalized_algorithm) => normalized_algorithm,
910 Err(error) => {
911 promise.reject_error(cx, error);
912 return promise;
913 },
914 };
915
916 let normalized_derived_key_algorithm_import =
921 match normalize_algorithm::<ImportKeyOperation>(cx, &derived_key_type) {
922 Ok(normalized_algorithm) => normalized_algorithm,
923 Err(error) => {
924 promise.reject_error(cx, error);
925 return promise;
926 },
927 };
928
929 let normalized_derived_key_algorithm_length =
934 match normalize_algorithm::<GetKeyLengthOperation>(cx, &derived_key_type) {
935 Ok(normalized_algorithm) => normalized_algorithm,
936 Err(error) => {
937 promise.reject_error(cx, error);
938 return promise;
939 },
940 };
941
942 let trusted_subtle = Trusted::new(self);
948 let trusted_base_key = Trusted::new(base_key);
949 let trusted_promise = TrustedPromise::from(&promise);
950 self.global().task_manager().dom_manipulation_task_source().queue(
951 task!(derive_key: move |cx| {
952 let subtle = trusted_subtle.root();
953 let base_key = trusted_base_key.root();
954 let promise = &trusted_promise.root(cx);
955
956 if normalized_algorithm.name() != base_key.algorithm().name() {
964 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
965 return;
966 }
967
968 if !base_key.usages().contains(&KeyUsage::DeriveKey) {
971 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveKey' entry".into())));
972 return;
973 }
974
975 let length = match normalized_derived_key_algorithm_length.get_key_length() {
978 Ok(length) => length,
979 Err(error) => {
980 subtle.reject_promise_with_error(promise, error);
981 return;
982 }
983 };
984
985 let secret = match normalized_algorithm.derive_bits(&base_key, length) {
988 Ok(secret) => Zeroizing::new(secret),
989 Err(error) => {
990 subtle.reject_promise_with_error(promise, error);
991 return;
992 }
993 };
994
995 let result = match normalized_derived_key_algorithm_import.import_key(
1001 cx,
1002 &subtle.global(),
1003 KeyFormat::Raw_secret,
1004 &secret,
1005 extractable,
1006 usages.clone(),
1007 ) {
1008 Ok(algorithm) => algorithm,
1009 Err(error) => {
1010 subtle.reject_promise_with_error(promise, error);
1011 return;
1012 },
1013 };
1014
1015 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1018 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1019 return;
1020 }
1021
1022 subtle.resolve_promise_with_key(promise, &result);
1033 }),
1034 );
1035 promise
1036 }
1037
1038 fn DeriveBits(
1040 &self,
1041 cx: &mut CurrentRealm,
1042 algorithm: AlgorithmIdentifier,
1043 base_key: &CryptoKey,
1044 length: Option<u32>,
1045 ) -> RootedPromise {
1046 let promise = Promise::new_in_realm_rooted(cx);
1054 let normalized_algorithm = match normalize_algorithm::<DeriveBitsOperation>(cx, &algorithm)
1055 {
1056 Ok(normalized_algorithm) => normalized_algorithm,
1057 Err(error) => {
1058 promise.reject_error(cx, error);
1059 return promise;
1060 },
1061 };
1062
1063 let trsuted_subtle = Trusted::new(self);
1069 let trusted_base_key = Trusted::new(base_key);
1070 let trusted_promise = TrustedPromise::from(&promise);
1071 self.global()
1072 .task_manager()
1073 .dom_manipulation_task_source()
1074 .queue(task!(import_key: move |cx| {
1075 let subtle = trsuted_subtle.root();
1076 let base_key = trusted_base_key.root();
1077 let promise = &trusted_promise.root(cx);
1078
1079 if normalized_algorithm.name() != base_key.algorithm().name() {
1087 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of base key algorithm".into())));
1088 return;
1089 }
1090
1091 if !base_key.usages().contains(&KeyUsage::DeriveBits) {
1094 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key usages does not contain 'deriveBits' entry".into())));
1095 return;
1096 }
1097
1098 let bits = match normalized_algorithm.derive_bits(&base_key, length) {
1101 Ok(bits) => Zeroizing::new(bits),
1102 Err(error) => {
1103 subtle.reject_promise_with_error(promise, error);
1104 return;
1105 }
1106 };
1107
1108 subtle.resolve_promise_with_data(promise, bits);
1114 }));
1115 promise
1116 }
1117
1118 fn ImportKey(
1120 &self,
1121 cx: &mut CurrentRealm,
1122 format: KeyFormat,
1123 key_data: ArrayBufferViewOrArrayBufferOrJsonWebKey,
1124 algorithm: AlgorithmIdentifier,
1125 extractable: bool,
1126 key_usages: Vec<KeyUsage>,
1127 ) -> RootedPromise {
1128 let normalized_algorithm = match normalize_algorithm::<ImportKeyOperation>(cx, &algorithm) {
1135 Ok(algorithm) => algorithm,
1136 Err(error) => {
1137 let promise = Promise::new_in_realm_rooted(cx);
1138 promise.reject_error(cx, error);
1139 return promise;
1140 },
1141 };
1142
1143 let key_data = match format {
1145 KeyFormat::Jwk => {
1147 match key_data {
1148 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(_) |
1149 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(_) => {
1150 let promise = Promise::new_in_realm_rooted(cx);
1153 promise.reject_error(
1154 cx,
1155 Error::Type(c"The keyData type does not match the format".to_owned()),
1156 );
1157 return promise;
1158 },
1159
1160 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(jwk) => {
1161 match jwk.stringify(cx) {
1169 Ok(stringified) => Zeroizing::new(stringified.as_bytes().to_vec()),
1170 Err(error) => {
1171 let promise = Promise::new_in_realm_rooted(cx);
1172 promise.reject_error(cx, error);
1173 return promise;
1174 },
1175 }
1176 },
1177 }
1178 },
1179 _ => {
1181 match &key_data {
1182 ArrayBufferViewOrArrayBufferOrJsonWebKey::JsonWebKey(_) => {
1185 let promise = Promise::new_in_realm_rooted(cx);
1186 promise.reject_error(
1187 cx,
1188 Error::Type(c"The keyData type does not match the format".to_owned()),
1189 );
1190 return promise;
1191 },
1192
1193 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBufferView(view) => {
1196 Zeroizing::new(get_buffer_source_copy(view.into()))
1197 },
1198 ArrayBufferViewOrArrayBufferOrJsonWebKey::ArrayBuffer(buffer) => {
1199 Zeroizing::new(get_buffer_source_copy(buffer.into()))
1200 },
1201 }
1202 },
1203 };
1204
1205 let promise = Promise::new_in_realm_rooted(cx);
1208
1209 let this = Trusted::new(self);
1211 let trusted_promise = TrustedPromise::from(&promise);
1212 self.global()
1213 .task_manager()
1214 .dom_manipulation_task_source()
1215 .queue(task!(import_key: move |cx| {
1216 let subtle = this.root();
1217 let promise = &trusted_promise.root(cx);
1218
1219 let result = match normalized_algorithm.import_key(
1227 cx,
1228 &subtle.global(),
1229 format,
1230 &key_data,
1231 extractable,
1232 key_usages.clone(),
1233 ) {
1234 Ok(key) => key,
1235 Err(error) => {
1236 subtle.reject_promise_with_error(promise, error);
1237 return;
1238 },
1239 };
1240
1241 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && key_usages.is_empty() {
1244 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1245 return;
1246 }
1247
1248 subtle.resolve_promise_with_key(promise, &result);
1259 }));
1260
1261 promise
1262 }
1263
1264 fn ExportKey(
1266 &self,
1267 cx: &mut CurrentRealm,
1268 format: KeyFormat,
1269 key: &CryptoKey,
1270 ) -> RootedPromise {
1271 let promise = Promise::new_in_realm_rooted(cx);
1278
1279 let trusted_subtle = Trusted::new(self);
1281 let trusted_promise = TrustedPromise::from(&promise);
1282 let trusted_key = Trusted::new(key);
1283 self.global()
1284 .task_manager()
1285 .dom_manipulation_task_source()
1286 .queue(task!(export_key: move |cx| {
1287 let subtle = trusted_subtle.root();
1288 let promise = &trusted_promise.root(cx);
1289 let key = trusted_key.root();
1290
1291 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1302 cx,
1303 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1304 ) {
1305 Ok(normalized_algorithm) => normalized_algorithm,
1306 Err(error) => {
1307 subtle.reject_promise_with_error(promise, error);
1308 return;
1309 },
1310 };
1311
1312 if !key.Extractable() {
1315 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key is not extractable".into())));
1316 return;
1317 }
1318
1319 let result = match export_key_algorithm.export_key(format, &key) {
1322 Ok(exported_key) => exported_key,
1323 Err(error) => {
1324 subtle.reject_promise_with_error(promise, error);
1325 return;
1326 },
1327 };
1328
1329 match result {
1342 ExportedKey::Bytes(bytes) => {
1343 subtle.resolve_promise_with_data(promise, bytes);
1344 },
1345 ExportedKey::Jwk(jwk) => {
1346 subtle.resolve_promise_with_jwk(cx, promise, jwk);
1347 },
1348 }
1349 }));
1350 promise
1351 }
1352
1353 fn WrapKey(
1355 &self,
1356 cx: &mut CurrentRealm,
1357 format: KeyFormat,
1358 key: &CryptoKey,
1359 wrapping_key: &CryptoKey,
1360 algorithm: AlgorithmIdentifier,
1361 ) -> RootedPromise {
1362 enum WrapKeyAlgorithmOrEncryptAlgorithm {
1372 WrapKeyAlgorithm(WrapKeyAlgorithm),
1373 EncryptAlgorithm(EncryptAlgorithm),
1374 }
1375 let normalized_algorithm = if let Ok(algorithm) =
1376 normalize_algorithm::<WrapKeyOperation>(cx, &algorithm)
1377 {
1378 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm)
1379 } else {
1380 match normalize_algorithm::<EncryptOperation>(cx, &algorithm) {
1381 Ok(algorithm) => WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm),
1382 Err(error) => {
1383 let promise = Promise::new_in_realm_rooted(cx);
1384 promise.reject_error(cx, error);
1385 return promise;
1386 },
1387 }
1388 };
1389
1390 let promise = Promise::new_in_realm_rooted(cx);
1393
1394 let trusted_subtle = Trusted::new(self);
1396 let trusted_key = Trusted::new(key);
1397 let trusted_wrapping_key = Trusted::new(wrapping_key);
1398 let trusted_promise = TrustedPromise::from(&promise);
1399 self.global()
1400 .task_manager()
1401 .dom_manipulation_task_source()
1402 .queue(task!(wrap_key: move |cx| {
1403 let subtle = trusted_subtle.root();
1404 let key = trusted_key.root();
1405 let wrapping_key = trusted_wrapping_key.root();
1406 let promise = &trusted_promise.root(cx);
1407
1408 let normalized_algorithm_name = match &normalized_algorithm {
1416 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1417 algorithm.name()
1418 },
1419 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1420 algorithm.name()
1421 },
1422 };
1423 if normalized_algorithm_name != wrapping_key.algorithm().name() {
1424 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of wrapping key algorithm".into())));
1425 return;
1426 }
1427
1428 if !wrapping_key.usages().contains(&KeyUsage::WrapKey) {
1431 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Wrapping key usages does not contain 'wrapKey' entry".into())));
1432 return;
1433 }
1434
1435 let export_key_algorithm = match normalize_algorithm::<ExportKeyOperation>(
1441 cx,
1442 &AlgorithmIdentifier::String(DOMString::from(key.algorithm().name().as_str())),
1443 ) {
1444 Ok(normalized_algorithm) => normalized_algorithm,
1445 Err(error) => {
1446 subtle.reject_promise_with_error(promise, error);
1447 return;
1448 },
1449 };
1450
1451 if !key.Extractable() {
1454 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Key is not extractable".into())));
1455 return;
1456 }
1457
1458 let exported_key = match export_key_algorithm.export_key(format, &key) {
1461 Ok(exported_key) => exported_key,
1462 Err(error) => {
1463 subtle.reject_promise_with_error(promise, error);
1464 return;
1465 },
1466 };
1467
1468 let bytes = match exported_key {
1480 ExportedKey::Bytes(bytes) => bytes,
1481 ExportedKey::Jwk(jwk) => match jwk.stringify(cx) {
1482 Ok(stringified_jwk) => Zeroizing::new(stringified_jwk.as_bytes().to_vec()),
1483 Err(error) => {
1484 subtle.reject_promise_with_error(promise, error);
1485 return;
1486 },
1487 },
1488 };
1489
1490 let result = match normalized_algorithm {
1502 WrapKeyAlgorithmOrEncryptAlgorithm::WrapKeyAlgorithm(algorithm) => {
1503 algorithm.wrap_key(&wrapping_key, &bytes)
1504 },
1505 WrapKeyAlgorithmOrEncryptAlgorithm::EncryptAlgorithm(algorithm) => {
1506 algorithm.encrypt(&wrapping_key, &bytes)
1507 },
1508 };
1509 let result = match result {
1510 Ok(result) => result,
1511 Err(error) => {
1512 subtle.reject_promise_with_error(promise, error);
1513 return;
1514 },
1515 };
1516
1517 subtle.resolve_promise_with_data(promise, result.into());
1523 }));
1524 promise
1525 }
1526
1527 fn UnwrapKey(
1529 &self,
1530 cx: &mut CurrentRealm,
1531 format: KeyFormat,
1532 wrapped_key: ArrayBufferViewOrArrayBuffer,
1533 unwrapping_key: &CryptoKey,
1534 algorithm: AlgorithmIdentifier,
1535 unwrapped_key_algorithm: AlgorithmIdentifier,
1536 extractable: bool,
1537 usages: Vec<KeyUsage>,
1538 ) -> RootedPromise {
1539 enum UnwrapKeyAlgorithmOrDecryptAlgorithm {
1550 UnwrapKeyAlgorithm(UnwrapKeyAlgorithm),
1551 DecryptAlgorithm(DecryptAlgorithm),
1552 }
1553 let normalized_algorithm = if let Ok(algorithm) =
1554 normalize_algorithm::<UnwrapKeyOperation>(cx, &algorithm)
1555 {
1556 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm)
1557 } else {
1558 match normalize_algorithm::<DecryptOperation>(cx, &algorithm) {
1559 Ok(algorithm) => UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm),
1560 Err(error) => {
1561 let promise = Promise::new_in_realm_rooted(cx);
1562 promise.reject_error(cx, error);
1563 return promise;
1564 },
1565 }
1566 };
1567
1568 let normalized_key_algorithm =
1572 match normalize_algorithm::<ImportKeyOperation>(cx, &unwrapped_key_algorithm) {
1573 Ok(algorithm) => algorithm,
1574 Err(error) => {
1575 let promise = Promise::new_in_realm_rooted(cx);
1576 promise.reject_error(cx, error);
1577 return promise;
1578 },
1579 };
1580
1581 let wrapped_key = get_buffer_source_copy((&wrapped_key).into());
1584
1585 let promise = Promise::new_in_realm_rooted(cx);
1588
1589 let trusted_subtle = Trusted::new(self);
1591 let trusted_unwrapping_key = Trusted::new(unwrapping_key);
1592 let trusted_promise = TrustedPromise::from(&promise);
1593 self.global().task_manager().dom_manipulation_task_source().queue(
1594 task!(unwrap_key: move |cx| {
1595 let subtle = trusted_subtle.root();
1596 let unwrapping_key = trusted_unwrapping_key.root();
1597 let promise = &trusted_promise.root(cx);
1598
1599 let normalized_algorithm_name = match &normalized_algorithm {
1607 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1608 algorithm.name()
1609 },
1610 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1611 algorithm.name()
1612 },
1613 };
1614 if normalized_algorithm_name != unwrapping_key.algorithm().name() {
1615 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Normalized algorithm name does not equal name of unwrapping key algorithm".into())));
1616 return;
1617 }
1618
1619 if !unwrapping_key.usages().contains(&KeyUsage::UnwrapKey) {
1622 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some("Unwrapping key usages does not contain 'unwrapKey' entry".into())));
1623 return;
1624 }
1625
1626 let bytes = match normalized_algorithm {
1638 UnwrapKeyAlgorithmOrDecryptAlgorithm::UnwrapKeyAlgorithm(algorithm) => {
1639 algorithm.unwrap_key(&unwrapping_key, &wrapped_key)
1640 },
1641 UnwrapKeyAlgorithmOrDecryptAlgorithm::DecryptAlgorithm(algorithm) => {
1642 algorithm.decrypt(&unwrapping_key, &wrapped_key)
1643 },
1644 };
1645 let bytes = match bytes {
1646 Ok(bytes) => Zeroizing::new(bytes),
1647 Err(error) => {
1648 subtle.reject_promise_with_error(promise, error);
1649 return;
1650 },
1651 };
1652
1653 if format == KeyFormat::Jwk
1664 && let Err(error) = JsonWebKey::parse(cx, &bytes) {
1665 subtle.reject_promise_with_error(promise, error);
1666 return;
1667 }
1668 let key = bytes;
1669
1670 let result = match normalized_key_algorithm.import_key(
1674 cx,
1675 &subtle.global(),
1676 format,
1677 &key,
1678 extractable,
1679 usages.clone(),
1680 ) {
1681 Ok(result) => result,
1682 Err(error) => {
1683 subtle.reject_promise_with_error(promise, error);
1684 return;
1685 },
1686 };
1687
1688 if matches!(result.Type(), KeyType::Secret | KeyType::Private) && usages.is_empty() {
1691 subtle.reject_promise_with_error(promise, Error::Syntax(Some("Key usages is empty".into())));
1692 return;
1693 }
1694
1695 subtle.resolve_promise_with_key(promise, &result);
1706 }),
1707 );
1708 promise
1709 }
1710
1711 fn EncapsulateKey(
1713 &self,
1714 cx: &mut CurrentRealm,
1715 encapsulation_algorithm: AlgorithmIdentifier,
1716 encapsulation_key: &CryptoKey,
1717 shared_key_algorithm: AlgorithmIdentifier,
1718 extractable: bool,
1719 usages: Vec<KeyUsage>,
1720 ) -> RootedPromise {
1721 let promise = Promise::new_in_realm_rooted(cx);
1731 let normalized_encapsulation_algorithm =
1732 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1733 Ok(algorithm) => algorithm,
1734 Err(error) => {
1735 promise.reject_error(cx, error);
1736 return promise;
1737 },
1738 };
1739
1740 let normalized_shared_key_algorithm =
1745 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1746 Ok(algorithm) => algorithm,
1747 Err(error) => {
1748 promise.reject_error(cx, error);
1749 return promise;
1750 },
1751 };
1752
1753 let trusted_subtle = Trusted::new(self);
1759 let trusted_encapsulated_key = Trusted::new(encapsulation_key);
1760 let trusted_promise = TrustedPromise::from(&promise);
1761 self.global().task_manager().dom_manipulation_task_source().queue(
1762 task!(encapsulate_keys: move |cx| {
1763 let subtle = trusted_subtle.root();
1764 let encapsulation_key = trusted_encapsulated_key.root();
1765 let promise = &trusted_promise.root(cx);
1766
1767 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1775 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1776 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1777 normalizedEncapsulationAlgorithm".to_string(),
1778 )));
1779 return;
1780 }
1781
1782 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateKey) {
1785 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1786 "[[usages]] internal slot of encapsulationKey does not contain an \
1787 entry that is \"encapsulateBits\"".to_string(),
1788 )));
1789 return;
1790 }
1791
1792 let encapsulated_bits_result =
1798 normalized_encapsulation_algorithm.encapsulate(&encapsulation_key);
1799 let encapsulated_bits = match encapsulated_bits_result {
1800 Ok(encapsulated_bits) => encapsulated_bits,
1801 Err(error) => {
1802 subtle.reject_promise_with_error(promise, error);
1803 return;
1804 },
1805 };
1806
1807 let encapsulated_shared_key = match &encapsulated_bits.shared_key {
1816 Some(shared_key) => shared_key,
1817 None => {
1818 subtle.reject_promise_with_error(promise, Error::Operation(Some(
1819 "Shared key is missing in the result of the encapsulate operation"
1820 .to_string())));
1821 return;
1822 },
1823 };
1824 let shared_key_result = normalized_shared_key_algorithm.import_key(
1825 cx,
1826 &subtle.global(),
1827 KeyFormat::Raw_secret,
1828 encapsulated_shared_key,
1829 extractable,
1830 usages.clone(),
1831 );
1832 let shared_key = match shared_key_result {
1833 Ok(shared_key) => shared_key,
1834 Err(error) => {
1835 subtle.reject_promise_with_error(promise, error);
1836 return;
1837 },
1838 };
1839
1840 let encapsulated_key = EncapsulatedKey {
1843 shared_key: Some(Trusted::new(&shared_key)),
1844 ciphertext:encapsulated_bits.ciphertext,
1845 };
1846
1847 subtle.resolve_promise_with_encapsulated_key(promise, encapsulated_key);
1853 })
1854 );
1855 promise
1856 }
1857
1858 fn EncapsulateBits(
1860 &self,
1861 cx: &mut CurrentRealm,
1862 encapsulation_algorithm: AlgorithmIdentifier,
1863 encapsulation_key: &CryptoKey,
1864 ) -> RootedPromise {
1865 let promise = Promise::new_in_realm_rooted(cx);
1873 let normalized_encapsulation_algorithm =
1874 match normalize_algorithm::<EncapsulateOperation>(cx, &encapsulation_algorithm) {
1875 Ok(algorithm) => algorithm,
1876 Err(error) => {
1877 promise.reject_error(cx, error);
1878 return promise;
1879 },
1880 };
1881
1882 let trusted_subtle = Trusted::new(self);
1888 let trusted_encapsulation_key = Trusted::new(encapsulation_key);
1889 let trusted_promise = TrustedPromise::from(&promise);
1890 self.global().task_manager().dom_manipulation_task_source().queue(
1891 task!(derive_key: move |cx| {
1892 let subtle = trusted_subtle.root();
1893 let encapsulation_key = trusted_encapsulation_key.root();
1894 let promise = &trusted_promise.root(cx);
1895
1896 if normalized_encapsulation_algorithm.name() != encapsulation_key.algorithm().name() {
1904 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1905 "[[algorithm]] internal slot of encapsulationKey is not equal to \
1906 normalizedEncapsulationAlgorithm".to_string(),
1907 )));
1908 return;
1909 }
1910
1911 if !encapsulation_key.usages().contains(&KeyUsage::EncapsulateBits) {
1914 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
1915 "[[usages]] internal slot of encapsulationKey does not contain an \
1916 entry that is \"encapsulateBits\"".to_string(),
1917 )));
1918 return;
1919 }
1920
1921 let encapsulated_bits =
1927 match normalized_encapsulation_algorithm.encapsulate(&encapsulation_key) {
1928 Ok(encapsulated_bits) => encapsulated_bits,
1929 Err(error) => {
1930 subtle.reject_promise_with_error(promise, error);
1931 return;
1932 },
1933 };
1934
1935 subtle.resolve_promise_with_encapsulated_bits(promise, encapsulated_bits);
1941 }),
1942 );
1943 promise
1944 }
1945
1946 fn DecapsulateKey(
1948 &self,
1949 cx: &mut CurrentRealm,
1950 decapsulation_algorithm: AlgorithmIdentifier,
1951 decapsulation_key: &CryptoKey,
1952 ciphertext: ArrayBufferViewOrArrayBuffer,
1953 shared_key_algorithm: AlgorithmIdentifier,
1954 extractable: bool,
1955 usages: Vec<KeyUsage>,
1956 ) -> RootedPromise {
1957 let normalized_decapsulation_algorithm =
1967 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
1968 Ok(normalized_algorithm) => normalized_algorithm,
1969 Err(error) => {
1970 let promise = Promise::new_in_realm_rooted(cx);
1971 promise.reject_error(cx, error);
1972 return promise;
1973 },
1974 };
1975
1976 let normalized_shared_key_algorithm =
1981 match normalize_algorithm::<ImportKeyOperation>(cx, &shared_key_algorithm) {
1982 Ok(normalized_algorithm) => normalized_algorithm,
1983 Err(error) => {
1984 let promise = Promise::new_in_realm_rooted(cx);
1985 promise.reject_error(cx, error);
1986 return promise;
1987 },
1988 };
1989
1990 let ciphertext = get_buffer_source_copy((&ciphertext).into());
1993
1994 let promise = Promise::new_in_realm_rooted(cx);
1997
1998 let trusted_subtle = Trusted::new(self);
2000 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2001 let trusted_promise = TrustedPromise::from(&promise);
2002 self.global()
2003 .task_manager()
2004 .dom_manipulation_task_source()
2005 .queue(task!(decapsulate_key: move |cx| {
2006 let subtle = trusted_subtle.root();
2007 let promise = &trusted_promise.root(cx);
2008 let decapsulation_key = trusted_decapsulation_key.root();
2009
2010 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2018 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2019 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2020 normalizedDecapsulationAlgorithm".to_string()
2021 )));
2022 return;
2023 }
2024
2025 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateKey) {
2028 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2029 "[[usages]] internal slot of decapsulationKey does not contain an \
2030 entry that is \"decapsulateBits\"".to_string(),
2031 )));
2032 return;
2033 }
2034
2035 let decapsulated_bits_result =
2041 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2042 let decapsulated_bits = match decapsulated_bits_result {
2043 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2044 Err(error) => {
2045 subtle.reject_promise_with_error(promise, error);
2046 return;
2047 },
2048 };
2049
2050
2051 let shared_key_result = normalized_shared_key_algorithm.import_key(
2060 cx,
2061 &subtle.global(),
2062 KeyFormat::Raw_secret,
2063 &decapsulated_bits,
2064 extractable,
2065 usages.clone(),
2066 );
2067 let shared_key = match shared_key_result {
2068 Ok(shared_key) => shared_key,
2069 Err(error) => {
2070 subtle.reject_promise_with_error(promise, error);
2071 return;
2072 },
2073 };
2074
2075 subtle.resolve_promise_with_key(promise, &shared_key);
2081 }));
2082 promise
2083 }
2084
2085 fn DecapsulateBits(
2087 &self,
2088 cx: &mut CurrentRealm,
2089 decapsulation_algorithm: AlgorithmIdentifier,
2090 decapsulation_key: &CryptoKey,
2091 ciphertext: ArrayBufferViewOrArrayBuffer,
2092 ) -> RootedPromise {
2093 let normalized_decapsulation_algorithm =
2101 match normalize_algorithm::<DecapsulateOperation>(cx, &decapsulation_algorithm) {
2102 Ok(normalized_algorithm) => normalized_algorithm,
2103 Err(error) => {
2104 let promise = Promise::new_in_realm_rooted(cx);
2105 promise.reject_error(cx, error);
2106 return promise;
2107 },
2108 };
2109
2110 let ciphertext = get_buffer_source_copy((&ciphertext).into());
2113
2114 let promise = Promise::new_in_realm_rooted(cx);
2117
2118 let trusted_subtle = Trusted::new(self);
2120 let trusted_decapsulation_key = Trusted::new(decapsulation_key);
2121 let trusted_promise = TrustedPromise::from(&promise);
2122 self.global()
2123 .task_manager()
2124 .dom_manipulation_task_source()
2125 .queue(task!(decapsulate_bits: move |cx| {
2126 let subtle = trusted_subtle.root();
2127 let promise = &trusted_promise.root(cx);
2128 let decapsulation_key = trusted_decapsulation_key.root();
2129
2130 if normalized_decapsulation_algorithm.name() != decapsulation_key.algorithm().name() {
2138 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2139 "[[algorithm]] internal slot of decapsulationKey is not equal to \
2140 normalizedDecapsulationAlgorithm".to_string()
2141 )));
2142 return;
2143 }
2144
2145 if !decapsulation_key.usages().contains(&KeyUsage::DecapsulateBits) {
2148 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2149 "[[usages]] internal slot of decapsulationKey does not contain an \
2150 entry that is \"decapsulateBits\"".to_string(),
2151 )));
2152 return;
2153 }
2154
2155 let decapsulated_bits_result =
2161 normalized_decapsulation_algorithm.decapsulate(&decapsulation_key, &ciphertext);
2162 let decapsulated_bits = match decapsulated_bits_result {
2163 Ok(decapsulated_bits) => Zeroizing::new(decapsulated_bits),
2164 Err(error) => {
2165 subtle.reject_promise_with_error(promise, error);
2166 return;
2167 },
2168 };
2169
2170 subtle.resolve_promise_with_data(promise, decapsulated_bits);
2176 }));
2177 promise
2178 }
2179
2180 fn GetPublicKey(
2182 &self,
2183 cx: &mut CurrentRealm,
2184 key: &CryptoKey,
2185 usages: Vec<KeyUsage>,
2186 ) -> RootedPromise {
2187 let algorithm = key.algorithm();
2192
2193 let get_public_key_algorithm = match normalize_algorithm::<GetPublicKeyOperation>(
2200 cx,
2201 &AlgorithmIdentifier::String(DOMString::from_static(algorithm.name().as_str())),
2202 ) {
2203 Ok(normalized_algorithm) => normalized_algorithm,
2204 Err(error) => {
2205 let promise = Promise::new_in_realm_rooted(cx);
2206 promise.reject_error(cx, error);
2207 return promise;
2208 },
2209 };
2210
2211 let promise = Promise::new_in_realm_rooted(cx);
2214
2215 let trusted_subtle = Trusted::new(self);
2217 let trusted_promise = TrustedPromise::from(&promise);
2218 let trusted_key = Trusted::new(key);
2219 self.global()
2220 .task_manager()
2221 .dom_manipulation_task_source()
2222 .queue(task!(get_public_key: move |cx| {
2223 let subtle = trusted_subtle.root();
2224 let promise = &trusted_promise.root(cx);
2225 let key = trusted_key.root();
2226
2227 if key.Type() != KeyType::Private {
2234 subtle.reject_promise_with_error(promise, Error::InvalidAccess(Some(
2235 "[[type]] internal slot of key is not \"private\"".to_string()
2236 )));
2237 return;
2238 }
2239
2240 let result = match get_public_key_algorithm.get_public_key(
2254 cx,
2255 &subtle.global(),
2256 &key,
2257 key.algorithm(),
2258 usages.clone(),
2259 ) {
2260 Ok(public_key) => public_key,
2261 Err(error) => {
2262 subtle.reject_promise_with_error(promise, error);
2263 return;
2264 },
2265 };
2266
2267 subtle.resolve_promise_with_key(promise, &result);
2273 }));
2274 promise
2275 }
2276
2277 fn Supports(
2279 cx: &mut js::context::JSContext,
2280 _global: &GlobalScope,
2281 operation: DOMString,
2282 algorithm: AlgorithmIdentifier,
2283 length: Option<u32>,
2284 ) -> bool {
2285 let operation = &*operation.str();
2290 if !matches!(
2291 operation,
2292 "encrypt" |
2293 "decrypt" |
2294 "sign" |
2295 "verify" |
2296 "digest" |
2297 "generateKey" |
2298 "deriveKey" |
2299 "deriveBits" |
2300 "importKey" |
2301 "exportKey" |
2302 "wrapKey" |
2303 "unwrapKey" |
2304 "encapsulateKey" |
2305 "encapsulateBits" |
2306 "decapsulateKey" |
2307 "decapsulateBits" |
2308 "getPublicKey"
2309 ) {
2310 return false;
2311 }
2312
2313 check_support_for_algorithm(cx, operation, &algorithm, length)
2316 }
2317
2318 fn Supports_(
2320 cx: &mut js::context::JSContext,
2321 _global: &GlobalScope,
2322 operation: DOMString,
2323 algorithm: AlgorithmIdentifier,
2324 additional_algorithm: AlgorithmIdentifier,
2325 ) -> bool {
2326 let mut operation = &*operation.str();
2331 if !matches!(
2332 operation,
2333 "encrypt" |
2334 "decrypt" |
2335 "sign" |
2336 "verify" |
2337 "digest" |
2338 "generateKey" |
2339 "deriveKey" |
2340 "deriveBits" |
2341 "importKey" |
2342 "exportKey" |
2343 "wrapKey" |
2344 "unwrapKey" |
2345 "encapsulateKey" |
2346 "encapsulateBits" |
2347 "decapsulateKey" |
2348 "decapsulateBits" |
2349 "getPublicKey"
2350 ) {
2351 return false;
2352 }
2353
2354 if matches!(operation, "deriveKey" | "unwrapKey") &&
2362 !check_support_for_algorithm(cx, "importKey", &additional_algorithm, None)
2363 {
2364 return false;
2365 }
2366 if operation == "wrapKey" &&
2367 !check_support_for_algorithm(cx, "exportKey", &additional_algorithm, None)
2368 {
2369 return false;
2370 }
2371
2372 if matches!(operation, "encapsulateKey" | "decapsulateKey") {
2374 let Ok(normalized_algorithm) =
2378 normalize_algorithm::<GetSharedKeyLengthOperation>(cx, &algorithm)
2379 else {
2380 return false;
2381 };
2382
2383 let shared_key_length = normalized_algorithm.get_shared_key_length();
2386
2387 let Ok(normalized_additional_algorithm) =
2391 normalize_algorithm::<ImportKeyOperation>(cx, &additional_algorithm)
2392 else {
2393 return false;
2394 };
2395
2396 if !normalized_additional_algorithm.determine_support_from_operation_steps(None) {
2404 return false;
2405 }
2406
2407 if normalized_additional_algorithm.will_throw_for_key_data_length(shared_key_length) {
2411 return false;
2412 }
2413 }
2414
2415 let mut length = None;
2417
2418 if operation == "deriveKey" {
2420 if !check_support_for_algorithm(cx, "get key length", &additional_algorithm, None) {
2423 return false;
2424 }
2425
2426 let Ok(normalized_additional_algorithm) =
2429 normalize_algorithm::<GetKeyLengthOperation>(cx, &additional_algorithm)
2430 else {
2431 return false;
2432 };
2433
2434 match normalized_additional_algorithm.get_key_length() {
2437 Ok(key_length) => {
2438 length = key_length;
2439 },
2440 Err(_) => return false,
2441 };
2442
2443 operation = "deriveBits";
2445 }
2446
2447 check_support_for_algorithm(cx, operation, &algorithm, length)
2450 }
2451}
2452
2453pub(crate) fn check_support_for_algorithm(
2455 cx: &mut js::context::JSContext,
2456 mut operation: &str,
2457 algorithm: &AlgorithmIdentifier,
2458 length: Option<u32>,
2459) -> bool {
2460 if operation == "encapsulateKey" || operation == "encapsulateBits" {
2462 operation = "encapsulate";
2463 }
2464
2465 if operation == "decapsulateKey" || operation == "decapsulateBits" {
2467 operation = "decapsulate";
2468 }
2469
2470 if operation == "getPublicKey" {
2472 let Ok(normalized_algorithm) = normalize_algorithm::<ExportKeyOperation>(cx, algorithm)
2476 else {
2477 return false;
2478 };
2479
2480 return normalize_algorithm::<GetPublicKeyOperation>(
2487 cx,
2488 &AlgorithmIdentifier::String(DOMString::from_static(
2489 normalized_algorithm.name().as_str(),
2490 )),
2491 )
2492 .is_ok();
2493 }
2494
2495 match operation {
2506 "encrypt" => {
2507 normalize_and_determine_support::<EncryptOperation>(cx, operation, algorithm, length)
2508 },
2509 "decrypt" => {
2510 normalize_and_determine_support::<DecryptOperation>(cx, operation, algorithm, length)
2511 },
2512 "sign" => {
2513 normalize_and_determine_support::<SignOperation>(cx, operation, algorithm, length)
2514 },
2515 "verify" => {
2516 normalize_and_determine_support::<VerifyOperation>(cx, operation, algorithm, length)
2517 },
2518 "digest" => {
2519 normalize_and_determine_support::<DigestOperation>(cx, operation, algorithm, length)
2520 },
2521 "deriveBits" => {
2522 normalize_and_determine_support::<DeriveBitsOperation>(cx, operation, algorithm, length)
2523 },
2524 "wrapKey" => {
2525 normalize_and_determine_support::<WrapKeyOperation>(cx, operation, algorithm, length)
2526 },
2527 "unwrapKey" => {
2528 normalize_and_determine_support::<UnwrapKeyOperation>(cx, operation, algorithm, length)
2529 },
2530 "generateKey" => normalize_and_determine_support::<GenerateKeyOperation>(
2531 cx, operation, algorithm, length,
2532 ),
2533 "importKey" => {
2534 normalize_and_determine_support::<ImportKeyOperation>(cx, operation, algorithm, length)
2535 },
2536 "exportKey" => {
2537 normalize_and_determine_support::<ExportKeyOperation>(cx, operation, algorithm, length)
2538 },
2539 "get key length" => normalize_and_determine_support::<GetKeyLengthOperation>(
2540 cx, operation, algorithm, length,
2541 ),
2542 "encapsulate" => normalize_and_determine_support::<EncapsulateOperation>(
2543 cx, operation, algorithm, length,
2544 ),
2545 "decapsulate" => normalize_and_determine_support::<DecapsulateOperation>(
2546 cx, operation, algorithm, length,
2547 ),
2548 _ => false,
2549 }
2550}
2551
2552fn normalize_and_determine_support<T: Operation>(
2555 cx: &mut js::context::JSContext,
2556 op: &str,
2557 algorithm: &AlgorithmIdentifier,
2558 length: Option<u32>,
2559) -> bool {
2560 if let Ok(normalized_algorithm) = normalize_algorithm::<T>(cx, algorithm) {
2561 normalized_algorithm.determine_support_from_operation_steps(length)
2562 } else {
2563 match op {
2564 "wrapKey" => check_support_for_algorithm(cx, "encrypt", algorithm, length),
2565 "unwrapKey" => check_support_for_algorithm(cx, "decrypt", algorithm, length),
2566 _ => false,
2567 }
2568 }
2569}
2570
2571trait TryFromWithCxAndName<T>: Sized {
2573 type Error;
2574
2575 fn try_from_with_cx_and_name(
2576 value: T,
2577 cx: &mut js::context::JSContext,
2578 algorithm_name: CryptoAlgorithm,
2579 ) -> Result<Self, Self::Error>;
2580}
2581
2582trait TryIntoWithCxAndName<T>: Sized {
2584 type Error;
2585
2586 fn try_into_with_cx_and_name(
2587 self,
2588 cx: &mut js::context::JSContext,
2589 algorithm_name: CryptoAlgorithm,
2590 ) -> Result<T, Self::Error>;
2591}
2592
2593impl<T, U> TryIntoWithCxAndName<U> for T
2594where
2595 U: TryFromWithCxAndName<T>,
2596{
2597 type Error = U::Error;
2598
2599 fn try_into_with_cx_and_name(
2600 self,
2601 cx: &mut js::context::JSContext,
2602 algorithm_name: CryptoAlgorithm,
2603 ) -> Result<U, Self::Error> {
2604 U::try_from_with_cx_and_name(self, cx, algorithm_name)
2605 }
2606}
2607
2608#[derive(Clone, MallocSizeOf)]
2628struct Algorithm {
2629 name: CryptoAlgorithm,
2631}
2632
2633impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Algorithm {
2634 type Error = Error;
2635
2636 fn try_from_with_cx_and_name(
2637 _object: HandleObject<'a>,
2638 _cx: &mut js::context::JSContext,
2639 algorithm_name: CryptoAlgorithm,
2640 ) -> Result<Self, Self::Error> {
2641 Ok(Algorithm {
2642 name: algorithm_name,
2643 })
2644 }
2645}
2646
2647impl TryFrom<SerializableAlgorithm> for Algorithm {
2648 type Error = ();
2649
2650 fn try_from(value: SerializableAlgorithm) -> Result<Self, Self::Error> {
2651 Ok(Algorithm {
2652 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2653 })
2654 }
2655}
2656
2657impl From<&Algorithm> for SerializableAlgorithm {
2658 fn from(value: &Algorithm) -> Self {
2659 SerializableAlgorithm {
2660 name: value.name.as_str().into(),
2661 }
2662 }
2663}
2664
2665#[derive(Clone, MallocSizeOf)]
2667pub(crate) struct KeyAlgorithm {
2668 name: CryptoAlgorithm,
2670}
2671
2672impl ToJSValConvertible for KeyAlgorithm {
2673 #[expect(unsafe_code)]
2674 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
2675 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2676
2677 rooted!(&in(cx) let mut name_js = UndefinedValue());
2678 self.name.as_str().to_jsval(cx, name_js.handle_mut());
2679 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2680 .expect("Failed to set name property of KeyAlgorithm");
2681
2682 rval.set(ObjectOrNullValue(object.get()));
2683 }
2684}
2685
2686impl TryFrom<SerializableKeyAlgorithm> for KeyAlgorithm {
2687 type Error = ();
2688
2689 fn try_from(value: SerializableKeyAlgorithm) -> Result<Self, Self::Error> {
2690 Ok(KeyAlgorithm {
2691 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2692 })
2693 }
2694}
2695
2696impl From<&KeyAlgorithm> for SerializableKeyAlgorithm {
2697 fn from(value: &KeyAlgorithm) -> Self {
2698 SerializableKeyAlgorithm {
2699 name: value.name.as_str().into(),
2700 }
2701 }
2702}
2703
2704#[derive(Clone, MallocSizeOf)]
2706pub(crate) struct RsaHashedKeyGenParams {
2707 name: CryptoAlgorithm,
2709
2710 modulus_length: u32,
2712
2713 public_exponent: Vec<u8>,
2715
2716 hash: DigestAlgorithm,
2718}
2719
2720impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedKeyGenParams {
2721 type Error = Error;
2722
2723 fn try_from_with_cx_and_name(
2724 object: HandleObject,
2725 cx: &mut js::context::JSContext,
2726 algorithm_name: CryptoAlgorithm,
2727 ) -> Result<Self, Self::Error> {
2728 let hash = get_required_parameter(cx, object, c"hash", ())?;
2729
2730 Ok(RsaHashedKeyGenParams {
2731 name: algorithm_name,
2732 modulus_length: get_required_parameter(
2733 cx,
2734 object,
2735 c"modulusLength",
2736 ConversionBehavior::EnforceRange,
2737 )?,
2738 public_exponent: get_required_parameter_in_box::<HeapUint8Array>(
2739 cx,
2740 object,
2741 c"publicExponent",
2742 (),
2743 )?
2744 .to_vec()
2745 .unwrap_or_default(),
2746 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2747 })
2748 }
2749}
2750
2751impl RsaHashedKeyGenParams {
2752 fn validate_parameters(&self) -> Result<(), Error> {
2754 let modulus_length = self.modulus_length;
2756
2757 let public_exponent = &self.public_exponent;
2760
2761 let is_less_than_3 = |public_exponent: &[u8]| {
2764 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2765 byte_iterator.next().is_none_or(|byte| *byte < 3) && byte_iterator.count() == 0
2766 };
2767 let is_even =
2768 |public_exponent: &[u8]| public_exponent.last().is_none_or(|byte| byte % 2 == 0);
2769 let upper_bound_first_byte = (1u8 << (modulus_length % 8)).wrapping_sub(1);
2770 let upper_bound_length_in_bytes = modulus_length.div_ceil(8) as usize;
2771 let is_greater_than_upper_bound = |public_exponent: &[u8]| {
2772 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2773 byte_iterator
2774 .next()
2775 .is_some_and(|byte| *byte > upper_bound_first_byte) &&
2776 byte_iterator.count() + 1 >= upper_bound_length_in_bytes
2777 };
2778 let is_equal_to_upper_bound = |public_exponent: &[u8]| {
2779 let mut byte_iterator = public_exponent.iter().skip_while(|byte| **byte == 0);
2780 byte_iterator
2781 .next()
2782 .is_some_and(|byte| *byte == upper_bound_first_byte) &&
2783 byte_iterator.clone().all(|byte| *byte == 255) &&
2784 byte_iterator.count() + 1 == upper_bound_length_in_bytes
2785 };
2786 if modulus_length < 4 ||
2787 is_less_than_3(public_exponent) ||
2788 is_even(public_exponent) ||
2789 is_greater_than_upper_bound(public_exponent) ||
2790 is_equal_to_upper_bound(public_exponent)
2791 {
2792 return Err(Error::Operation(Some(
2793 "Invalid RsaHashedKeyGenParams".into(),
2794 )));
2795 }
2796
2797 Ok(())
2798 }
2799}
2800
2801#[derive(Clone, MallocSizeOf)]
2803pub(crate) struct RsaHashedKeyAlgorithm {
2804 name: CryptoAlgorithm,
2806
2807 modulus_length: u32,
2809
2810 public_exponent: Vec<u8>,
2812
2813 hash: DigestAlgorithm,
2815}
2816
2817impl ToJSValConvertible for RsaHashedKeyAlgorithm {
2818 #[expect(unsafe_code)]
2819 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
2820 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
2821
2822 rooted!(&in(cx) let mut name_js = UndefinedValue());
2823 self.name.as_str().to_jsval(cx, name_js.handle_mut());
2824 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
2825 .expect("Failed to set name property of RsaHashedKeyAlgorithm");
2826
2827 rooted!(&in(cx) let mut modulus_length_js = UndefinedValue());
2828 self.modulus_length
2829 .to_jsval(cx, modulus_length_js.handle_mut());
2830 set_dictionary_property(
2831 cx,
2832 object.handle(),
2833 c"modulusLength",
2834 modulus_length_js.handle(),
2835 )
2836 .expect("Failed to set modulusLength property of RsaHashedKeyAlgorithm");
2837
2838 rooted!(&in(cx) let mut public_exponent_js = UndefinedValue());
2839 rooted!(&in(cx) let mut public_exponent_js_object = ptr::null_mut::<JSObject>());
2840 let public_exponent = create_buffer_source::<ArrayBufferU8>(
2841 cx,
2842 &self.public_exponent,
2843 public_exponent_js_object.handle_mut(),
2844 )
2845 .expect("Failed to convert publicExponent to Uint8Array");
2846 public_exponent.to_jsval(cx, public_exponent_js.handle_mut());
2847 set_dictionary_property(
2848 cx,
2849 object.handle(),
2850 c"publicExponent",
2851 public_exponent_js.handle(),
2852 )
2853 .expect("Failed to set publicExponent property of RsaHashedKeyAlgorithm");
2854
2855 rooted!(&in(cx) let mut hash_js = UndefinedValue());
2856 let hash = KeyAlgorithm {
2857 name: self.hash.name(),
2858 };
2859 hash.to_jsval(cx, hash_js.handle_mut());
2860 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
2861 .expect("Failed to set hash property of RsaHashedKeyAlgorithm");
2862
2863 rval.set(ObjectOrNullValue(object.get()));
2864 }
2865}
2866
2867impl TryFrom<SerializableRsaHashedKeyAlgorithm> for RsaHashedKeyAlgorithm {
2868 type Error = ();
2869
2870 fn try_from(value: SerializableRsaHashedKeyAlgorithm) -> Result<Self, Self::Error> {
2871 Ok(RsaHashedKeyAlgorithm {
2872 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
2873 modulus_length: value.modulus_length,
2874 public_exponent: value.public_exponent,
2875 hash: value.hash.try_into()?,
2876 })
2877 }
2878}
2879
2880impl From<&RsaHashedKeyAlgorithm> for SerializableRsaHashedKeyAlgorithm {
2881 fn from(value: &RsaHashedKeyAlgorithm) -> Self {
2882 SerializableRsaHashedKeyAlgorithm {
2883 name: value.name.as_str().into(),
2884 modulus_length: value.modulus_length,
2885 public_exponent: value.public_exponent.clone(),
2886 hash: (&value.hash).into(),
2887 }
2888 }
2889}
2890
2891#[derive(Clone, MallocSizeOf)]
2893struct RsaHashedImportParams {
2894 name: CryptoAlgorithm,
2896
2897 hash: DigestAlgorithm,
2899}
2900
2901impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaHashedImportParams {
2902 type Error = Error;
2903
2904 fn try_from_with_cx_and_name(
2905 object: HandleObject,
2906 cx: &mut js::context::JSContext,
2907 algorithm_name: CryptoAlgorithm,
2908 ) -> Result<Self, Self::Error> {
2909 let hash = get_required_parameter(cx, object, c"hash", ())?;
2910
2911 Ok(RsaHashedImportParams {
2912 name: algorithm_name,
2913 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2914 })
2915 }
2916}
2917
2918#[derive(Clone, MallocSizeOf)]
2920struct RsaPssParams {
2921 name: CryptoAlgorithm,
2923
2924 salt_length: u32,
2926}
2927
2928impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaPssParams {
2929 type Error = Error;
2930
2931 fn try_from_with_cx_and_name(
2932 object: HandleObject,
2933 cx: &mut js::context::JSContext,
2934 algorithm_name: CryptoAlgorithm,
2935 ) -> Result<Self, Self::Error> {
2936 Ok(RsaPssParams {
2937 name: algorithm_name,
2938 salt_length: get_required_parameter(
2939 cx,
2940 object,
2941 c"saltLength",
2942 ConversionBehavior::EnforceRange,
2943 )?,
2944 })
2945 }
2946}
2947
2948#[derive(Clone, MallocSizeOf)]
2950struct RsaOaepParams {
2951 name: CryptoAlgorithm,
2953
2954 label: Option<Vec<u8>>,
2956}
2957
2958impl<'a> TryFromWithCxAndName<HandleObject<'a>> for RsaOaepParams {
2959 type Error = Error;
2960
2961 fn try_from_with_cx_and_name(
2962 object: HandleObject<'a>,
2963 cx: &mut js::context::JSContext,
2964 algorithm_name: CryptoAlgorithm,
2965 ) -> Result<Self, Self::Error> {
2966 Ok(RsaOaepParams {
2967 name: algorithm_name,
2968 label: get_optional_buffer_source(cx, object, c"label")?,
2969 })
2970 }
2971}
2972
2973#[derive(Clone, MallocSizeOf)]
2975struct EcdsaParams {
2976 name: CryptoAlgorithm,
2978
2979 hash: DigestAlgorithm,
2981}
2982
2983impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcdsaParams {
2984 type Error = Error;
2985
2986 fn try_from_with_cx_and_name(
2987 object: HandleObject<'a>,
2988 cx: &mut js::context::JSContext,
2989 algorithm_name: CryptoAlgorithm,
2990 ) -> Result<Self, Self::Error> {
2991 let hash = get_required_parameter(cx, object, c"hash", ())?;
2992
2993 Ok(EcdsaParams {
2994 name: algorithm_name,
2995 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
2996 })
2997 }
2998}
2999
3000#[derive(Clone, MallocSizeOf)]
3002struct EcKeyGenParams {
3003 name: CryptoAlgorithm,
3005
3006 named_curve: String,
3008}
3009
3010impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyGenParams {
3011 type Error = Error;
3012
3013 fn try_from_with_cx_and_name(
3014 object: HandleObject<'a>,
3015 cx: &mut js::context::JSContext,
3016 algorithm_name: CryptoAlgorithm,
3017 ) -> Result<Self, Self::Error> {
3018 Ok(EcKeyGenParams {
3019 name: algorithm_name,
3020 named_curve: String::from(get_required_parameter::<DOMString>(
3021 cx,
3022 object,
3023 c"namedCurve",
3024 StringificationBehavior::Default,
3025 )?),
3026 })
3027 }
3028}
3029
3030#[derive(Clone, MallocSizeOf)]
3032pub(crate) struct EcKeyAlgorithm {
3033 name: CryptoAlgorithm,
3035
3036 named_curve: String,
3038}
3039
3040impl ToJSValConvertible for EcKeyAlgorithm {
3041 #[expect(unsafe_code)]
3042 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3043 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3044
3045 rooted!(&in(cx) let mut name_js = UndefinedValue());
3046 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3047 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3048 .expect("Failed to set name property of EcKeyAlgorithm");
3049
3050 rooted!(&in(cx) let mut named_curve_js = UndefinedValue());
3051 self.named_curve.to_jsval(cx, named_curve_js.handle_mut());
3052 set_dictionary_property(cx, object.handle(), c"namedCurve", named_curve_js.handle())
3053 .expect("Failed to set namedCurve property of EcKeyAlgorithm");
3054
3055 rval.set(ObjectOrNullValue(object.get()));
3056 }
3057}
3058
3059impl TryFrom<SerializableEcKeyAlgorithm> for EcKeyAlgorithm {
3060 type Error = ();
3061
3062 fn try_from(value: SerializableEcKeyAlgorithm) -> Result<Self, Self::Error> {
3063 Ok(EcKeyAlgorithm {
3064 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3065 named_curve: value.named_curve,
3066 })
3067 }
3068}
3069
3070impl From<&EcKeyAlgorithm> for SerializableEcKeyAlgorithm {
3071 fn from(value: &EcKeyAlgorithm) -> Self {
3072 SerializableEcKeyAlgorithm {
3073 name: value.name.as_str().into(),
3074 named_curve: value.named_curve.clone(),
3075 }
3076 }
3077}
3078
3079#[derive(Clone, MallocSizeOf)]
3081struct EcKeyImportParams {
3082 name: CryptoAlgorithm,
3084
3085 named_curve: String,
3087}
3088
3089impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcKeyImportParams {
3090 type Error = Error;
3091
3092 fn try_from_with_cx_and_name(
3093 object: HandleObject<'a>,
3094 cx: &mut js::context::JSContext,
3095 algorithm_name: CryptoAlgorithm,
3096 ) -> Result<Self, Self::Error> {
3097 Ok(EcKeyImportParams {
3098 name: algorithm_name,
3099 named_curve: String::from(get_required_parameter::<DOMString>(
3100 cx,
3101 object,
3102 c"namedCurve",
3103 StringificationBehavior::Default,
3104 )?),
3105 })
3106 }
3107}
3108
3109#[derive(Clone, MallocSizeOf)]
3111struct EcdhKeyDeriveParams {
3112 name: CryptoAlgorithm,
3114
3115 public: Trusted<CryptoKey>,
3117}
3118
3119impl<'a> TryFromWithCxAndName<HandleObject<'a>> for EcdhKeyDeriveParams {
3120 type Error = Error;
3121
3122 fn try_from_with_cx_and_name(
3123 object: HandleObject<'a>,
3124 cx: &mut js::context::JSContext,
3125 algorithm_name: CryptoAlgorithm,
3126 ) -> Result<Self, Self::Error> {
3127 let public = get_required_parameter::<DomRoot<CryptoKey>>(cx, object, c"public", ())?;
3128
3129 Ok(EcdhKeyDeriveParams {
3130 name: algorithm_name,
3131 public: Trusted::new(&public),
3132 })
3133 }
3134}
3135
3136#[derive(Clone, MallocSizeOf)]
3138struct AesCtrParams {
3139 name: CryptoAlgorithm,
3141
3142 counter: Vec<u8>,
3144
3145 length: u8,
3147}
3148
3149impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCtrParams {
3150 type Error = Error;
3151
3152 fn try_from_with_cx_and_name(
3153 object: HandleObject<'a>,
3154 cx: &mut js::context::JSContext,
3155 algorithm_name: CryptoAlgorithm,
3156 ) -> Result<Self, Self::Error> {
3157 Ok(AesCtrParams {
3158 name: algorithm_name,
3159 counter: get_required_buffer_source(cx, object, c"counter")?,
3160 length: get_required_parameter(
3161 cx,
3162 object,
3163 c"length",
3164 ConversionBehavior::EnforceRange,
3165 )?,
3166 })
3167 }
3168}
3169
3170#[derive(Clone, MallocSizeOf)]
3172pub(crate) struct AesKeyAlgorithm {
3173 name: CryptoAlgorithm,
3175
3176 length: u16,
3178}
3179
3180impl ToJSValConvertible for AesKeyAlgorithm {
3181 #[expect(unsafe_code)]
3182 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3183 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3184
3185 rooted!(&in(cx) let mut name_js = UndefinedValue());
3186 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3187 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3188 .expect("Failed to set name property of AesKeyAlgorithm");
3189
3190 rooted!(&in(cx) let mut length_js = UndefinedValue());
3191 self.length.to_jsval(cx, length_js.handle_mut());
3192 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3193 .expect("Failed to set length property of AesKeyAlgorithm");
3194
3195 rval.set(ObjectOrNullValue(object.get()));
3196 }
3197}
3198
3199impl TryFrom<SerializableAesKeyAlgorithm> for AesKeyAlgorithm {
3200 type Error = ();
3201
3202 fn try_from(value: SerializableAesKeyAlgorithm) -> Result<Self, Self::Error> {
3203 Ok(AesKeyAlgorithm {
3204 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3205 length: value.length,
3206 })
3207 }
3208}
3209
3210impl From<&AesKeyAlgorithm> for SerializableAesKeyAlgorithm {
3211 fn from(value: &AesKeyAlgorithm) -> Self {
3212 SerializableAesKeyAlgorithm {
3213 name: value.name.as_str().into(),
3214 length: value.length,
3215 }
3216 }
3217}
3218
3219#[derive(Clone, MallocSizeOf)]
3221struct AesKeyGenParams {
3222 name: CryptoAlgorithm,
3224
3225 length: u16,
3227}
3228
3229impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesKeyGenParams {
3230 type Error = Error;
3231
3232 fn try_from_with_cx_and_name(
3233 object: HandleObject<'a>,
3234 cx: &mut js::context::JSContext,
3235 algorithm_name: CryptoAlgorithm,
3236 ) -> Result<Self, Self::Error> {
3237 Ok(AesKeyGenParams {
3238 name: algorithm_name,
3239 length: get_required_parameter(
3240 cx,
3241 object,
3242 c"length",
3243 ConversionBehavior::EnforceRange,
3244 )?,
3245 })
3246 }
3247}
3248
3249#[derive(Clone, MallocSizeOf)]
3251struct AesDerivedKeyParams {
3252 name: CryptoAlgorithm,
3254
3255 length: u16,
3257}
3258
3259impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesDerivedKeyParams {
3260 type Error = Error;
3261
3262 fn try_from_with_cx_and_name(
3263 object: HandleObject<'a>,
3264 cx: &mut js::context::JSContext,
3265 algorithm_name: CryptoAlgorithm,
3266 ) -> Result<Self, Self::Error> {
3267 Ok(AesDerivedKeyParams {
3268 name: algorithm_name,
3269 length: get_required_parameter(
3270 cx,
3271 object,
3272 c"length",
3273 ConversionBehavior::EnforceRange,
3274 )?,
3275 })
3276 }
3277}
3278
3279#[derive(Clone, MallocSizeOf)]
3281struct AesCbcParams {
3282 name: CryptoAlgorithm,
3284
3285 iv: Vec<u8>,
3287}
3288
3289impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesCbcParams {
3290 type Error = Error;
3291
3292 fn try_from_with_cx_and_name(
3293 object: HandleObject<'a>,
3294 cx: &mut js::context::JSContext,
3295 algorithm_name: CryptoAlgorithm,
3296 ) -> Result<Self, Self::Error> {
3297 Ok(AesCbcParams {
3298 name: algorithm_name,
3299 iv: get_required_buffer_source(cx, object, c"iv")?,
3300 })
3301 }
3302}
3303
3304#[derive(Clone, MallocSizeOf)]
3306struct AesGcmParams {
3307 name: CryptoAlgorithm,
3309
3310 iv: Vec<u8>,
3312
3313 additional_data: Option<Vec<u8>>,
3315
3316 tag_length: Option<u8>,
3318}
3319
3320impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AesGcmParams {
3321 type Error = Error;
3322
3323 fn try_from_with_cx_and_name(
3324 object: HandleObject<'a>,
3325 cx: &mut js::context::JSContext,
3326 algorithm_name: CryptoAlgorithm,
3327 ) -> Result<Self, Self::Error> {
3328 Ok(AesGcmParams {
3329 name: algorithm_name,
3330 iv: get_required_buffer_source(cx, object, c"iv")?,
3331 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3332 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3333 })
3334 }
3335}
3336
3337#[derive(Clone, MallocSizeOf)]
3339struct HmacImportParams {
3340 name: CryptoAlgorithm,
3342
3343 hash: DigestAlgorithm,
3345
3346 length: Option<u32>,
3348}
3349
3350impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacImportParams {
3351 type Error = Error;
3352
3353 fn try_from_with_cx_and_name(
3354 object: HandleObject<'a>,
3355 cx: &mut js::context::JSContext,
3356 algorithm_name: CryptoAlgorithm,
3357 ) -> Result<Self, Self::Error> {
3358 let hash = get_required_parameter(cx, object, c"hash", ())?;
3359
3360 Ok(HmacImportParams {
3361 name: algorithm_name,
3362 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3363 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3364 })
3365 }
3366}
3367
3368#[derive(Clone, MallocSizeOf)]
3370pub(crate) struct HmacKeyAlgorithm {
3371 name: CryptoAlgorithm,
3373
3374 hash: DigestAlgorithm,
3376
3377 length: u32,
3379}
3380
3381impl ToJSValConvertible for HmacKeyAlgorithm {
3382 #[expect(unsafe_code)]
3383 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3384 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3385
3386 rooted!(&in(cx) let mut name_js = UndefinedValue());
3387 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3388 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3389 .expect("Failed to set name property of HmacKeyAlgorithm");
3390
3391 rooted!(&in(cx) let mut hash_js = UndefinedValue());
3392 let hash = KeyAlgorithm {
3393 name: self.hash.name(),
3394 };
3395 hash.to_jsval(cx, hash_js.handle_mut());
3396 set_dictionary_property(cx, object.handle(), c"hash", hash_js.handle())
3397 .expect("Failed to set hash property of HmacKeyAlgorithm");
3398
3399 rooted!(&in(cx) let mut length_js = UndefinedValue());
3400 self.length.to_jsval(cx, length_js.handle_mut());
3401 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3402 .expect("Failed to set length property of HmacKeyAlgorithm");
3403
3404 rval.set(ObjectOrNullValue(object.get()));
3405 }
3406}
3407
3408impl TryFrom<SerializableHmacKeyAlgorithm> for HmacKeyAlgorithm {
3409 type Error = ();
3410
3411 fn try_from(value: SerializableHmacKeyAlgorithm) -> Result<Self, Self::Error> {
3412 Ok(HmacKeyAlgorithm {
3413 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3414 hash: value.hash.try_into()?,
3415 length: value.length,
3416 })
3417 }
3418}
3419
3420impl From<&HmacKeyAlgorithm> for SerializableHmacKeyAlgorithm {
3421 fn from(value: &HmacKeyAlgorithm) -> Self {
3422 SerializableHmacKeyAlgorithm {
3423 name: value.name.as_str().into(),
3424 hash: (&value.hash).into(),
3425 length: value.length,
3426 }
3427 }
3428}
3429
3430#[derive(Clone, MallocSizeOf)]
3432struct HmacKeyGenParams {
3433 name: CryptoAlgorithm,
3435
3436 hash: DigestAlgorithm,
3438
3439 length: Option<u32>,
3441}
3442
3443impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HmacKeyGenParams {
3444 type Error = Error;
3445
3446 fn try_from_with_cx_and_name(
3447 object: HandleObject<'a>,
3448 cx: &mut js::context::JSContext,
3449 algorithm_name: CryptoAlgorithm,
3450 ) -> Result<Self, Self::Error> {
3451 let hash = get_required_parameter(cx, object, c"hash", ())?;
3452
3453 Ok(HmacKeyGenParams {
3454 name: algorithm_name,
3455 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3456 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3457 })
3458 }
3459}
3460
3461#[derive(Clone, MallocSizeOf)]
3463pub(crate) struct HkdfParams {
3464 name: CryptoAlgorithm,
3466
3467 hash: DigestAlgorithm,
3469
3470 salt: Vec<u8>,
3472
3473 info: Vec<u8>,
3475}
3476
3477impl<'a> TryFromWithCxAndName<HandleObject<'a>> for HkdfParams {
3478 type Error = Error;
3479
3480 fn try_from_with_cx_and_name(
3481 object: HandleObject<'a>,
3482 cx: &mut js::context::JSContext,
3483 algorithm_name: CryptoAlgorithm,
3484 ) -> Result<Self, Self::Error> {
3485 let hash = get_required_parameter(cx, object, c"hash", ())?;
3486
3487 Ok(HkdfParams {
3488 name: algorithm_name,
3489 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3490 salt: get_required_buffer_source(cx, object, c"salt")?,
3491 info: get_required_buffer_source(cx, object, c"info")?,
3492 })
3493 }
3494}
3495
3496#[derive(Clone, MallocSizeOf)]
3498pub(crate) struct Pbkdf2Params {
3499 name: CryptoAlgorithm,
3501
3502 salt: Vec<u8>,
3504
3505 iterations: u32,
3507
3508 hash: DigestAlgorithm,
3510}
3511
3512impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Pbkdf2Params {
3513 type Error = Error;
3514
3515 fn try_from_with_cx_and_name(
3516 object: HandleObject<'a>,
3517 cx: &mut js::context::JSContext,
3518 algorithm_name: CryptoAlgorithm,
3519 ) -> Result<Self, Self::Error> {
3520 let hash = get_required_parameter(cx, object, c"hash", ())?;
3521
3522 Ok(Pbkdf2Params {
3523 name: algorithm_name,
3524 salt: get_required_buffer_source(cx, object, c"salt")?,
3525 iterations: get_required_parameter(
3526 cx,
3527 object,
3528 c"iterations",
3529 ConversionBehavior::EnforceRange,
3530 )?,
3531 hash: normalize_algorithm::<DigestOperation>(cx, &hash)?,
3532 })
3533 }
3534}
3535
3536#[derive(Clone, MallocSizeOf)]
3538struct ContextParams {
3539 name: CryptoAlgorithm,
3541
3542 context: Option<Vec<u8>>,
3544}
3545
3546impl<'a> TryFromWithCxAndName<HandleObject<'a>> for ContextParams {
3547 type Error = Error;
3548
3549 fn try_from_with_cx_and_name(
3550 object: HandleObject<'a>,
3551 cx: &mut js::context::JSContext,
3552 algorithm_name: CryptoAlgorithm,
3553 ) -> Result<Self, Self::Error> {
3554 Ok(ContextParams {
3555 name: algorithm_name,
3556 context: get_optional_buffer_source(cx, object, c"context")?,
3557 })
3558 }
3559}
3560
3561#[derive(Clone, MallocSizeOf)]
3563struct AeadParams {
3564 name: CryptoAlgorithm,
3566
3567 iv: Vec<u8>,
3569
3570 additional_data: Option<Vec<u8>>,
3572
3573 tag_length: Option<u8>,
3575}
3576
3577impl<'a> TryFromWithCxAndName<HandleObject<'a>> for AeadParams {
3578 type Error = Error;
3579
3580 fn try_from_with_cx_and_name(
3581 object: HandleObject<'a>,
3582 cx: &mut js::context::JSContext,
3583 algorithm_name: CryptoAlgorithm,
3584 ) -> Result<Self, Self::Error> {
3585 Ok(AeadParams {
3586 name: algorithm_name,
3587 iv: get_required_buffer_source(cx, object, c"iv")?,
3588 additional_data: get_optional_buffer_source(cx, object, c"additionalData")?,
3589 tag_length: get_property(cx, object, c"tagLength", ConversionBehavior::EnforceRange)?,
3590 })
3591 }
3592}
3593
3594#[derive(Clone, MallocSizeOf)]
3596struct CShakeParams {
3597 name: CryptoAlgorithm,
3599
3600 output_length: u32,
3602
3603 function_name: Option<Vec<u8>>,
3605
3606 customization: Option<Vec<u8>>,
3608}
3609
3610impl<'a> TryFromWithCxAndName<HandleObject<'a>> for CShakeParams {
3611 type Error = Error;
3612
3613 fn try_from_with_cx_and_name(
3614 object: HandleObject<'a>,
3615 cx: &mut js::context::JSContext,
3616 algorithm_name: CryptoAlgorithm,
3617 ) -> Result<Self, Self::Error> {
3618 Ok(CShakeParams {
3619 name: algorithm_name,
3620 output_length: get_required_parameter(
3621 cx,
3622 object,
3623 c"outputLength",
3624 ConversionBehavior::EnforceRange,
3625 )?,
3626 function_name: get_optional_buffer_source(cx, object, c"functionName")?,
3627 customization: get_optional_buffer_source(cx, object, c"customization")?,
3628 })
3629 }
3630}
3631
3632impl TryFrom<SerializableCShakeParams> for CShakeParams {
3633 type Error = ();
3634
3635 fn try_from(value: SerializableCShakeParams) -> Result<Self, Self::Error> {
3636 Ok(CShakeParams {
3637 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3638 output_length: value.output_length,
3639 function_name: value.function_name,
3640 customization: value.customization,
3641 })
3642 }
3643}
3644
3645impl From<&CShakeParams> for SerializableCShakeParams {
3646 fn from(value: &CShakeParams) -> Self {
3647 SerializableCShakeParams {
3648 name: value.name.as_str().into(),
3649 output_length: value.output_length,
3650 function_name: value.function_name.clone(),
3651 customization: value.customization.clone(),
3652 }
3653 }
3654}
3655
3656#[derive(Clone, MallocSizeOf)]
3658struct TurboShakeParams {
3659 name: CryptoAlgorithm,
3661
3662 output_length: u32,
3664
3665 domain_separation: Option<u8>,
3667}
3668
3669impl<'a> TryFromWithCxAndName<HandleObject<'a>> for TurboShakeParams {
3670 type Error = Error;
3671
3672 fn try_from_with_cx_and_name(
3673 object: HandleObject<'a>,
3674 cx: &mut js::context::JSContext,
3675 algorithm_name: CryptoAlgorithm,
3676 ) -> Result<Self, Self::Error> {
3677 Ok(TurboShakeParams {
3678 name: algorithm_name,
3679 output_length: get_required_parameter(
3680 cx,
3681 object,
3682 c"outputLength",
3683 ConversionBehavior::EnforceRange,
3684 )?,
3685 domain_separation: get_property(
3686 cx,
3687 object,
3688 c"domainSeparation",
3689 ConversionBehavior::EnforceRange,
3690 )?,
3691 })
3692 }
3693}
3694
3695impl TryFrom<SerializableTurboShakeParams> for TurboShakeParams {
3696 type Error = ();
3697
3698 fn try_from(value: SerializableTurboShakeParams) -> Result<Self, Self::Error> {
3699 Ok(TurboShakeParams {
3700 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3701 output_length: value.output_length,
3702 domain_separation: value.domain_separation,
3703 })
3704 }
3705}
3706
3707impl From<&TurboShakeParams> for SerializableTurboShakeParams {
3708 fn from(value: &TurboShakeParams) -> Self {
3709 SerializableTurboShakeParams {
3710 name: value.name.as_str().into(),
3711 output_length: value.output_length,
3712 domain_separation: value.domain_separation,
3713 }
3714 }
3715}
3716
3717#[derive(Clone, MallocSizeOf)]
3719struct KangarooTwelveParams {
3720 name: CryptoAlgorithm,
3722
3723 output_length: u32,
3725
3726 customization: Option<Vec<u8>>,
3728}
3729
3730impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KangarooTwelveParams {
3731 type Error = Error;
3732
3733 fn try_from_with_cx_and_name(
3734 object: HandleObject<'a>,
3735 cx: &mut js::context::JSContext,
3736 algorithm_name: CryptoAlgorithm,
3737 ) -> Result<Self, Self::Error> {
3738 Ok(KangarooTwelveParams {
3739 name: algorithm_name,
3740 output_length: get_required_parameter(
3741 cx,
3742 object,
3743 c"outputLength",
3744 ConversionBehavior::EnforceRange,
3745 )?,
3746 customization: get_optional_buffer_source(cx, object, c"customization")?,
3747 })
3748 }
3749}
3750
3751impl TryFrom<SerializableKangarooTwelveParams> for KangarooTwelveParams {
3752 type Error = ();
3753
3754 fn try_from(value: SerializableKangarooTwelveParams) -> Result<Self, Self::Error> {
3755 Ok(KangarooTwelveParams {
3756 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3757 output_length: value.output_length,
3758 customization: value.customization,
3759 })
3760 }
3761}
3762
3763impl From<&KangarooTwelveParams> for SerializableKangarooTwelveParams {
3764 fn from(value: &KangarooTwelveParams) -> Self {
3765 SerializableKangarooTwelveParams {
3766 name: value.name.as_str().into(),
3767 output_length: value.output_length,
3768 customization: value.customization.clone(),
3769 }
3770 }
3771}
3772
3773#[derive(Clone, MallocSizeOf)]
3775struct KmacKeyGenParams {
3776 name: CryptoAlgorithm,
3778
3779 length: Option<u32>,
3781}
3782
3783impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacKeyGenParams {
3784 type Error = Error;
3785
3786 fn try_from_with_cx_and_name(
3787 object: HandleObject,
3788 cx: &mut js::context::JSContext,
3789 algorithm_name: CryptoAlgorithm,
3790 ) -> Result<Self, Self::Error> {
3791 Ok(KmacKeyGenParams {
3792 name: algorithm_name,
3793 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3794 })
3795 }
3796}
3797
3798#[derive(Clone, MallocSizeOf)]
3800struct KmacImportParams {
3801 name: CryptoAlgorithm,
3803
3804 length: Option<u32>,
3806}
3807
3808impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacImportParams {
3809 type Error = Error;
3810
3811 fn try_from_with_cx_and_name(
3812 object: HandleObject,
3813 cx: &mut js::context::JSContext,
3814 algorithm_name: CryptoAlgorithm,
3815 ) -> Result<Self, Self::Error> {
3816 Ok(KmacImportParams {
3817 name: algorithm_name,
3818 length: get_property(cx, object, c"length", ConversionBehavior::EnforceRange)?,
3819 })
3820 }
3821}
3822
3823#[derive(Clone, MallocSizeOf)]
3825pub(crate) struct KmacKeyAlgorithm {
3826 name: CryptoAlgorithm,
3828
3829 length: u32,
3831}
3832
3833impl ToJSValConvertible for KmacKeyAlgorithm {
3834 #[expect(unsafe_code)]
3835 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3836 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3837
3838 rooted!(&in(cx) let mut name_js = UndefinedValue());
3839 self.name.as_str().to_jsval(cx, name_js.handle_mut());
3840 set_dictionary_property(cx, object.handle(), c"name", name_js.handle())
3841 .expect("Failed to set name property of KmacKeyAlgorithm");
3842
3843 rooted!(&in(cx) let mut length_js = UndefinedValue());
3844 self.length.to_jsval(cx, length_js.handle_mut());
3845 set_dictionary_property(cx, object.handle(), c"length", length_js.handle())
3846 .expect("Failed to set length property of KmacKeyAlgorithm");
3847
3848 rval.set(ObjectOrNullValue(object.get()));
3849 }
3850}
3851
3852impl TryFrom<SerializableKmacKeyAlgorithm> for KmacKeyAlgorithm {
3853 type Error = ();
3854
3855 fn try_from(value: SerializableKmacKeyAlgorithm) -> Result<Self, Self::Error> {
3856 Ok(KmacKeyAlgorithm {
3857 name: CryptoAlgorithm::from_str(&value.name).map_err(|_| ())?,
3858 length: value.length,
3859 })
3860 }
3861}
3862
3863impl From<&KmacKeyAlgorithm> for SerializableKmacKeyAlgorithm {
3864 fn from(value: &KmacKeyAlgorithm) -> Self {
3865 SerializableKmacKeyAlgorithm {
3866 name: value.name.as_str().into(),
3867 length: value.length,
3868 }
3869 }
3870}
3871
3872struct KmacParams {
3874 name: CryptoAlgorithm,
3876
3877 output_length: u32,
3879
3880 customization: Option<Vec<u8>>,
3882}
3883
3884impl<'a> TryFromWithCxAndName<HandleObject<'a>> for KmacParams {
3885 type Error = Error;
3886
3887 fn try_from_with_cx_and_name(
3888 object: HandleObject<'a>,
3889 cx: &mut js::context::JSContext,
3890 algorithm_name: CryptoAlgorithm,
3891 ) -> Result<Self, Self::Error> {
3892 Ok(KmacParams {
3893 name: algorithm_name,
3894 output_length: get_required_parameter(
3895 cx,
3896 object,
3897 c"outputLength",
3898 ConversionBehavior::EnforceRange,
3899 )?,
3900 customization: get_optional_buffer_source(cx, object, c"customization")?,
3901 })
3902 }
3903}
3904
3905#[derive(Clone, MallocSizeOf)]
3907struct Argon2Params {
3908 name: CryptoAlgorithm,
3910
3911 nonce: Vec<u8>,
3913
3914 parallelism: u32,
3916
3917 memory: u32,
3919
3920 passes: u32,
3922
3923 version: Option<u8>,
3925
3926 secret_value: Option<Vec<u8>>,
3928
3929 associated_data: Option<Vec<u8>>,
3931}
3932
3933impl<'a> TryFromWithCxAndName<HandleObject<'a>> for Argon2Params {
3934 type Error = Error;
3935
3936 fn try_from_with_cx_and_name(
3937 object: HandleObject<'a>,
3938 cx: &mut js::context::JSContext,
3939 algorithm_name: CryptoAlgorithm,
3940 ) -> Result<Self, Self::Error> {
3941 Ok(Argon2Params {
3942 name: algorithm_name,
3943 nonce: get_required_buffer_source(cx, object, c"nonce")?,
3944 parallelism: get_required_parameter(
3945 cx,
3946 object,
3947 c"parallelism",
3948 ConversionBehavior::EnforceRange,
3949 )?,
3950 memory: get_required_parameter(
3951 cx,
3952 object,
3953 c"memory",
3954 ConversionBehavior::EnforceRange,
3955 )?,
3956 passes: get_required_parameter(
3957 cx,
3958 object,
3959 c"passes",
3960 ConversionBehavior::EnforceRange,
3961 )?,
3962 version: get_property(cx, object, c"version", ConversionBehavior::EnforceRange)?,
3963 secret_value: get_optional_buffer_source(cx, object, c"secretValue")?,
3964 associated_data: get_optional_buffer_source(cx, object, c"associatedData")?,
3965 })
3966 }
3967}
3968
3969struct EncapsulatedKey {
3971 shared_key: Option<Trusted<CryptoKey>>,
3973
3974 ciphertext: Option<Vec<u8>>,
3976}
3977
3978impl ToJSValConvertible for EncapsulatedKey {
3979 #[expect(unsafe_code)]
3980 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
3981 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
3982
3983 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
3984 self.shared_key
3985 .as_ref()
3986 .map(|shared_key| shared_key.root())
3987 .to_jsval(cx, shared_key_js.handle_mut());
3988 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
3989 .expect("Failed to set sharedKey property of EncapsulatedKey");
3990
3991 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
3992 self.ciphertext
3993 .as_ref()
3994 .map(|ciphertext| {
3995 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
3996 create_buffer_source::<ArrayBufferU8>(
3997 cx,
3998 ciphertext,
3999 ciphertext_js_object.handle_mut(),
4000 )
4001 .expect("Failed to convert ciphertext to ArrayBufferU8")
4002 })
4003 .to_jsval(cx, ciphertext_js.handle_mut());
4004 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4005 .expect("Failed to set ciphertext property of EncapsulatedKey");
4006
4007 rval.set(ObjectOrNullValue(object.get()));
4008 }
4009}
4010
4011struct EncapsulatedBits {
4013 shared_key: Option<Zeroizing<Vec<u8>>>,
4015
4016 ciphertext: Option<Vec<u8>>,
4018}
4019
4020impl ToJSValConvertible for EncapsulatedBits {
4021 #[expect(unsafe_code)]
4022 fn to_jsval(&self, cx: &mut js::context::JSContext, mut rval: MutableHandleValue) {
4023 rooted!(&in(cx) let mut object = unsafe { JS_NewObject(cx, ptr::null()) });
4024
4025 rooted!(&in(cx) let mut shared_key_js = UndefinedValue());
4026 self.shared_key
4027 .as_ref()
4028 .map(|shared_key| {
4029 rooted!(&in(cx) let mut shared_key_js_object = ptr::null_mut::<JSObject>());
4030 create_buffer_source::<ArrayBufferU8>(
4031 cx,
4032 shared_key,
4033 shared_key_js_object.handle_mut(),
4034 )
4035 .expect("Failed to convert shared_key to ArrayBufferU8")
4036 })
4037 .to_jsval(cx, shared_key_js.handle_mut());
4038 set_dictionary_property(cx, object.handle(), c"sharedKey", shared_key_js.handle())
4039 .expect("Failed to set sharedKey property of EncapsulatedBits");
4040
4041 rooted!(&in(cx) let mut ciphertext_js = UndefinedValue());
4042 self.ciphertext
4043 .as_ref()
4044 .map(|ciphertext| {
4045 rooted!(&in(cx) let mut ciphertext_js_object = ptr::null_mut::<JSObject>());
4046 create_buffer_source::<ArrayBufferU8>(
4047 cx,
4048 ciphertext,
4049 ciphertext_js_object.handle_mut(),
4050 )
4051 .expect("Failed to convert ciphertext to ArrayBufferU8")
4052 })
4053 .to_jsval(cx, ciphertext_js.handle_mut());
4054 set_dictionary_property(cx, object.handle(), c"ciphertext", ciphertext_js.handle())
4055 .expect("Failed to set ciphertext property of EncapsulatedBits");
4056
4057 rval.set(ObjectOrNullValue(object.get()));
4058 }
4059}
4060
4061#[derive(Clone, MallocSizeOf)]
4063struct SubtleEd448Params {
4064 name: CryptoAlgorithm,
4066
4067 context: Option<Vec<u8>>,
4069}
4070
4071impl<'a> TryFromWithCxAndName<HandleObject<'a>> for SubtleEd448Params {
4072 type Error = Error;
4073
4074 fn try_from_with_cx_and_name(
4075 object: HandleObject<'a>,
4076 cx: &mut js::context::JSContext,
4077 algorithm_name: CryptoAlgorithm,
4078 ) -> Result<Self, Self::Error> {
4079 Ok(SubtleEd448Params {
4080 name: algorithm_name,
4081 context: get_optional_buffer_source(cx, object, c"context")?,
4082 })
4083 }
4084}
4085
4086fn get_required_parameter<T: FromJSValConvertible>(
4088 cx: &mut js::context::JSContext,
4089 object: HandleObject,
4090 parameter: &std::ffi::CStr,
4091 option: T::Config,
4092) -> Fallible<T> {
4093 get_property::<T>(cx, object, parameter, option)?
4094 .ok_or(Error::Type(c"Missing required parameter".into()))
4095}
4096
4097fn get_required_parameter_in_box<T: FromJSValConvertible + Trace>(
4099 cx: &mut js::context::JSContext,
4100 object: HandleObject,
4101 parameter: &std::ffi::CStr,
4102 option: T::Config,
4103) -> Fallible<RootedTraceableBox<T>> {
4104 get_property::<T>(cx, object, parameter, option)?
4105 .map(RootedTraceableBox::new)
4106 .ok_or(Error::Type(c"Missing required parameter".into()))
4107}
4108
4109fn get_optional_buffer_source(
4113 cx: &mut js::context::JSContext,
4114 object: HandleObject,
4115 parameter: &std::ffi::CStr,
4116) -> Fallible<Option<Vec<u8>>> {
4117 let buffer_source = get_property::<ArrayBufferViewOrArrayBuffer>(cx, object, parameter, ())?;
4118 Ok(buffer_source
4119 .as_ref()
4120 .map(|buffer| get_buffer_source_copy(buffer.into())))
4121}
4122
4123fn get_required_buffer_source(
4127 cx: &mut js::context::JSContext,
4128 object: HandleObject,
4129 parameter: &std::ffi::CStr,
4130) -> Fallible<Vec<u8>> {
4131 get_optional_buffer_source(cx, object, parameter)?
4132 .ok_or(Error::Type(c"Missing required parameter".into()))
4133}
4134
4135enum ExportedKey {
4139 Bytes(Zeroizing<Vec<u8>>),
4140 Jwk(Box<JsonWebKey>),
4141}
4142
4143impl ExportedKey {
4144 fn new_bytes(bytes: Vec<u8>) -> ExportedKey {
4145 ExportedKey::Bytes(Zeroizing::new(bytes))
4146 }
4147
4148 fn new_jwk(jwk: JsonWebKey) -> ExportedKey {
4149 ExportedKey::Jwk(Box::new(jwk))
4150 }
4151}
4152
4153#[derive(Clone, MallocSizeOf)]
4157#[expect(clippy::enum_variant_names)]
4158pub(crate) enum KeyAlgorithmAndDerivatives {
4159 KeyAlgorithm(KeyAlgorithm),
4160 RsaHashedKeyAlgorithm(RsaHashedKeyAlgorithm),
4161 EcKeyAlgorithm(EcKeyAlgorithm),
4162 AesKeyAlgorithm(AesKeyAlgorithm),
4163 HmacKeyAlgorithm(HmacKeyAlgorithm),
4164 KmacKeyAlgorithm(KmacKeyAlgorithm),
4165}
4166
4167impl KeyAlgorithmAndDerivatives {
4168 fn name(&self) -> CryptoAlgorithm {
4169 match self {
4170 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => algorithm.name,
4171 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => algorithm.name,
4172 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => algorithm.name,
4173 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => algorithm.name,
4174 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => algorithm.name,
4175 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => algorithm.name,
4176 }
4177 }
4178}
4179
4180impl ToJSValConvertible for KeyAlgorithmAndDerivatives {
4181 fn to_jsval(&self, cx: &mut js::context::JSContext, rval: MutableHandleValue) {
4182 match self {
4183 KeyAlgorithmAndDerivatives::KeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4184 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4185 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4186 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4187 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4188 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algo) => algo.to_jsval(cx, rval),
4189 }
4190 }
4191}
4192
4193impl TryFrom<SerializableKeyAlgorithmAndDerivatives> for KeyAlgorithmAndDerivatives {
4194 type Error = ();
4195
4196 fn try_from(value: SerializableKeyAlgorithmAndDerivatives) -> Result<Self, Self::Error> {
4197 match value {
4198 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => Ok(
4199 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.try_into()?),
4200 ),
4201 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => Ok(
4202 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.try_into()?),
4203 ),
4204 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => Ok(
4205 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.try_into()?),
4206 ),
4207 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => Ok(
4208 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.try_into()?),
4209 ),
4210 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => Ok(
4211 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.try_into()?),
4212 ),
4213 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => Ok(
4214 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.try_into()?),
4215 ),
4216 }
4217 }
4218}
4219
4220impl From<&KeyAlgorithmAndDerivatives> for SerializableKeyAlgorithmAndDerivatives {
4221 fn from(value: &KeyAlgorithmAndDerivatives) -> Self {
4222 match value {
4223 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm) => {
4224 SerializableKeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm.into())
4225 },
4226 KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) => {
4227 SerializableKeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm.into())
4228 },
4229 KeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm) => {
4230 SerializableKeyAlgorithmAndDerivatives::EcKeyAlgorithm(algorithm.into())
4231 },
4232 KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) => {
4233 SerializableKeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm.into())
4234 },
4235 KeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm) => {
4236 SerializableKeyAlgorithmAndDerivatives::HmacKeyAlgorithm(algorithm.into())
4237 },
4238 KeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm) => {
4239 SerializableKeyAlgorithmAndDerivatives::KmacKeyAlgorithm(algorithm.into())
4240 },
4241 }
4242 }
4243}
4244
4245#[derive(Clone, Copy)]
4246enum JwkStringField {
4247 X,
4248 Y,
4249 D,
4250 N,
4251 E,
4252 P,
4253 Q,
4254 DP,
4255 DQ,
4256 QI,
4257 K,
4258 Priv,
4259 Pub,
4260}
4261
4262impl Display for JwkStringField {
4263 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4264 let field_name = match self {
4265 JwkStringField::X => "x",
4266 JwkStringField::Y => "y",
4267 JwkStringField::D => "d",
4268 JwkStringField::N => "n",
4269 JwkStringField::E => "e",
4270 JwkStringField::P => "q",
4271 JwkStringField::Q => "q",
4272 JwkStringField::DP => "dp",
4273 JwkStringField::DQ => "dq",
4274 JwkStringField::QI => "qi",
4275 JwkStringField::K => "k",
4276 JwkStringField::Priv => "priv",
4277 JwkStringField::Pub => "pub",
4278 };
4279 write!(f, "{}", field_name)
4280 }
4281}
4282
4283trait JsonWebKeyExt {
4284 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error>;
4285 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error>;
4286 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error>;
4287 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error>;
4288 fn set_key_ops(&mut self, usages: &[KeyUsage]);
4289 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]);
4290 fn decode_optional_string_field(
4291 &self,
4292 field: JwkStringField,
4293 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error>;
4294 fn decode_required_string_field(
4295 &self,
4296 field: JwkStringField,
4297 ) -> Result<Zeroizing<Vec<u8>>, Error>;
4298 fn decode_primes_from_oth_field(
4299 &self,
4300 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4301 ) -> Result<(), Error>;
4302}
4303
4304impl JsonWebKeyExt for JsonWebKey {
4305 #[expect(unsafe_code)]
4307 fn parse(cx: &mut js::context::JSContext, data: &[u8]) -> Result<JsonWebKey, Error> {
4308 let json = String::from_utf8_lossy(data);
4313
4314 let json: Vec<_> = json.encode_utf16().collect();
4316
4317 rooted!(&in(cx) let mut result = UndefinedValue());
4321 unsafe {
4322 if !JS_ParseJSON(cx, json.as_ptr(), json.len() as u32, result.handle_mut()) {
4323 return Err(Error::JSFailed);
4324 }
4325 }
4326
4327 let key = match JsonWebKey::new(cx, result.handle()) {
4329 Ok(ConversionResult::Success(key)) => key,
4330 Ok(ConversionResult::Failure(error)) => {
4331 return Err(Error::Type(error.into_owned()));
4332 },
4333 Err(()) => {
4334 return Err(Error::JSFailed);
4335 },
4336 };
4337
4338 if key.kty.is_none() {
4340 return Err(Error::Data(Some(
4341 "'kty' field of key is not defined".into(),
4342 )));
4343 }
4344
4345 Ok(key)
4347 }
4348
4349 fn stringify(&self, cx: &mut js::context::JSContext) -> Result<Zeroizing<DOMString>, Error> {
4355 rooted!(&in(cx) let mut data = UndefinedValue());
4356 self.to_jsval(cx, data.handle_mut());
4357 serialize_jsval_to_json_utf8(cx, data.handle()).map(Zeroizing::new)
4358 }
4359
4360 fn get_usages_from_key_ops(&self) -> Result<Vec<KeyUsage>, Error> {
4361 let mut usages = vec![];
4362 for op in self.key_ops.as_ref().ok_or(Error::Data(Some(
4363 "'key_ops' member is not present in the JSON Web Key".into(),
4364 )))? {
4365 usages.push(
4366 KeyUsage::from_str(&op.str())
4367 .map_err(|_| Error::Data(Some("Unknown key usage".into())))?,
4368 );
4369 }
4370 Ok(usages)
4371 }
4372
4373 fn check_key_ops(&self, specified_usages: &[KeyUsage]) -> Result<(), Error> {
4377 if let Some(ref key_ops) = self.key_ops {
4379 if key_ops
4382 .iter()
4383 .collect::<std::collections::HashSet<_>>()
4384 .len() <
4385 key_ops.len()
4386 {
4387 return Err(Error::Data(Some(
4388 "Duplicate key operation values are present in array".into(),
4389 )));
4390 }
4391 if let Some(ref use_) = self.use_ &&
4394 key_ops.iter().any(|op| op != use_)
4395 {
4396 return Err(Error::Data(Some(
4397 "Key operations are not consistent with intended use for Json Web Key".into(),
4398 )));
4399 }
4400
4401 let key_ops_as_usages = self.get_usages_from_key_ops()?;
4403 if !specified_usages
4404 .iter()
4405 .all(|specified_usage| key_ops_as_usages.contains(specified_usage))
4406 {
4407 return Err(Error::Data(Some(
4408 "Key operations do not contain all of the specified usage values".into(),
4409 )));
4410 }
4411 }
4412
4413 Ok(())
4414 }
4415
4416 fn set_key_ops(&mut self, usages: &[KeyUsage]) {
4418 self.key_ops = Some(
4419 usages
4420 .iter()
4421 .map(|usage| DOMString::from(usage.as_str()))
4422 .collect(),
4423 );
4424 }
4425
4426 fn encode_string_field(&mut self, field: JwkStringField, data: &[u8]) {
4429 let encoded_data = DOMString::from(Base64UrlUnpadded::encode_string(data));
4430 match field {
4431 JwkStringField::X => self.x = Some(encoded_data),
4432 JwkStringField::Y => self.y = Some(encoded_data),
4433 JwkStringField::D => self.d = Some(encoded_data),
4434 JwkStringField::N => self.n = Some(encoded_data),
4435 JwkStringField::E => self.e = Some(encoded_data),
4436 JwkStringField::P => self.p = Some(encoded_data),
4437 JwkStringField::Q => self.q = Some(encoded_data),
4438 JwkStringField::DP => self.dp = Some(encoded_data),
4439 JwkStringField::DQ => self.dq = Some(encoded_data),
4440 JwkStringField::QI => self.qi = Some(encoded_data),
4441 JwkStringField::K => self.k = Some(encoded_data),
4442 JwkStringField::Priv => self.priv_ = Some(encoded_data),
4443 JwkStringField::Pub => self.pub_ = Some(encoded_data),
4444 }
4445 }
4446
4447 fn decode_optional_string_field(
4450 &self,
4451 field: JwkStringField,
4452 ) -> Result<Option<Zeroizing<Vec<u8>>>, Error> {
4453 let field_string = match field {
4454 JwkStringField::X => &self.x,
4455 JwkStringField::Y => &self.y,
4456 JwkStringField::D => &self.d,
4457 JwkStringField::N => &self.n,
4458 JwkStringField::E => &self.e,
4459 JwkStringField::P => &self.p,
4460 JwkStringField::Q => &self.q,
4461 JwkStringField::DP => &self.dp,
4462 JwkStringField::DQ => &self.dq,
4463 JwkStringField::QI => &self.qi,
4464 JwkStringField::K => &self.k,
4465 JwkStringField::Priv => &self.priv_,
4466 JwkStringField::Pub => &self.pub_,
4467 };
4468
4469 field_string
4470 .as_ref()
4471 .map(|field_string| {
4472 Base64UrlUnpadded::decode_vec(&field_string.str()).map(Zeroizing::new)
4473 })
4474 .transpose()
4475 .map_err(|_| Error::Data(Some(format!("Failed to decode {} field in jwk", field))))
4476 }
4477
4478 fn decode_required_string_field(
4481 &self,
4482 field: JwkStringField,
4483 ) -> Result<Zeroizing<Vec<u8>>, Error> {
4484 self.decode_optional_string_field(field)?
4485 .ok_or(Error::Data(Some(format!(
4486 "The {} field is not present in jwk",
4487 field
4488 ))))
4489 }
4490
4491 fn decode_primes_from_oth_field(
4500 &self,
4501 primes: &mut Vec<Zeroizing<Vec<u8>>>,
4502 ) -> Result<(), Error> {
4503 if self.oth.is_some() &&
4504 (self.p.is_none() ||
4505 self.q.is_none() ||
4506 self.dp.is_none() ||
4507 self.dq.is_none() ||
4508 self.qi.is_none())
4509 {
4510 return Err(Error::Data(Some(
4511 "The oth field is present while at least one of p, q, dp, dq, qi is missing, in jwk".to_string()
4512 )));
4513 }
4514
4515 for rsa_other_prime_info in self.oth.as_ref().unwrap_or(&Vec::new()) {
4516 let r = Base64UrlUnpadded::decode_vec(
4517 &rsa_other_prime_info
4518 .r
4519 .as_ref()
4520 .ok_or(Error::Data(Some(
4521 "The r field is not present in one of the entry of oth field in jwk"
4522 .to_string(),
4523 )))?
4524 .str(),
4525 )
4526 .map_err(|_| {
4527 Error::Data(Some(
4528 "Fail to decode r field in one of the entry of oth field in jwk".to_string(),
4529 ))
4530 })?;
4531 primes.push(Zeroizing::new(r));
4532
4533 let _d = Base64UrlUnpadded::decode_vec(
4534 &rsa_other_prime_info
4535 .d
4536 .as_ref()
4537 .ok_or(Error::Data(Some(
4538 "The d field is not present in one of the entry of oth field in jwk"
4539 .to_string(),
4540 )))?
4541 .str(),
4542 )
4543 .map_err(|_| {
4544 Error::Data(Some(
4545 "Fail to decode d field in one of the entry of oth field in jwk".to_string(),
4546 ))
4547 })?;
4548
4549 let _t = Base64UrlUnpadded::decode_vec(
4550 &rsa_other_prime_info
4551 .t
4552 .as_ref()
4553 .ok_or(Error::Data(Some(
4554 "The t field is not present in one of the entry of oth field in jwk"
4555 .to_string(),
4556 )))?
4557 .str(),
4558 )
4559 .map_err(|_| {
4560 Error::Data(Some(
4561 "Fail to decode t field in one of the entry of oth field in jwk".to_string(),
4562 ))
4563 })?;
4564 }
4565
4566 Ok(())
4567 }
4568}
4569
4570fn normalize_algorithm<Op: Operation>(
4572 cx: &mut js::context::JSContext,
4573 algorithm: &AlgorithmIdentifier,
4574) -> Result<Op::RegisteredAlgorithm, Error> {
4575 match algorithm {
4576 AlgorithmIdentifier::String(name) => {
4578 let algorithm = AlgorithmWithDOMString {
4585 name: name.to_owned(),
4586 };
4587 rooted!(&in(cx) let mut algorithm_value = UndefinedValue());
4588 algorithm.to_jsval(cx, algorithm_value.handle_mut());
4589 let algorithm_object = RootedTraceableBox::new(Heap::default());
4590 algorithm_object.set(algorithm_value.to_object());
4591 normalize_algorithm::<Op>(cx, &AlgorithmIdentifier::Object(algorithm_object))
4592 },
4593 AlgorithmIdentifier::Object(object) => {
4595 let algorithm_name = get_required_parameter::<DOMString>(
4603 cx,
4604 object.handle(),
4605 c"name",
4606 StringificationBehavior::Default,
4607 )?;
4608
4609 let algorithm_name = CryptoAlgorithm::from_str_ignore_case(&algorithm_name.str())?;
4650 let normalized_algorithm =
4651 Op::RegisteredAlgorithm::from_object(cx, algorithm_name, object.handle())?;
4652
4653 Ok(normalized_algorithm)
4655 },
4656 }
4657}
4658
4659trait Operation {
4718 type RegisteredAlgorithm: NormalizedAlgorithm;
4719}
4720
4721trait NormalizedAlgorithm: Sized {
4722 fn from_object(
4724 cx: &mut js::context::JSContext,
4725 algorithm_name: CryptoAlgorithm,
4726 object: HandleObject,
4727 ) -> Fallible<Self>;
4728
4729 fn name(&self) -> CryptoAlgorithm;
4731
4732 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
4737 debug_assert!(
4778 false,
4779 "determine_support_from_operation_steps() is not implemented \
4780 for this normalized algorithm."
4781 );
4782 false
4783 }
4784}
4785
4786struct EncryptOperation {}
4788
4789impl Operation for EncryptOperation {
4790 type RegisteredAlgorithm = EncryptAlgorithm;
4791}
4792
4793enum EncryptAlgorithm {
4796 RsaOaep(RsaOaepParams),
4797 AesCtr(AesCtrParams),
4798 AesCbc(AesCbcParams),
4799 AesGcm(AesGcmParams),
4800 AesOcb(AeadParams),
4801 ChaCha20Poly1305(AeadParams),
4802}
4803
4804impl NormalizedAlgorithm for EncryptAlgorithm {
4805 fn from_object(
4806 cx: &mut js::context::JSContext,
4807 algorithm_name: CryptoAlgorithm,
4808 object: HandleObject,
4809 ) -> Fallible<Self> {
4810 match algorithm_name {
4811 CryptoAlgorithm::RsaOaep => Ok(EncryptAlgorithm::RsaOaep(
4812 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4813 )),
4814 CryptoAlgorithm::AesCtr => Ok(EncryptAlgorithm::AesCtr(
4815 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4816 )),
4817 CryptoAlgorithm::AesCbc => Ok(EncryptAlgorithm::AesCbc(
4818 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4819 )),
4820 CryptoAlgorithm::AesGcm => Ok(EncryptAlgorithm::AesGcm(
4821 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4822 )),
4823 CryptoAlgorithm::AesOcb => Ok(EncryptAlgorithm::AesOcb(
4824 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4825 )),
4826 CryptoAlgorithm::ChaCha20Poly1305 => Ok(EncryptAlgorithm::ChaCha20Poly1305(
4827 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4828 )),
4829 _ => Err(Error::NotSupported(Some(format!(
4830 "{} does not support \"encrypt\" operation",
4831 algorithm_name.as_str()
4832 )))),
4833 }
4834 }
4835
4836 fn name(&self) -> CryptoAlgorithm {
4837 match self {
4838 EncryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4839 EncryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4840 EncryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4841 EncryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4842 EncryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4843 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4844 }
4845 }
4846
4847 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
4848 match self {
4849 EncryptAlgorithm::RsaOaep(_) => true,
4850 EncryptAlgorithm::AesCtr(normalized_algorithm) => {
4851 normalized_algorithm.counter.len() == 16 &&
4852 normalized_algorithm.length != 0 &&
4853 normalized_algorithm.length <= 128
4854 },
4855 EncryptAlgorithm::AesCbc(normalized_algorithm) => normalized_algorithm.iv.len() == 16,
4856 EncryptAlgorithm::AesGcm(normalized_algorithm) => {
4857 normalized_algorithm.iv.len() <= u64::MAX as usize &&
4858 normalized_algorithm
4859 .additional_data
4860 .as_ref()
4861 .is_none_or(|additional_data| additional_data.len() <= u64::MAX as usize) &&
4862 normalized_algorithm.tag_length.is_none_or(|length| {
4863 matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)
4864 })
4865 },
4866 EncryptAlgorithm::AesOcb(normalized_algorithm) => {
4867 normalized_algorithm.iv.len() <= 15 &&
4868 normalized_algorithm
4869 .tag_length
4870 .is_none_or(|length| matches!(length, 64 | 96 | 128))
4871 },
4872 EncryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
4873 normalized_algorithm.iv.len() == 12 &&
4874 normalized_algorithm
4875 .tag_length
4876 .is_none_or(|length| length == 128)
4877 },
4878 }
4879 }
4880}
4881
4882impl EncryptAlgorithm {
4883 fn encrypt(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
4884 match self {
4885 EncryptAlgorithm::RsaOaep(algorithm) => {
4886 rsa_oaep_operation::encrypt(algorithm, key, plaintext)
4887 },
4888 EncryptAlgorithm::AesCtr(algorithm) => {
4889 aes_ctr_operation::encrypt(algorithm, key, plaintext)
4890 },
4891 EncryptAlgorithm::AesCbc(algorithm) => {
4892 aes_cbc_operation::encrypt(algorithm, key, plaintext)
4893 },
4894 EncryptAlgorithm::AesGcm(algorithm) => {
4895 aes_gcm_operation::encrypt(algorithm, key, plaintext)
4896 },
4897 EncryptAlgorithm::AesOcb(algorithm) => {
4898 aes_ocb_operation::encrypt(algorithm, key, plaintext)
4899 },
4900 EncryptAlgorithm::ChaCha20Poly1305(algorithm) => {
4901 chacha20_poly1305_operation::encrypt(algorithm, key, plaintext)
4902 },
4903 }
4904 }
4905}
4906
4907struct DecryptOperation {}
4909
4910impl Operation for DecryptOperation {
4911 type RegisteredAlgorithm = DecryptAlgorithm;
4912}
4913
4914enum DecryptAlgorithm {
4917 RsaOaep(RsaOaepParams),
4918 AesCtr(AesCtrParams),
4919 AesCbc(AesCbcParams),
4920 AesGcm(AesGcmParams),
4921 AesOcb(AeadParams),
4922 ChaCha20Poly1305(AeadParams),
4923}
4924
4925impl NormalizedAlgorithm for DecryptAlgorithm {
4926 fn from_object(
4927 cx: &mut js::context::JSContext,
4928 algorithm_name: CryptoAlgorithm,
4929 object: HandleObject,
4930 ) -> Fallible<Self> {
4931 match algorithm_name {
4932 CryptoAlgorithm::RsaOaep => Ok(DecryptAlgorithm::RsaOaep(
4933 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4934 )),
4935 CryptoAlgorithm::AesCtr => Ok(DecryptAlgorithm::AesCtr(
4936 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4937 )),
4938 CryptoAlgorithm::AesCbc => Ok(DecryptAlgorithm::AesCbc(
4939 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4940 )),
4941 CryptoAlgorithm::AesGcm => Ok(DecryptAlgorithm::AesGcm(
4942 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4943 )),
4944 CryptoAlgorithm::AesOcb => Ok(DecryptAlgorithm::AesOcb(
4945 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4946 )),
4947 CryptoAlgorithm::ChaCha20Poly1305 => Ok(DecryptAlgorithm::ChaCha20Poly1305(
4948 object.try_into_with_cx_and_name(cx, algorithm_name)?,
4949 )),
4950 _ => Err(Error::NotSupported(Some(format!(
4951 "{} does not support \"decrypt\" operation",
4952 algorithm_name.as_str()
4953 )))),
4954 }
4955 }
4956
4957 fn name(&self) -> CryptoAlgorithm {
4958 match self {
4959 DecryptAlgorithm::RsaOaep(algorithm) => algorithm.name,
4960 DecryptAlgorithm::AesCtr(algorithm) => algorithm.name,
4961 DecryptAlgorithm::AesCbc(algorithm) => algorithm.name,
4962 DecryptAlgorithm::AesGcm(algorithm) => algorithm.name,
4963 DecryptAlgorithm::AesOcb(algorithm) => algorithm.name,
4964 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
4965 }
4966 }
4967
4968 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
4969 match self {
4970 DecryptAlgorithm::RsaOaep(_) => true,
4971 DecryptAlgorithm::AesCtr(normalized_algorithm) => {
4972 normalized_algorithm.counter.len() == 16 &&
4973 normalized_algorithm.length != 0 &&
4974 normalized_algorithm.length <= 128
4975 },
4976 DecryptAlgorithm::AesCbc(normalized_algorithm) => normalized_algorithm.iv.len() == 16,
4977 DecryptAlgorithm::AesGcm(normalized_algorithm) => {
4978 normalized_algorithm
4979 .tag_length
4980 .as_ref()
4981 .is_none_or(|length| matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128)) &&
4982 normalized_algorithm.iv.len() <= u64::MAX as usize &&
4983 normalized_algorithm
4984 .additional_data
4985 .as_ref()
4986 .is_none_or(|additional_data| additional_data.len() <= u64::MAX as usize)
4987 },
4988 DecryptAlgorithm::AesOcb(normalized_algorithm) => {
4989 normalized_algorithm.iv.len() <= 15 &&
4990 normalized_algorithm
4991 .tag_length
4992 .as_ref()
4993 .is_none_or(|length| matches!(length, 64 | 96 | 128))
4994 },
4995 DecryptAlgorithm::ChaCha20Poly1305(normalized_algorithm) => {
4996 normalized_algorithm.iv.len() == 12 &&
4997 normalized_algorithm
4998 .tag_length
4999 .as_ref()
5000 .is_none_or(|length| *length == 128)
5001 },
5002 }
5003 }
5004}
5005
5006impl DecryptAlgorithm {
5007 fn decrypt(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5008 match self {
5009 DecryptAlgorithm::RsaOaep(algorithm) => {
5010 rsa_oaep_operation::decrypt(algorithm, key, ciphertext)
5011 },
5012 DecryptAlgorithm::AesCtr(algorithm) => {
5013 aes_ctr_operation::decrypt(algorithm, key, ciphertext)
5014 },
5015 DecryptAlgorithm::AesCbc(algorithm) => {
5016 aes_cbc_operation::decrypt(algorithm, key, ciphertext)
5017 },
5018 DecryptAlgorithm::AesGcm(algorithm) => {
5019 aes_gcm_operation::decrypt(algorithm, key, ciphertext)
5020 },
5021 DecryptAlgorithm::AesOcb(algorithm) => {
5022 aes_ocb_operation::decrypt(algorithm, key, ciphertext)
5023 },
5024 DecryptAlgorithm::ChaCha20Poly1305(algorithm) => {
5025 chacha20_poly1305_operation::decrypt(algorithm, key, ciphertext)
5026 },
5027 }
5028 }
5029}
5030
5031struct SignOperation {}
5033
5034impl Operation for SignOperation {
5035 type RegisteredAlgorithm = SignAlgorithm;
5036}
5037
5038enum SignAlgorithm {
5041 RsassaPkcs1V1_5(Algorithm),
5042 RsaPss(RsaPssParams),
5043 Ecdsa(EcdsaParams),
5044 Ed25519(Algorithm),
5045 Ed448(SubtleEd448Params),
5046 Hmac(Algorithm),
5047 MlDsa(ContextParams),
5048 Kmac(KmacParams),
5049}
5050
5051impl NormalizedAlgorithm for SignAlgorithm {
5052 fn from_object(
5053 cx: &mut js::context::JSContext,
5054 algorithm_name: CryptoAlgorithm,
5055 object: HandleObject,
5056 ) -> Fallible<Self> {
5057 match algorithm_name {
5058 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(SignAlgorithm::RsassaPkcs1V1_5(
5059 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5060 )),
5061 CryptoAlgorithm::RsaPss => Ok(SignAlgorithm::RsaPss(
5062 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5063 )),
5064 CryptoAlgorithm::Ecdsa => Ok(SignAlgorithm::Ecdsa(
5065 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5066 )),
5067 CryptoAlgorithm::Ed25519 => Ok(SignAlgorithm::Ed25519(
5068 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5069 )),
5070 CryptoAlgorithm::Ed448 => Ok(SignAlgorithm::Ed448(
5071 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5072 )),
5073 CryptoAlgorithm::Hmac => Ok(SignAlgorithm::Hmac(
5074 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5075 )),
5076 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5077 SignAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5078 ),
5079 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(SignAlgorithm::Kmac(
5080 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5081 )),
5082 _ => Err(Error::NotSupported(Some(format!(
5083 "{} does not support \"sign\" operation",
5084 algorithm_name.as_str()
5085 )))),
5086 }
5087 }
5088
5089 fn name(&self) -> CryptoAlgorithm {
5090 match self {
5091 SignAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5092 SignAlgorithm::RsaPss(algorithm) => algorithm.name,
5093 SignAlgorithm::Ecdsa(algorithm) => algorithm.name,
5094 SignAlgorithm::Ed25519(algorithm) => algorithm.name,
5095 SignAlgorithm::Ed448(algorithm) => algorithm.name,
5096 SignAlgorithm::Hmac(algorithm) => algorithm.name,
5097 SignAlgorithm::MlDsa(algorithm) => algorithm.name,
5098 SignAlgorithm::Kmac(algorithm) => algorithm.name,
5099 }
5100 }
5101
5102 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5103 match self {
5104 SignAlgorithm::RsassaPkcs1V1_5(_) |
5105 SignAlgorithm::RsaPss(_) |
5106 SignAlgorithm::Ecdsa(_) |
5107 SignAlgorithm::Ed25519(_) => true,
5108 SignAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
5109 .context
5110 .as_ref()
5111 .is_none_or(|context| context.len() <= 255),
5112 SignAlgorithm::Hmac(_) => true,
5113 SignAlgorithm::MlDsa(normalized_algorithm) => normalized_algorithm
5114 .context
5115 .as_ref()
5116 .is_none_or(|context| context.len() <= 255),
5117 SignAlgorithm::Kmac(_) => true,
5118 }
5119 }
5120}
5121
5122impl SignAlgorithm {
5123 fn sign(&self, key: &CryptoKey, message: &[u8]) -> Result<Vec<u8>, Error> {
5124 match self {
5125 SignAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5126 rsassa_pkcs1_v1_5_operation::sign(key, message)
5127 },
5128 SignAlgorithm::RsaPss(algorithm) => rsa_pss_operation::sign(algorithm, key, message),
5129 SignAlgorithm::Ecdsa(algorithm) => ecdsa_operation::sign(algorithm, key, message),
5130 SignAlgorithm::Ed25519(_algorithm) => ed25519_operation::sign(key, message),
5131 SignAlgorithm::Ed448(algorithm) => ed448_operation::sign(algorithm, key, message),
5132 SignAlgorithm::Hmac(_algorithm) => hmac_operation::sign(key, message),
5133 SignAlgorithm::MlDsa(algorithm) => ml_dsa_operation::sign(algorithm, key, message),
5134 SignAlgorithm::Kmac(algorithm) => kmac_operation::sign(algorithm, key, message),
5135 }
5136 }
5137}
5138
5139struct VerifyOperation {}
5141
5142impl Operation for VerifyOperation {
5143 type RegisteredAlgorithm = VerifyAlgorithm;
5144}
5145
5146enum VerifyAlgorithm {
5149 RsassaPkcs1V1_5(Algorithm),
5150 RsaPss(RsaPssParams),
5151 Ecdsa(EcdsaParams),
5152 Ed25519(Algorithm),
5153 Ed448(SubtleEd448Params),
5154 Hmac(Algorithm),
5155 MlDsa(ContextParams),
5156 Kmac(KmacParams),
5157}
5158
5159impl NormalizedAlgorithm for VerifyAlgorithm {
5160 fn from_object(
5161 cx: &mut js::context::JSContext,
5162 algorithm_name: CryptoAlgorithm,
5163 object: HandleObject,
5164 ) -> Fallible<Self> {
5165 match algorithm_name {
5166 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(VerifyAlgorithm::RsassaPkcs1V1_5(
5167 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5168 )),
5169 CryptoAlgorithm::RsaPss => Ok(VerifyAlgorithm::RsaPss(
5170 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5171 )),
5172 CryptoAlgorithm::Ecdsa => Ok(VerifyAlgorithm::Ecdsa(
5173 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5174 )),
5175 CryptoAlgorithm::Ed25519 => Ok(VerifyAlgorithm::Ed25519(
5176 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5177 )),
5178 CryptoAlgorithm::Ed448 => Ok(VerifyAlgorithm::Ed448(
5179 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5180 )),
5181 CryptoAlgorithm::Hmac => Ok(VerifyAlgorithm::Hmac(
5182 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5183 )),
5184 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5185 VerifyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5186 ),
5187 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(VerifyAlgorithm::Kmac(
5188 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5189 )),
5190 _ => Err(Error::NotSupported(Some(format!(
5191 "{} does not support \"verify\" operation",
5192 algorithm_name.as_str()
5193 )))),
5194 }
5195 }
5196
5197 fn name(&self) -> CryptoAlgorithm {
5198 match self {
5199 VerifyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5200 VerifyAlgorithm::RsaPss(algorithm) => algorithm.name,
5201 VerifyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5202 VerifyAlgorithm::Ed25519(algorithm) => algorithm.name,
5203 VerifyAlgorithm::Ed448(algorithm) => algorithm.name,
5204 VerifyAlgorithm::Hmac(algorithm) => algorithm.name,
5205 VerifyAlgorithm::MlDsa(algorithm) => algorithm.name,
5206 VerifyAlgorithm::Kmac(algorithm) => algorithm.name,
5207 }
5208 }
5209
5210 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5211 match self {
5212 VerifyAlgorithm::RsassaPkcs1V1_5(_) |
5213 VerifyAlgorithm::RsaPss(_) |
5214 VerifyAlgorithm::Ecdsa(_) |
5215 VerifyAlgorithm::Ed25519(_) => true,
5216 VerifyAlgorithm::Ed448(normalized_algorithm) => normalized_algorithm
5217 .context
5218 .as_ref()
5219 .is_none_or(|context| context.len() <= 255),
5220 VerifyAlgorithm::Hmac(_) => true,
5221 VerifyAlgorithm::MlDsa(normalized_algorithm) => normalized_algorithm
5222 .context
5223 .as_ref()
5224 .is_none_or(|context| context.len() <= 255),
5225 VerifyAlgorithm::Kmac(_) => true,
5226 }
5227 }
5228}
5229
5230impl VerifyAlgorithm {
5231 fn verify(&self, key: &CryptoKey, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
5232 match self {
5233 VerifyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
5234 rsassa_pkcs1_v1_5_operation::verify(key, message, signature)
5235 },
5236 VerifyAlgorithm::RsaPss(algorithm) => {
5237 rsa_pss_operation::verify(algorithm, key, message, signature)
5238 },
5239 VerifyAlgorithm::Ecdsa(algorithm) => {
5240 ecdsa_operation::verify(algorithm, key, message, signature)
5241 },
5242 VerifyAlgorithm::Ed25519(_algorithm) => {
5243 ed25519_operation::verify(key, message, signature)
5244 },
5245 VerifyAlgorithm::Ed448(algorithm) => {
5246 ed448_operation::verify(algorithm, key, message, signature)
5247 },
5248 VerifyAlgorithm::Hmac(_algorithm) => hmac_operation::verify(key, message, signature),
5249 VerifyAlgorithm::MlDsa(algorithm) => {
5250 ml_dsa_operation::verify(algorithm, key, message, signature)
5251 },
5252 VerifyAlgorithm::Kmac(algorithm) => {
5253 kmac_operation::verify(algorithm, key, message, signature)
5254 },
5255 }
5256 }
5257}
5258
5259struct DigestOperation {}
5261
5262impl Operation for DigestOperation {
5263 type RegisteredAlgorithm = DigestAlgorithm;
5264}
5265
5266#[derive(Clone, MallocSizeOf)]
5269enum DigestAlgorithm {
5270 Sha(Algorithm),
5271 Sha3(Algorithm),
5272 CShake(CShakeParams),
5273 TurboShake(TurboShakeParams),
5274 KangarooTwelve(KangarooTwelveParams),
5275}
5276
5277impl NormalizedAlgorithm for DigestAlgorithm {
5278 fn from_object(
5279 cx: &mut js::context::JSContext,
5280 algorithm_name: CryptoAlgorithm,
5281 object: HandleObject,
5282 ) -> Fallible<Self> {
5283 match algorithm_name {
5284 CryptoAlgorithm::Sha1 |
5285 CryptoAlgorithm::Sha256 |
5286 CryptoAlgorithm::Sha384 |
5287 CryptoAlgorithm::Sha512 => Ok(DigestAlgorithm::Sha(
5288 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5289 )),
5290 CryptoAlgorithm::Sha3_256 | CryptoAlgorithm::Sha3_384 | CryptoAlgorithm::Sha3_512 => {
5291 Ok(DigestAlgorithm::Sha3(
5292 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5293 ))
5294 },
5295 CryptoAlgorithm::CShake128 | CryptoAlgorithm::CShake256 => Ok(DigestAlgorithm::CShake(
5296 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5297 )),
5298 CryptoAlgorithm::TurboShake128 | CryptoAlgorithm::TurboShake256 => Ok(
5299 DigestAlgorithm::TurboShake(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5300 ),
5301 CryptoAlgorithm::Kt128 | CryptoAlgorithm::Kt256 => Ok(DigestAlgorithm::KangarooTwelve(
5302 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5303 )),
5304 _ => Err(Error::NotSupported(Some(format!(
5305 "{} does not support \"digest\" operation",
5306 algorithm_name.as_str()
5307 )))),
5308 }
5309 }
5310
5311 fn name(&self) -> CryptoAlgorithm {
5312 match self {
5313 DigestAlgorithm::Sha(algorithm) => algorithm.name,
5314 DigestAlgorithm::Sha3(algorithm) => algorithm.name,
5315 DigestAlgorithm::CShake(algorithm) => algorithm.name,
5316 DigestAlgorithm::TurboShake(algorithm) => algorithm.name,
5317 DigestAlgorithm::KangarooTwelve(algorithm) => algorithm.name,
5318 }
5319 }
5320
5321 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5322 match self {
5323 DigestAlgorithm::Sha(_) |
5324 DigestAlgorithm::Sha3(_) |
5325 DigestAlgorithm::CShake(_) |
5326 DigestAlgorithm::TurboShake(_) => true,
5327 DigestAlgorithm::KangarooTwelve(normalized_algorithm) => {
5328 normalized_algorithm.output_length != 0 &&
5329 normalized_algorithm.output_length.is_multiple_of(8)
5330 },
5331 }
5332 }
5333}
5334
5335impl DigestAlgorithm {
5336 fn digest(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
5337 match self {
5338 DigestAlgorithm::Sha(algorithm) => sha_operation::digest(algorithm, message),
5339 DigestAlgorithm::Sha3(algorithm) => sha3_operation::digest(algorithm, message),
5340 DigestAlgorithm::CShake(algorithm) => cshake_operation::digest(algorithm, message),
5341 DigestAlgorithm::TurboShake(algorithm) => {
5342 turboshake_operation::digest(algorithm, message)
5343 },
5344 DigestAlgorithm::KangarooTwelve(algorithm) => {
5345 kangarootwelve_operation::digest(algorithm, message)
5346 },
5347 }
5348 }
5349}
5350
5351impl TryFrom<SerializableDigestAlgorithm> for DigestAlgorithm {
5352 type Error = ();
5353
5354 fn try_from(value: SerializableDigestAlgorithm) -> Result<Self, Self::Error> {
5355 match value {
5356 SerializableDigestAlgorithm::Sha(algorithm) => {
5357 Ok(DigestAlgorithm::Sha(algorithm.try_into()?))
5358 },
5359 SerializableDigestAlgorithm::Sha3(algorithm) => {
5360 Ok(DigestAlgorithm::Sha3(algorithm.try_into()?))
5361 },
5362 SerializableDigestAlgorithm::CShake(algorithm) => {
5363 Ok(DigestAlgorithm::CShake(algorithm.try_into()?))
5364 },
5365 SerializableDigestAlgorithm::TurboShake(algorithm) => {
5366 Ok(DigestAlgorithm::TurboShake(algorithm.try_into()?))
5367 },
5368 SerializableDigestAlgorithm::KangarooTwelve(algorithm) => {
5369 Ok(DigestAlgorithm::KangarooTwelve(algorithm.try_into()?))
5370 },
5371 }
5372 }
5373}
5374
5375impl From<&DigestAlgorithm> for SerializableDigestAlgorithm {
5376 fn from(value: &DigestAlgorithm) -> Self {
5377 match value {
5378 DigestAlgorithm::Sha(algorithm) => SerializableDigestAlgorithm::Sha(algorithm.into()),
5379 DigestAlgorithm::Sha3(algorithm) => SerializableDigestAlgorithm::Sha3(algorithm.into()),
5380 DigestAlgorithm::CShake(algorithm) => {
5381 SerializableDigestAlgorithm::CShake(algorithm.into())
5382 },
5383 DigestAlgorithm::TurboShake(algorithm) => {
5384 SerializableDigestAlgorithm::TurboShake(algorithm.into())
5385 },
5386 DigestAlgorithm::KangarooTwelve(algorithm) => {
5387 SerializableDigestAlgorithm::KangarooTwelve(algorithm.into())
5388 },
5389 }
5390 }
5391}
5392
5393struct DeriveBitsOperation {}
5395
5396impl Operation for DeriveBitsOperation {
5397 type RegisteredAlgorithm = DeriveBitsAlgorithm;
5398}
5399
5400enum DeriveBitsAlgorithm {
5403 Ecdh(EcdhKeyDeriveParams),
5404 X25519(EcdhKeyDeriveParams),
5405 X448(EcdhKeyDeriveParams),
5406 Hkdf(HkdfParams),
5407 Pbkdf2(Pbkdf2Params),
5408 Argon2(Argon2Params),
5409}
5410
5411impl NormalizedAlgorithm for DeriveBitsAlgorithm {
5412 fn from_object(
5413 cx: &mut js::context::JSContext,
5414 algorithm_name: CryptoAlgorithm,
5415 object: HandleObject,
5416 ) -> Fallible<Self> {
5417 match algorithm_name {
5418 CryptoAlgorithm::Ecdh => Ok(DeriveBitsAlgorithm::Ecdh(
5419 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5420 )),
5421 CryptoAlgorithm::X25519 => Ok(DeriveBitsAlgorithm::X25519(
5422 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5423 )),
5424 CryptoAlgorithm::X448 => Ok(DeriveBitsAlgorithm::X448(
5425 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5426 )),
5427 CryptoAlgorithm::Hkdf => Ok(DeriveBitsAlgorithm::Hkdf(
5428 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5429 )),
5430 CryptoAlgorithm::Pbkdf2 => Ok(DeriveBitsAlgorithm::Pbkdf2(
5431 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5432 )),
5433 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
5434 DeriveBitsAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5435 ),
5436 _ => Err(Error::NotSupported(Some(format!(
5437 "{} does not support \"deriveBits\" operation",
5438 algorithm_name.as_str()
5439 )))),
5440 }
5441 }
5442
5443 fn name(&self) -> CryptoAlgorithm {
5444 match self {
5445 DeriveBitsAlgorithm::Ecdh(algorithm) => algorithm.name,
5446 DeriveBitsAlgorithm::X25519(algorithm) => algorithm.name,
5447 DeriveBitsAlgorithm::X448(algorithm) => algorithm.name,
5448 DeriveBitsAlgorithm::Hkdf(algorithm) => algorithm.name,
5449 DeriveBitsAlgorithm::Pbkdf2(algorithm) => algorithm.name,
5450 DeriveBitsAlgorithm::Argon2(algorithm) => algorithm.name,
5451 }
5452 }
5453
5454 fn determine_support_from_operation_steps(&self, length: Option<u32>) -> bool {
5455 match self {
5456 DeriveBitsAlgorithm::Ecdh(normalized_algorithm) => {
5457 let public_key = normalized_algorithm.public.root();
5458 let Ok(maximum_length) = ecdh_operation::maximum_length(&public_key) else {
5459 return false;
5460 };
5461 public_key.Type() == KeyType::Public &&
5462 public_key.algorithm().name() == normalized_algorithm.name &&
5463 length.is_none_or(|length| length <= maximum_length)
5464 },
5465 DeriveBitsAlgorithm::X25519(normalized_algorithm) => {
5466 let public_key = normalized_algorithm.public.root();
5467 public_key.Type() == KeyType::Public &&
5468 public_key.algorithm().name() == normalized_algorithm.name &&
5469 length.is_none_or(|length| length <= 256)
5470 },
5471 DeriveBitsAlgorithm::X448(_) => {
5472 length.is_none_or(|length| x448_operation::SECRET_LENGTH as u32 * 8 >= length)
5473 },
5474 DeriveBitsAlgorithm::Hkdf(normalized_algorithm) => {
5475 let hash_length = match normalized_algorithm.hash.name() {
5476 CryptoAlgorithm::Sha1 => 160,
5477 CryptoAlgorithm::Sha256 => 256,
5478 CryptoAlgorithm::Sha384 => 384,
5479 CryptoAlgorithm::Sha512 => 512,
5480 _ => return false,
5481 };
5482 length.is_some_and(|length| length % 8 == 0 && length <= 255 * hash_length)
5483 },
5484 DeriveBitsAlgorithm::Pbkdf2(normalized_algorithm) => {
5485 length.is_some_and(|length| length % 8 == 0) && normalized_algorithm.iterations != 0
5486 },
5487 DeriveBitsAlgorithm::Argon2(normalized_algorithm) => {
5488 length.is_some_and(|length| length >= 32 && length % 8 == 0) &&
5489 normalized_algorithm
5490 .version
5491 .is_none_or(|version| version == 19) &&
5492 normalized_algorithm.parallelism != 0 &&
5493 normalized_algorithm.parallelism <= 16777215 &&
5494 normalized_algorithm.memory >= 8 * normalized_algorithm.parallelism &&
5495 normalized_algorithm.passes != 0
5496 },
5497 }
5498 }
5499}
5500
5501impl DeriveBitsAlgorithm {
5502 fn derive_bits(&self, key: &CryptoKey, length: Option<u32>) -> Result<Vec<u8>, Error> {
5503 match self {
5504 DeriveBitsAlgorithm::Ecdh(algorithm) => {
5505 ecdh_operation::derive_bits(algorithm, key, length)
5506 },
5507 DeriveBitsAlgorithm::X25519(algorithm) => {
5508 x25519_operation::derive_bits(algorithm, key, length)
5509 },
5510 DeriveBitsAlgorithm::X448(algorithm) => {
5511 x448_operation::derive_bits(algorithm, key, length)
5512 },
5513 DeriveBitsAlgorithm::Hkdf(algorithm) => {
5514 hkdf_operation::derive_bits(algorithm, key, length)
5515 },
5516 DeriveBitsAlgorithm::Pbkdf2(algorithm) => {
5517 pbkdf2_operation::derive_bits(algorithm, key, length)
5518 },
5519 DeriveBitsAlgorithm::Argon2(algorithm) => {
5520 argon2_operation::derive_bits(algorithm, key, length)
5521 },
5522 }
5523 }
5524}
5525
5526struct WrapKeyOperation {}
5528
5529impl Operation for WrapKeyOperation {
5530 type RegisteredAlgorithm = WrapKeyAlgorithm;
5531}
5532
5533enum WrapKeyAlgorithm {
5536 AesKw(Algorithm),
5537}
5538
5539impl NormalizedAlgorithm for WrapKeyAlgorithm {
5540 fn from_object(
5541 cx: &mut js::context::JSContext,
5542 algorithm_name: CryptoAlgorithm,
5543 object: HandleObject,
5544 ) -> Fallible<Self> {
5545 match algorithm_name {
5546 CryptoAlgorithm::AesKw => Ok(WrapKeyAlgorithm::AesKw(
5547 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5548 )),
5549 _ => Err(Error::NotSupported(Some(format!(
5550 "{} does not support \"wrapKey\" operation",
5551 algorithm_name.as_str()
5552 )))),
5553 }
5554 }
5555
5556 fn name(&self) -> CryptoAlgorithm {
5557 match self {
5558 WrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5559 }
5560 }
5561
5562 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5563 match self {
5564 WrapKeyAlgorithm::AesKw(_) => true,
5565 }
5566 }
5567}
5568
5569impl WrapKeyAlgorithm {
5570 fn wrap_key(&self, key: &CryptoKey, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
5571 match self {
5572 WrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::wrap_key(key, plaintext),
5573 }
5574 }
5575}
5576
5577struct UnwrapKeyOperation {}
5579
5580impl Operation for UnwrapKeyOperation {
5581 type RegisteredAlgorithm = UnwrapKeyAlgorithm;
5582}
5583
5584enum UnwrapKeyAlgorithm {
5587 AesKw(Algorithm),
5588}
5589
5590impl NormalizedAlgorithm for UnwrapKeyAlgorithm {
5591 fn from_object(
5592 cx: &mut js::context::JSContext,
5593 algorithm_name: CryptoAlgorithm,
5594 object: HandleObject,
5595 ) -> Fallible<Self> {
5596 match algorithm_name {
5597 CryptoAlgorithm::AesKw => Ok(UnwrapKeyAlgorithm::AesKw(
5598 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5599 )),
5600 _ => Err(Error::NotSupported(Some(format!(
5601 "{} does not support \"unwrapKey\" operation",
5602 algorithm_name.as_str()
5603 )))),
5604 }
5605 }
5606
5607 fn name(&self) -> CryptoAlgorithm {
5608 match self {
5609 UnwrapKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5610 }
5611 }
5612
5613 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5614 match self {
5615 UnwrapKeyAlgorithm::AesKw(_) => true,
5616 }
5617 }
5618}
5619
5620impl UnwrapKeyAlgorithm {
5621 fn unwrap_key(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
5622 match self {
5623 UnwrapKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::unwrap_key(key, ciphertext),
5624 }
5625 }
5626}
5627
5628struct GenerateKeyOperation {}
5630
5631impl Operation for GenerateKeyOperation {
5632 type RegisteredAlgorithm = GenerateKeyAlgorithm;
5633}
5634
5635enum GenerateKeyAlgorithm {
5638 RsassaPkcs1V1_5(RsaHashedKeyGenParams),
5639 RsaPss(RsaHashedKeyGenParams),
5640 RsaOaep(RsaHashedKeyGenParams),
5641 Ecdsa(EcKeyGenParams),
5642 Ecdh(EcKeyGenParams),
5643 Ed25519(Algorithm),
5644 X25519(Algorithm),
5645 Ed448(Algorithm),
5646 X448(Algorithm),
5647 AesCtr(AesKeyGenParams),
5648 AesCbc(AesKeyGenParams),
5649 AesGcm(AesKeyGenParams),
5650 AesKw(AesKeyGenParams),
5651 Hmac(HmacKeyGenParams),
5652 MlKem(Algorithm),
5653 HybridKem(Algorithm),
5654 MlDsa(Algorithm),
5655 AesOcb(AesKeyGenParams),
5656 ChaCha20Poly1305(Algorithm),
5657 Kmac(KmacKeyGenParams),
5658}
5659
5660impl NormalizedAlgorithm for GenerateKeyAlgorithm {
5661 fn from_object(
5662 cx: &mut js::context::JSContext,
5663 algorithm_name: CryptoAlgorithm,
5664 object: HandleObject,
5665 ) -> Fallible<Self> {
5666 match algorithm_name {
5667 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GenerateKeyAlgorithm::RsassaPkcs1V1_5(
5668 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5669 )),
5670 CryptoAlgorithm::RsaPss => Ok(GenerateKeyAlgorithm::RsaPss(
5671 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5672 )),
5673 CryptoAlgorithm::RsaOaep => Ok(GenerateKeyAlgorithm::RsaOaep(
5674 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5675 )),
5676 CryptoAlgorithm::Ecdsa => Ok(GenerateKeyAlgorithm::Ecdsa(
5677 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5678 )),
5679 CryptoAlgorithm::Ecdh => Ok(GenerateKeyAlgorithm::Ecdh(
5680 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5681 )),
5682 CryptoAlgorithm::Ed25519 => Ok(GenerateKeyAlgorithm::Ed25519(
5683 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5684 )),
5685 CryptoAlgorithm::X25519 => Ok(GenerateKeyAlgorithm::X25519(
5686 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5687 )),
5688 CryptoAlgorithm::Ed448 => Ok(GenerateKeyAlgorithm::Ed448(
5689 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5690 )),
5691 CryptoAlgorithm::X448 => Ok(GenerateKeyAlgorithm::X448(
5692 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5693 )),
5694 CryptoAlgorithm::AesCtr => Ok(GenerateKeyAlgorithm::AesCtr(
5695 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5696 )),
5697 CryptoAlgorithm::AesCbc => Ok(GenerateKeyAlgorithm::AesCbc(
5698 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5699 )),
5700 CryptoAlgorithm::AesGcm => Ok(GenerateKeyAlgorithm::AesGcm(
5701 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5702 )),
5703 CryptoAlgorithm::AesKw => Ok(GenerateKeyAlgorithm::AesKw(
5704 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5705 )),
5706 CryptoAlgorithm::Hmac => Ok(GenerateKeyAlgorithm::Hmac(
5707 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5708 )),
5709 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5710 Ok(GenerateKeyAlgorithm::MlKem(
5711 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5712 ))
5713 },
5714 CryptoAlgorithm::MlKem768X25519 => Ok(GenerateKeyAlgorithm::HybridKem(
5715 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5716 )),
5717 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5718 GenerateKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5719 ),
5720 CryptoAlgorithm::AesOcb => Ok(GenerateKeyAlgorithm::AesOcb(
5721 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5722 )),
5723 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GenerateKeyAlgorithm::ChaCha20Poly1305(
5724 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5725 )),
5726 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GenerateKeyAlgorithm::Kmac(
5727 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5728 )),
5729 _ => Err(Error::NotSupported(Some(format!(
5730 "{} does not support \"generateKey\" operation",
5731 algorithm_name.as_str()
5732 )))),
5733 }
5734 }
5735
5736 fn name(&self) -> CryptoAlgorithm {
5737 match self {
5738 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
5739 GenerateKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
5740 GenerateKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
5741 GenerateKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
5742 GenerateKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
5743 GenerateKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
5744 GenerateKeyAlgorithm::X25519(algorithm) => algorithm.name,
5745 GenerateKeyAlgorithm::Ed448(algorithm) => algorithm.name,
5746 GenerateKeyAlgorithm::X448(algorithm) => algorithm.name,
5747 GenerateKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
5748 GenerateKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
5749 GenerateKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
5750 GenerateKeyAlgorithm::AesKw(algorithm) => algorithm.name,
5751 GenerateKeyAlgorithm::Hmac(algorithm) => algorithm.name,
5752 GenerateKeyAlgorithm::MlKem(algorithm) => algorithm.name,
5753 GenerateKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
5754 GenerateKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
5755 GenerateKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
5756 GenerateKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
5757 GenerateKeyAlgorithm::Kmac(algorithm) => algorithm.name,
5758 }
5759 }
5760
5761 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
5762 match self {
5763 GenerateKeyAlgorithm::RsassaPkcs1V1_5(normalized_algorithm) |
5764 GenerateKeyAlgorithm::RsaPss(normalized_algorithm) |
5765 GenerateKeyAlgorithm::RsaOaep(normalized_algorithm) => {
5766 normalized_algorithm.validate_parameters().is_ok()
5767 },
5768 GenerateKeyAlgorithm::Ecdsa(normalized_algorithm) |
5769 GenerateKeyAlgorithm::Ecdh(normalized_algorithm) => {
5770 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
5771 },
5772 GenerateKeyAlgorithm::Ed25519(_) |
5773 GenerateKeyAlgorithm::X25519(_) |
5774 GenerateKeyAlgorithm::Ed448(_) |
5775 GenerateKeyAlgorithm::X448(_) => true,
5776 GenerateKeyAlgorithm::AesCtr(normalized_algorithm) |
5777 GenerateKeyAlgorithm::AesCbc(normalized_algorithm) |
5778 GenerateKeyAlgorithm::AesGcm(normalized_algorithm) |
5779 GenerateKeyAlgorithm::AesKw(normalized_algorithm) => {
5780 matches!(normalized_algorithm.length, 128 | 192 | 256)
5781 },
5782 GenerateKeyAlgorithm::Hmac(normalized_algorithm) => {
5783 normalized_algorithm.length.is_none_or(|length| length != 0)
5784 },
5785 GenerateKeyAlgorithm::MlKem(_) |
5786 GenerateKeyAlgorithm::HybridKem(_) |
5787 GenerateKeyAlgorithm::MlDsa(_) => true,
5788 GenerateKeyAlgorithm::AesOcb(normalized_algorithm) => {
5789 matches!(normalized_algorithm.length, 128 | 192 | 256)
5790 },
5791 GenerateKeyAlgorithm::ChaCha20Poly1305(_) | GenerateKeyAlgorithm::Kmac(_) => true,
5792 }
5793 }
5794}
5795
5796impl GenerateKeyAlgorithm {
5797 fn generate_key(
5798 &self,
5799 cx: &mut js::context::JSContext,
5800 global: &GlobalScope,
5801 extractable: bool,
5802 usages: Vec<KeyUsage>,
5803 ) -> Result<CryptoKeyOrCryptoKeyPair, Error> {
5804 match self {
5805 GenerateKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
5806 rsassa_pkcs1_v1_5_operation::generate_key(
5807 cx,
5808 global,
5809 algorithm,
5810 extractable,
5811 usages,
5812 )
5813 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5814 },
5815 GenerateKeyAlgorithm::RsaPss(algorithm) => {
5816 rsa_pss_operation::generate_key(cx, global, algorithm, extractable, usages)
5817 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5818 },
5819 GenerateKeyAlgorithm::RsaOaep(algorithm) => {
5820 rsa_oaep_operation::generate_key(cx, global, algorithm, extractable, usages)
5821 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5822 },
5823 GenerateKeyAlgorithm::Ecdsa(algorithm) => {
5824 ecdsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5825 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5826 },
5827 GenerateKeyAlgorithm::Ecdh(algorithm) => {
5828 ecdh_operation::generate_key(cx, global, algorithm, extractable, usages)
5829 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5830 },
5831 GenerateKeyAlgorithm::Ed25519(_algorithm) => {
5832 ed25519_operation::generate_key(cx, global, extractable, usages)
5833 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5834 },
5835 GenerateKeyAlgorithm::X25519(_algorithm) => {
5836 x25519_operation::generate_key(cx, global, extractable, usages)
5837 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5838 },
5839 GenerateKeyAlgorithm::Ed448(_algorithm) => {
5840 ed448_operation::generate_key(cx, global, extractable, usages)
5841 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5842 },
5843 GenerateKeyAlgorithm::X448(_algorithm) => {
5844 x448_operation::generate_key(cx, global, extractable, usages)
5845 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5846 },
5847 GenerateKeyAlgorithm::AesCtr(algorithm) => {
5848 aes_ctr_operation::generate_key(cx, global, algorithm, extractable, usages)
5849 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5850 },
5851 GenerateKeyAlgorithm::AesCbc(algorithm) => {
5852 aes_cbc_operation::generate_key(cx, global, algorithm, extractable, usages)
5853 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5854 },
5855 GenerateKeyAlgorithm::AesGcm(algorithm) => {
5856 aes_gcm_operation::generate_key(cx, global, algorithm, extractable, usages)
5857 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5858 },
5859 GenerateKeyAlgorithm::AesKw(algorithm) => {
5860 aes_kw_operation::generate_key(cx, global, algorithm, extractable, usages)
5861 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5862 },
5863 GenerateKeyAlgorithm::Hmac(algorithm) => {
5864 hmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5865 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5866 },
5867 GenerateKeyAlgorithm::MlKem(algorithm) => {
5868 ml_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5869 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5870 },
5871 GenerateKeyAlgorithm::HybridKem(algorithm) => {
5872 hybrid_kem_operation::generate_key(cx, global, algorithm, extractable, usages)
5873 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5874 },
5875 GenerateKeyAlgorithm::MlDsa(algorithm) => {
5876 ml_dsa_operation::generate_key(cx, global, algorithm, extractable, usages)
5877 .map(CryptoKeyOrCryptoKeyPair::CryptoKeyPair)
5878 },
5879 GenerateKeyAlgorithm::AesOcb(algorithm) => {
5880 aes_ocb_operation::generate_key(cx, global, algorithm, extractable, usages)
5881 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5882 },
5883 GenerateKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
5884 chacha20_poly1305_operation::generate_key(cx, global, extractable, usages)
5885 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5886 },
5887 GenerateKeyAlgorithm::Kmac(algorithm) => {
5888 kmac_operation::generate_key(cx, global, algorithm, extractable, usages)
5889 .map(CryptoKeyOrCryptoKeyPair::CryptoKey)
5890 },
5891 }
5892 }
5893}
5894
5895struct ImportKeyOperation {}
5897
5898impl Operation for ImportKeyOperation {
5899 type RegisteredAlgorithm = ImportKeyAlgorithm;
5900}
5901
5902enum ImportKeyAlgorithm {
5905 RsassaPkcs1V1_5(RsaHashedImportParams),
5906 RsaPss(RsaHashedImportParams),
5907 RsaOaep(RsaHashedImportParams),
5908 Ecdsa(EcKeyImportParams),
5909 Ecdh(EcKeyImportParams),
5910 Ed25519(Algorithm),
5911 X25519(Algorithm),
5912 Ed448(Algorithm),
5913 X448(Algorithm),
5914 AesCtr(Algorithm),
5915 AesCbc(Algorithm),
5916 AesGcm(Algorithm),
5917 AesKw(Algorithm),
5918 Hmac(HmacImportParams),
5919 Hkdf(Algorithm),
5920 Pbkdf2(Algorithm),
5921 MlKem(Algorithm),
5922 HybridKem(Algorithm),
5923 MlDsa(Algorithm),
5924 AesOcb(Algorithm),
5925 ChaCha20Poly1305(Algorithm),
5926 Kmac(KmacImportParams),
5927 Argon2(Algorithm),
5928}
5929
5930impl NormalizedAlgorithm for ImportKeyAlgorithm {
5931 fn from_object(
5932 cx: &mut js::context::JSContext,
5933 algorithm_name: CryptoAlgorithm,
5934 object: HandleObject,
5935 ) -> Fallible<Self> {
5936 match algorithm_name {
5937 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ImportKeyAlgorithm::RsassaPkcs1V1_5(
5938 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5939 )),
5940 CryptoAlgorithm::RsaPss => Ok(ImportKeyAlgorithm::RsaPss(
5941 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5942 )),
5943 CryptoAlgorithm::RsaOaep => Ok(ImportKeyAlgorithm::RsaOaep(
5944 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5945 )),
5946 CryptoAlgorithm::Ecdsa => Ok(ImportKeyAlgorithm::Ecdsa(
5947 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5948 )),
5949 CryptoAlgorithm::Ecdh => Ok(ImportKeyAlgorithm::Ecdh(
5950 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5951 )),
5952 CryptoAlgorithm::Ed25519 => Ok(ImportKeyAlgorithm::Ed25519(
5953 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5954 )),
5955 CryptoAlgorithm::X25519 => Ok(ImportKeyAlgorithm::X25519(
5956 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5957 )),
5958 CryptoAlgorithm::Ed448 => Ok(ImportKeyAlgorithm::Ed448(
5959 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5960 )),
5961 CryptoAlgorithm::X448 => Ok(ImportKeyAlgorithm::X448(
5962 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5963 )),
5964 CryptoAlgorithm::AesCtr => Ok(ImportKeyAlgorithm::AesCtr(
5965 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5966 )),
5967 CryptoAlgorithm::AesCbc => Ok(ImportKeyAlgorithm::AesCbc(
5968 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5969 )),
5970 CryptoAlgorithm::AesGcm => Ok(ImportKeyAlgorithm::AesGcm(
5971 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5972 )),
5973 CryptoAlgorithm::AesKw => Ok(ImportKeyAlgorithm::AesKw(
5974 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5975 )),
5976 CryptoAlgorithm::Hmac => Ok(ImportKeyAlgorithm::Hmac(
5977 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5978 )),
5979 CryptoAlgorithm::Hkdf => Ok(ImportKeyAlgorithm::Hkdf(
5980 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5981 )),
5982 CryptoAlgorithm::Pbkdf2 => Ok(ImportKeyAlgorithm::Pbkdf2(
5983 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5984 )),
5985 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
5986 Ok(ImportKeyAlgorithm::MlKem(
5987 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5988 ))
5989 },
5990 CryptoAlgorithm::MlKem768X25519 => Ok(ImportKeyAlgorithm::HybridKem(
5991 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5992 )),
5993 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
5994 ImportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
5995 ),
5996 CryptoAlgorithm::AesOcb => Ok(ImportKeyAlgorithm::AesOcb(
5997 object.try_into_with_cx_and_name(cx, algorithm_name)?,
5998 )),
5999 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ImportKeyAlgorithm::ChaCha20Poly1305(
6000 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6001 )),
6002 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ImportKeyAlgorithm::Kmac(
6003 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6004 )),
6005 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => Ok(
6006 ImportKeyAlgorithm::Argon2(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6007 ),
6008 _ => Err(Error::NotSupported(Some(format!(
6009 "{} does not support \"importKey\" operation",
6010 algorithm_name.as_str()
6011 )))),
6012 }
6013 }
6014
6015 fn name(&self) -> CryptoAlgorithm {
6016 match self {
6017 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6018 ImportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6019 ImportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6020 ImportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6021 ImportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6022 ImportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6023 ImportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6024 ImportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6025 ImportKeyAlgorithm::X448(algorithm) => algorithm.name,
6026 ImportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6027 ImportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6028 ImportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6029 ImportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6030 ImportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6031 ImportKeyAlgorithm::Hkdf(algorithm) => algorithm.name,
6032 ImportKeyAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6033 ImportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6034 ImportKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
6035 ImportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6036 ImportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6037 ImportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6038 ImportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6039 ImportKeyAlgorithm::Argon2(algorithm) => algorithm.name,
6040 }
6041 }
6042
6043 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6044 match self {
6045 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6046 ImportKeyAlgorithm::RsaPss(_) |
6047 ImportKeyAlgorithm::RsaOaep(_) => true,
6048 ImportKeyAlgorithm::Ecdsa(normalized_algorithm) |
6049 ImportKeyAlgorithm::Ecdh(normalized_algorithm) => {
6050 SUPPORTED_CURVES.contains(&normalized_algorithm.named_curve.as_str())
6051 },
6052 ImportKeyAlgorithm::Ed25519(_) |
6053 ImportKeyAlgorithm::X25519(_) |
6054 ImportKeyAlgorithm::Ed448(_) |
6055 ImportKeyAlgorithm::X448(_) |
6056 ImportKeyAlgorithm::AesCtr(_) |
6057 ImportKeyAlgorithm::AesCbc(_) |
6058 ImportKeyAlgorithm::AesGcm(_) |
6059 ImportKeyAlgorithm::AesKw(_) => true,
6060 ImportKeyAlgorithm::Hmac(normalized_algorithm) => {
6061 normalized_algorithm.length.is_none_or(|length| length != 0)
6062 },
6063 ImportKeyAlgorithm::Hkdf(_) |
6064 ImportKeyAlgorithm::Pbkdf2(_) |
6065 ImportKeyAlgorithm::MlKem(_) |
6066 ImportKeyAlgorithm::HybridKem(_) |
6067 ImportKeyAlgorithm::MlDsa(_) |
6068 ImportKeyAlgorithm::AesOcb(_) |
6069 ImportKeyAlgorithm::ChaCha20Poly1305(_) |
6070 ImportKeyAlgorithm::Kmac(_) |
6071 ImportKeyAlgorithm::Argon2(_) => true,
6072 }
6073 }
6074}
6075
6076impl ImportKeyAlgorithm {
6077 fn import_key(
6078 &self,
6079 cx: &mut js::context::JSContext,
6080 global: &GlobalScope,
6081 format: KeyFormat,
6082 key_data: &[u8],
6083 extractable: bool,
6084 usages: Vec<KeyUsage>,
6085 ) -> Result<DomRoot<CryptoKey>, Error> {
6086 match self {
6087 ImportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => {
6088 rsassa_pkcs1_v1_5_operation::import_key(
6089 cx,
6090 global,
6091 algorithm,
6092 format,
6093 key_data,
6094 extractable,
6095 usages,
6096 )
6097 },
6098 ImportKeyAlgorithm::RsaPss(algorithm) => rsa_pss_operation::import_key(
6099 cx,
6100 global,
6101 algorithm,
6102 format,
6103 key_data,
6104 extractable,
6105 usages,
6106 ),
6107 ImportKeyAlgorithm::RsaOaep(algorithm) => rsa_oaep_operation::import_key(
6108 cx,
6109 global,
6110 algorithm,
6111 format,
6112 key_data,
6113 extractable,
6114 usages,
6115 ),
6116 ImportKeyAlgorithm::Ecdsa(algorithm) => ecdsa_operation::import_key(
6117 cx,
6118 global,
6119 algorithm,
6120 format,
6121 key_data,
6122 extractable,
6123 usages,
6124 ),
6125 ImportKeyAlgorithm::Ecdh(algorithm) => ecdh_operation::import_key(
6126 cx,
6127 global,
6128 algorithm,
6129 format,
6130 key_data,
6131 extractable,
6132 usages,
6133 ),
6134 ImportKeyAlgorithm::Ed25519(_algorithm) => {
6135 ed25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6136 },
6137 ImportKeyAlgorithm::X25519(_algorithm) => {
6138 x25519_operation::import_key(cx, global, format, key_data, extractable, usages)
6139 },
6140 ImportKeyAlgorithm::Ed448(_algorithm) => {
6141 ed448_operation::import_key(cx, global, format, key_data, extractable, usages)
6142 },
6143 ImportKeyAlgorithm::X448(_algorithm) => {
6144 x448_operation::import_key(cx, global, format, key_data, extractable, usages)
6145 },
6146 ImportKeyAlgorithm::AesCtr(_algorithm) => {
6147 aes_ctr_operation::import_key(cx, global, format, key_data, extractable, usages)
6148 },
6149 ImportKeyAlgorithm::AesCbc(_algorithm) => {
6150 aes_cbc_operation::import_key(cx, global, format, key_data, extractable, usages)
6151 },
6152 ImportKeyAlgorithm::AesGcm(_algorithm) => {
6153 aes_gcm_operation::import_key(cx, global, format, key_data, extractable, usages)
6154 },
6155 ImportKeyAlgorithm::AesKw(_algorithm) => {
6156 aes_kw_operation::import_key(cx, global, format, key_data, extractable, usages)
6157 },
6158 ImportKeyAlgorithm::Hmac(algorithm) => hmac_operation::import_key(
6159 cx,
6160 global,
6161 algorithm,
6162 format,
6163 key_data,
6164 extractable,
6165 usages,
6166 ),
6167 ImportKeyAlgorithm::Hkdf(_algorithm) => {
6168 hkdf_operation::import_key(cx, global, format, key_data, extractable, usages)
6169 },
6170 ImportKeyAlgorithm::Pbkdf2(_algorithm) => {
6171 pbkdf2_operation::import_key(cx, global, format, key_data, extractable, usages)
6172 },
6173 ImportKeyAlgorithm::MlKem(algorithm) => ml_kem_operation::import_key(
6174 cx,
6175 global,
6176 algorithm,
6177 format,
6178 key_data,
6179 extractable,
6180 usages,
6181 ),
6182 ImportKeyAlgorithm::HybridKem(algorithm) => hybrid_kem_operation::import_key(
6183 cx,
6184 global,
6185 algorithm,
6186 format,
6187 key_data,
6188 extractable,
6189 usages,
6190 ),
6191 ImportKeyAlgorithm::MlDsa(algorithm) => ml_dsa_operation::import_key(
6192 cx,
6193 global,
6194 algorithm,
6195 format,
6196 key_data,
6197 extractable,
6198 usages,
6199 ),
6200 ImportKeyAlgorithm::AesOcb(_algorithm) => {
6201 aes_ocb_operation::import_key(cx, global, format, key_data, extractable, usages)
6202 },
6203 ImportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6204 chacha20_poly1305_operation::import_key(
6205 cx,
6206 global,
6207 format,
6208 key_data,
6209 extractable,
6210 usages,
6211 )
6212 },
6213 ImportKeyAlgorithm::Kmac(algorithm) => kmac_operation::import_key(
6214 cx,
6215 global,
6216 algorithm,
6217 format,
6218 key_data,
6219 extractable,
6220 usages,
6221 ),
6222 ImportKeyAlgorithm::Argon2(algorithm) => argon2_operation::import_key(
6223 cx,
6224 global,
6225 algorithm,
6226 format,
6227 key_data,
6228 extractable,
6229 usages,
6230 ),
6231 }
6232 }
6233
6234 fn will_throw_for_key_data_length(&self, key_data_length: u32) -> bool {
6238 match self {
6239 ImportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6240 ImportKeyAlgorithm::RsaPss(_) |
6241 ImportKeyAlgorithm::RsaOaep(_) |
6242 ImportKeyAlgorithm::Ecdsa(_) |
6243 ImportKeyAlgorithm::Ecdh(_) |
6244 ImportKeyAlgorithm::Ed25519(_) |
6245 ImportKeyAlgorithm::X25519(_) |
6246 ImportKeyAlgorithm::Ed448(_) |
6247 ImportKeyAlgorithm::X448(_) => true,
6248 ImportKeyAlgorithm::AesCtr(_) |
6249 ImportKeyAlgorithm::AesCbc(_) |
6250 ImportKeyAlgorithm::AesGcm(_) |
6251 ImportKeyAlgorithm::AesKw(_) => !matches!(key_data_length, 128 | 192 | 256),
6252 ImportKeyAlgorithm::Hmac(algorithm) => {
6253 key_data_length == 0 ||
6254 algorithm.length.is_some_and(|length| {
6255 length > key_data_length || length + 8 <= key_data_length
6256 })
6257 },
6258 ImportKeyAlgorithm::Hkdf(_) | ImportKeyAlgorithm::Pbkdf2(_) => false,
6259 ImportKeyAlgorithm::MlKem(_) |
6260 ImportKeyAlgorithm::HybridKem(_) |
6261 ImportKeyAlgorithm::MlDsa(_) => true,
6262 ImportKeyAlgorithm::AesOcb(_) => !matches!(key_data_length, 128 | 192 | 256),
6263 ImportKeyAlgorithm::ChaCha20Poly1305(_) => key_data_length != 256,
6264 ImportKeyAlgorithm::Kmac(algorithm) => algorithm
6265 .length
6266 .is_some_and(|length| length > key_data_length || length + 8 <= key_data_length),
6267 ImportKeyAlgorithm::Argon2(_) => false,
6268 }
6269 }
6270}
6271
6272struct ExportKeyOperation {}
6274
6275impl Operation for ExportKeyOperation {
6276 type RegisteredAlgorithm = ExportKeyAlgorithm;
6277}
6278
6279enum ExportKeyAlgorithm {
6282 RsassaPkcs1V1_5(Algorithm),
6283 RsaPss(Algorithm),
6284 RsaOaep(Algorithm),
6285 Ecdsa(Algorithm),
6286 Ecdh(Algorithm),
6287 Ed25519(Algorithm),
6288 X25519(Algorithm),
6289 Ed448(Algorithm),
6290 X448(Algorithm),
6291 AesCtr(Algorithm),
6292 AesCbc(Algorithm),
6293 AesGcm(Algorithm),
6294 AesKw(Algorithm),
6295 Hmac(Algorithm),
6296 MlKem(Algorithm),
6297 HybridKem(Algorithm),
6298 MlDsa(Algorithm),
6299 AesOcb(Algorithm),
6300 ChaCha20Poly1305(Algorithm),
6301 Kmac(Algorithm),
6302}
6303
6304impl NormalizedAlgorithm for ExportKeyAlgorithm {
6305 fn from_object(
6306 cx: &mut js::context::JSContext,
6307 algorithm_name: CryptoAlgorithm,
6308 object: HandleObject,
6309 ) -> Fallible<Self> {
6310 match algorithm_name {
6311 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(ExportKeyAlgorithm::RsassaPkcs1V1_5(
6312 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6313 )),
6314 CryptoAlgorithm::RsaPss => Ok(ExportKeyAlgorithm::RsaPss(
6315 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6316 )),
6317 CryptoAlgorithm::RsaOaep => Ok(ExportKeyAlgorithm::RsaOaep(
6318 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6319 )),
6320 CryptoAlgorithm::Ecdsa => Ok(ExportKeyAlgorithm::Ecdsa(
6321 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6322 )),
6323 CryptoAlgorithm::Ecdh => Ok(ExportKeyAlgorithm::Ecdh(
6324 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6325 )),
6326 CryptoAlgorithm::Ed25519 => Ok(ExportKeyAlgorithm::Ed25519(
6327 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6328 )),
6329 CryptoAlgorithm::X25519 => Ok(ExportKeyAlgorithm::X25519(
6330 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6331 )),
6332 CryptoAlgorithm::Ed448 => Ok(ExportKeyAlgorithm::Ed448(
6333 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6334 )),
6335 CryptoAlgorithm::X448 => Ok(ExportKeyAlgorithm::X448(
6336 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6337 )),
6338 CryptoAlgorithm::AesCtr => Ok(ExportKeyAlgorithm::AesCtr(
6339 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6340 )),
6341 CryptoAlgorithm::AesCbc => Ok(ExportKeyAlgorithm::AesCbc(
6342 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6343 )),
6344 CryptoAlgorithm::AesGcm => Ok(ExportKeyAlgorithm::AesGcm(
6345 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6346 )),
6347 CryptoAlgorithm::AesKw => Ok(ExportKeyAlgorithm::AesKw(
6348 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6349 )),
6350 CryptoAlgorithm::Hmac => Ok(ExportKeyAlgorithm::Hmac(
6351 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6352 )),
6353 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6354 Ok(ExportKeyAlgorithm::MlKem(
6355 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6356 ))
6357 },
6358 CryptoAlgorithm::MlKem768X25519 => Ok(ExportKeyAlgorithm::HybridKem(
6359 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6360 )),
6361 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6362 ExportKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6363 ),
6364 CryptoAlgorithm::AesOcb => Ok(ExportKeyAlgorithm::AesOcb(
6365 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6366 )),
6367 CryptoAlgorithm::ChaCha20Poly1305 => Ok(ExportKeyAlgorithm::ChaCha20Poly1305(
6368 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6369 )),
6370 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(ExportKeyAlgorithm::Kmac(
6371 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6372 )),
6373 _ => Err(Error::NotSupported(Some(format!(
6374 "{} does not support \"exportKey\" operation",
6375 algorithm_name.as_str()
6376 )))),
6377 }
6378 }
6379
6380 fn name(&self) -> CryptoAlgorithm {
6381 match self {
6382 ExportKeyAlgorithm::RsassaPkcs1V1_5(algorithm) => algorithm.name,
6383 ExportKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6384 ExportKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6385 ExportKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6386 ExportKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6387 ExportKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6388 ExportKeyAlgorithm::X25519(algorithm) => algorithm.name,
6389 ExportKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6390 ExportKeyAlgorithm::X448(algorithm) => algorithm.name,
6391 ExportKeyAlgorithm::AesCtr(algorithm) => algorithm.name,
6392 ExportKeyAlgorithm::AesCbc(algorithm) => algorithm.name,
6393 ExportKeyAlgorithm::AesGcm(algorithm) => algorithm.name,
6394 ExportKeyAlgorithm::AesKw(algorithm) => algorithm.name,
6395 ExportKeyAlgorithm::Hmac(algorithm) => algorithm.name,
6396 ExportKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6397 ExportKeyAlgorithm::HybridKem(algorithm) => algorithm.name,
6398 ExportKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6399 ExportKeyAlgorithm::AesOcb(algorithm) => algorithm.name,
6400 ExportKeyAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6401 ExportKeyAlgorithm::Kmac(algorithm) => algorithm.name,
6402 }
6403 }
6404
6405 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6406 match self {
6407 ExportKeyAlgorithm::RsassaPkcs1V1_5(_) |
6408 ExportKeyAlgorithm::RsaPss(_) |
6409 ExportKeyAlgorithm::RsaOaep(_) |
6410 ExportKeyAlgorithm::Ecdsa(_) |
6411 ExportKeyAlgorithm::Ecdh(_) |
6412 ExportKeyAlgorithm::Ed25519(_) |
6413 ExportKeyAlgorithm::X25519(_) |
6414 ExportKeyAlgorithm::Ed448(_) |
6415 ExportKeyAlgorithm::X448(_) |
6416 ExportKeyAlgorithm::AesCtr(_) |
6417 ExportKeyAlgorithm::AesCbc(_) |
6418 ExportKeyAlgorithm::AesGcm(_) |
6419 ExportKeyAlgorithm::AesKw(_) |
6420 ExportKeyAlgorithm::Hmac(_) |
6421 ExportKeyAlgorithm::MlKem(_) |
6422 ExportKeyAlgorithm::HybridKem(_) |
6423 ExportKeyAlgorithm::MlDsa(_) |
6424 ExportKeyAlgorithm::AesOcb(_) |
6425 ExportKeyAlgorithm::ChaCha20Poly1305(_) |
6426 ExportKeyAlgorithm::Kmac(_) => true,
6427 }
6428 }
6429}
6430
6431impl ExportKeyAlgorithm {
6432 fn export_key(&self, format: KeyFormat, key: &CryptoKey) -> Result<ExportedKey, Error> {
6433 match self {
6434 ExportKeyAlgorithm::RsassaPkcs1V1_5(_algorithm) => {
6435 rsassa_pkcs1_v1_5_operation::export_key(format, key)
6436 },
6437 ExportKeyAlgorithm::RsaPss(_algorithm) => rsa_pss_operation::export_key(format, key),
6438 ExportKeyAlgorithm::RsaOaep(_algorithm) => rsa_oaep_operation::export_key(format, key),
6439 ExportKeyAlgorithm::Ecdsa(_algorithm) => ecdsa_operation::export_key(format, key),
6440 ExportKeyAlgorithm::Ecdh(_algorithm) => ecdh_operation::export_key(format, key),
6441 ExportKeyAlgorithm::Ed25519(_algorithm) => ed25519_operation::export_key(format, key),
6442 ExportKeyAlgorithm::X25519(_algorithm) => x25519_operation::export_key(format, key),
6443 ExportKeyAlgorithm::Ed448(_algorithm) => ed448_operation::export_key(format, key),
6444 ExportKeyAlgorithm::X448(_algorithm) => x448_operation::export_key(format, key),
6445 ExportKeyAlgorithm::AesCtr(_algorithm) => aes_ctr_operation::export_key(format, key),
6446 ExportKeyAlgorithm::AesCbc(_algorithm) => aes_cbc_operation::export_key(format, key),
6447 ExportKeyAlgorithm::AesGcm(_algorithm) => aes_gcm_operation::export_key(format, key),
6448 ExportKeyAlgorithm::AesKw(_algorithm) => aes_kw_operation::export_key(format, key),
6449 ExportKeyAlgorithm::Hmac(_algorithm) => hmac_operation::export_key(format, key),
6450 ExportKeyAlgorithm::MlKem(_algorithm) => ml_kem_operation::export_key(format, key),
6451 ExportKeyAlgorithm::HybridKem(_algorithm) => {
6452 hybrid_kem_operation::export_key(format, key)
6453 },
6454 ExportKeyAlgorithm::MlDsa(_algorithm) => ml_dsa_operation::export_key(format, key),
6455 ExportKeyAlgorithm::AesOcb(_algorithm) => aes_ocb_operation::export_key(format, key),
6456 ExportKeyAlgorithm::ChaCha20Poly1305(_algorithm) => {
6457 chacha20_poly1305_operation::export_key(format, key)
6458 },
6459 ExportKeyAlgorithm::Kmac(_algorithm) => kmac_operation::export_key(format, key),
6460 }
6461 }
6462}
6463
6464struct GetKeyLengthOperation {}
6466
6467impl Operation for GetKeyLengthOperation {
6468 type RegisteredAlgorithm = GetKeyLengthAlgorithm;
6469}
6470
6471enum GetKeyLengthAlgorithm {
6474 AesCtr(AesDerivedKeyParams),
6475 AesCbc(AesDerivedKeyParams),
6476 AesGcm(AesDerivedKeyParams),
6477 AesKw(AesDerivedKeyParams),
6478 Hmac(HmacImportParams),
6479 Hkdf(Algorithm),
6480 Pbkdf2(Algorithm),
6481 AesOcb(AesDerivedKeyParams),
6482 ChaCha20Poly1305(Algorithm),
6483 Kmac(KmacImportParams),
6484 Argon2(Algorithm),
6485}
6486
6487impl NormalizedAlgorithm for GetKeyLengthAlgorithm {
6488 fn from_object(
6489 cx: &mut js::context::JSContext,
6490 algorithm_name: CryptoAlgorithm,
6491 object: HandleObject,
6492 ) -> Fallible<Self> {
6493 match algorithm_name {
6494 CryptoAlgorithm::AesCtr => Ok(GetKeyLengthAlgorithm::AesCtr(
6495 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6496 )),
6497 CryptoAlgorithm::AesCbc => Ok(GetKeyLengthAlgorithm::AesCbc(
6498 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6499 )),
6500 CryptoAlgorithm::AesGcm => Ok(GetKeyLengthAlgorithm::AesGcm(
6501 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6502 )),
6503 CryptoAlgorithm::AesKw => Ok(GetKeyLengthAlgorithm::AesKw(
6504 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6505 )),
6506 CryptoAlgorithm::Hmac => Ok(GetKeyLengthAlgorithm::Hmac(
6507 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6508 )),
6509 CryptoAlgorithm::Hkdf => Ok(GetKeyLengthAlgorithm::Hkdf(
6510 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6511 )),
6512 CryptoAlgorithm::Pbkdf2 => Ok(GetKeyLengthAlgorithm::Pbkdf2(
6513 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6514 )),
6515 CryptoAlgorithm::AesOcb => Ok(GetKeyLengthAlgorithm::AesOcb(
6516 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6517 )),
6518 CryptoAlgorithm::ChaCha20Poly1305 => Ok(GetKeyLengthAlgorithm::ChaCha20Poly1305(
6519 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6520 )),
6521 CryptoAlgorithm::Kmac128 | CryptoAlgorithm::Kmac256 => Ok(GetKeyLengthAlgorithm::Kmac(
6522 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6523 )),
6524 CryptoAlgorithm::Argon2D | CryptoAlgorithm::Argon2I | CryptoAlgorithm::Argon2ID => {
6525 Ok(GetKeyLengthAlgorithm::Argon2(
6526 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6527 ))
6528 },
6529 _ => Err(Error::NotSupported(Some(format!(
6530 "{} does not support \"get key length\" operation",
6531 algorithm_name.as_str()
6532 )))),
6533 }
6534 }
6535
6536 fn name(&self) -> CryptoAlgorithm {
6537 match self {
6538 GetKeyLengthAlgorithm::AesCtr(algorithm) => algorithm.name,
6539 GetKeyLengthAlgorithm::AesCbc(algorithm) => algorithm.name,
6540 GetKeyLengthAlgorithm::AesGcm(algorithm) => algorithm.name,
6541 GetKeyLengthAlgorithm::AesKw(algorithm) => algorithm.name,
6542 GetKeyLengthAlgorithm::Hmac(algorithm) => algorithm.name,
6543 GetKeyLengthAlgorithm::Hkdf(algorithm) => algorithm.name,
6544 GetKeyLengthAlgorithm::Pbkdf2(algorithm) => algorithm.name,
6545 GetKeyLengthAlgorithm::AesOcb(algorithm) => algorithm.name,
6546 GetKeyLengthAlgorithm::ChaCha20Poly1305(algorithm) => algorithm.name,
6547 GetKeyLengthAlgorithm::Kmac(algorithm) => algorithm.name,
6548 GetKeyLengthAlgorithm::Argon2(algorithm) => algorithm.name,
6549 }
6550 }
6551
6552 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6553 match self {
6554 GetKeyLengthAlgorithm::AesCtr(normalized_derived_key_algorithm) |
6555 GetKeyLengthAlgorithm::AesCbc(normalized_derived_key_algorithm) |
6556 GetKeyLengthAlgorithm::AesGcm(normalized_derived_key_algorithm) |
6557 GetKeyLengthAlgorithm::AesKw(normalized_derived_key_algorithm) => {
6558 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
6559 },
6560 GetKeyLengthAlgorithm::Hmac(normalized_derived_key_algorithm) => {
6561 normalized_derived_key_algorithm
6562 .length
6563 .is_none_or(|length| length != 0)
6564 },
6565 GetKeyLengthAlgorithm::Hkdf(_) | GetKeyLengthAlgorithm::Pbkdf2(_) => true,
6566 GetKeyLengthAlgorithm::AesOcb(normalized_derived_key_algorithm) => {
6567 matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256)
6568 },
6569 GetKeyLengthAlgorithm::ChaCha20Poly1305(_) |
6570 GetKeyLengthAlgorithm::Kmac(_) |
6571 GetKeyLengthAlgorithm::Argon2(_) => true,
6572 }
6573 }
6574}
6575
6576impl GetKeyLengthAlgorithm {
6577 fn get_key_length(&self) -> Result<Option<u32>, Error> {
6578 match self {
6579 GetKeyLengthAlgorithm::AesCtr(algorithm) => {
6580 aes_ctr_operation::get_key_length(algorithm)
6581 },
6582 GetKeyLengthAlgorithm::AesCbc(algorithm) => {
6583 aes_cbc_operation::get_key_length(algorithm)
6584 },
6585 GetKeyLengthAlgorithm::AesGcm(algorithm) => {
6586 aes_gcm_operation::get_key_length(algorithm)
6587 },
6588 GetKeyLengthAlgorithm::AesKw(algorithm) => aes_kw_operation::get_key_length(algorithm),
6589 GetKeyLengthAlgorithm::Hmac(algorithm) => hmac_operation::get_key_length(algorithm),
6590 GetKeyLengthAlgorithm::Hkdf(_algorithm) => hkdf_operation::get_key_length(),
6591 GetKeyLengthAlgorithm::Pbkdf2(_algorithm) => pbkdf2_operation::get_key_length(),
6592 GetKeyLengthAlgorithm::AesOcb(algorithm) => {
6593 aes_ocb_operation::get_key_length(algorithm)
6594 },
6595 GetKeyLengthAlgorithm::ChaCha20Poly1305(_algorithm) => {
6596 chacha20_poly1305_operation::get_key_length()
6597 },
6598 GetKeyLengthAlgorithm::Kmac(algorithm) => kmac_operation::get_key_length(algorithm),
6599 GetKeyLengthAlgorithm::Argon2(_algorithm) => argon2_operation::get_key_length(),
6600 }
6601 }
6602}
6603
6604struct EncapsulateOperation {}
6606
6607impl Operation for EncapsulateOperation {
6608 type RegisteredAlgorithm = EncapsulateAlgorithm;
6609}
6610
6611enum EncapsulateAlgorithm {
6614 MlKem(Algorithm),
6615}
6616
6617impl NormalizedAlgorithm for EncapsulateAlgorithm {
6618 fn from_object(
6619 cx: &mut js::context::JSContext,
6620 algorithm_name: CryptoAlgorithm,
6621 object: HandleObject,
6622 ) -> Fallible<Self> {
6623 match algorithm_name {
6624 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6625 Ok(EncapsulateAlgorithm::MlKem(
6626 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6627 ))
6628 },
6629 _ => Err(Error::NotSupported(Some(format!(
6630 "{} does not support \"encapsulate\" operation",
6631 algorithm_name.as_str()
6632 )))),
6633 }
6634 }
6635
6636 fn name(&self) -> CryptoAlgorithm {
6637 match self {
6638 EncapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6639 }
6640 }
6641
6642 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6643 match self {
6644 EncapsulateAlgorithm::MlKem(_) => true,
6645 }
6646 }
6647}
6648
6649impl EncapsulateAlgorithm {
6650 fn encapsulate(&self, key: &CryptoKey) -> Result<EncapsulatedBits, Error> {
6651 match self {
6652 EncapsulateAlgorithm::MlKem(algorithm) => ml_kem_operation::encapsulate(algorithm, key),
6653 }
6654 }
6655}
6656
6657struct DecapsulateOperation {}
6659
6660impl Operation for DecapsulateOperation {
6661 type RegisteredAlgorithm = DecapsulateAlgorithm;
6662}
6663
6664enum DecapsulateAlgorithm {
6667 MlKem(Algorithm),
6668}
6669
6670impl NormalizedAlgorithm for DecapsulateAlgorithm {
6671 fn from_object(
6672 cx: &mut js::context::JSContext,
6673 algorithm_name: CryptoAlgorithm,
6674 object: HandleObject,
6675 ) -> Fallible<Self> {
6676 match algorithm_name {
6677 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6678 Ok(DecapsulateAlgorithm::MlKem(
6679 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6680 ))
6681 },
6682 _ => Err(Error::NotSupported(Some(format!(
6683 "{} does not support \"decapsulate\" operation",
6684 algorithm_name.as_str()
6685 )))),
6686 }
6687 }
6688
6689 fn name(&self) -> CryptoAlgorithm {
6690 match self {
6691 DecapsulateAlgorithm::MlKem(algorithm) => algorithm.name,
6692 }
6693 }
6694
6695 fn determine_support_from_operation_steps(&self, _length: Option<u32>) -> bool {
6696 match self {
6697 DecapsulateAlgorithm::MlKem(_) => true,
6698 }
6699 }
6700}
6701
6702impl DecapsulateAlgorithm {
6703 fn decapsulate(&self, key: &CryptoKey, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
6704 match self {
6705 DecapsulateAlgorithm::MlKem(algorithm) => {
6706 ml_kem_operation::decapsulate(algorithm, key, ciphertext)
6707 },
6708 }
6709 }
6710}
6711
6712struct GetSharedKeyLengthOperation {}
6714
6715impl Operation for GetSharedKeyLengthOperation {
6716 type RegisteredAlgorithm = GetSharedKeyLengthAlgorithm;
6717}
6718
6719enum GetSharedKeyLengthAlgorithm {
6722 MlKem(Algorithm),
6723}
6724
6725impl NormalizedAlgorithm for GetSharedKeyLengthAlgorithm {
6726 fn from_object(
6727 cx: &mut js::context::JSContext,
6728 algorithm_name: CryptoAlgorithm,
6729 object: HandleObject,
6730 ) -> Fallible<Self> {
6731 match algorithm_name {
6732 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6733 Ok(GetSharedKeyLengthAlgorithm::MlKem(
6734 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6735 ))
6736 },
6737 _ => Err(Error::NotSupported(Some(format!(
6738 "{} does not support \"get shared key length\" operation",
6739 algorithm_name.as_str()
6740 )))),
6741 }
6742 }
6743
6744 fn name(&self) -> CryptoAlgorithm {
6745 match self {
6746 GetSharedKeyLengthAlgorithm::MlKem(algorithm) => algorithm.name,
6747 }
6748 }
6749}
6750
6751impl GetSharedKeyLengthAlgorithm {
6752 fn get_shared_key_length(&self) -> u32 {
6753 match self {
6754 GetSharedKeyLengthAlgorithm::MlKem(_algorithm) => {
6755 ml_kem_operation::get_shared_key_length()
6756 },
6757 }
6758 }
6759}
6760
6761struct GetPublicKeyOperation {}
6763
6764impl Operation for GetPublicKeyOperation {
6765 type RegisteredAlgorithm = GetPublicKeyAlgorithm;
6766}
6767
6768enum GetPublicKeyAlgorithm {
6771 RsassaPkcs1v1_5(Algorithm),
6772 RsaPss(Algorithm),
6773 RsaOaep(Algorithm),
6774 Ecdsa(Algorithm),
6775 Ecdh(Algorithm),
6776 Ed25519(Algorithm),
6777 X25519(Algorithm),
6778 Ed448(Algorithm),
6779 X448(Algorithm),
6780 MlKem(Algorithm),
6781 MlDsa(Algorithm),
6782}
6783
6784impl NormalizedAlgorithm for GetPublicKeyAlgorithm {
6785 fn from_object(
6786 cx: &mut js::context::JSContext,
6787 algorithm_name: CryptoAlgorithm,
6788 object: HandleObject,
6789 ) -> Fallible<Self> {
6790 match algorithm_name {
6791 CryptoAlgorithm::RsassaPkcs1V1_5 => Ok(GetPublicKeyAlgorithm::RsassaPkcs1v1_5(
6792 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6793 )),
6794 CryptoAlgorithm::RsaPss => Ok(GetPublicKeyAlgorithm::RsaPss(
6795 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6796 )),
6797 CryptoAlgorithm::RsaOaep => Ok(GetPublicKeyAlgorithm::RsaOaep(
6798 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6799 )),
6800 CryptoAlgorithm::Ecdsa => Ok(GetPublicKeyAlgorithm::Ecdsa(
6801 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6802 )),
6803 CryptoAlgorithm::Ecdh => Ok(GetPublicKeyAlgorithm::Ecdh(
6804 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6805 )),
6806 CryptoAlgorithm::Ed25519 => Ok(GetPublicKeyAlgorithm::Ed25519(
6807 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6808 )),
6809 CryptoAlgorithm::X25519 => Ok(GetPublicKeyAlgorithm::X25519(
6810 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6811 )),
6812 CryptoAlgorithm::Ed448 => Ok(GetPublicKeyAlgorithm::Ed448(
6813 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6814 )),
6815 CryptoAlgorithm::X448 => Ok(GetPublicKeyAlgorithm::X448(
6816 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6817 )),
6818 CryptoAlgorithm::MlKem512 | CryptoAlgorithm::MlKem768 | CryptoAlgorithm::MlKem1024 => {
6819 Ok(GetPublicKeyAlgorithm::MlKem(
6820 object.try_into_with_cx_and_name(cx, algorithm_name)?,
6821 ))
6822 },
6823 CryptoAlgorithm::MlDsa44 | CryptoAlgorithm::MlDsa65 | CryptoAlgorithm::MlDsa87 => Ok(
6824 GetPublicKeyAlgorithm::MlDsa(object.try_into_with_cx_and_name(cx, algorithm_name)?),
6825 ),
6826 _ => Err(Error::NotSupported(Some(format!(
6827 "{} does not support \"getPublicKey\" operation",
6828 algorithm_name.as_str()
6829 )))),
6830 }
6831 }
6832
6833 fn name(&self) -> CryptoAlgorithm {
6834 match self {
6835 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(algorithm) => algorithm.name,
6836 GetPublicKeyAlgorithm::RsaPss(algorithm) => algorithm.name,
6837 GetPublicKeyAlgorithm::RsaOaep(algorithm) => algorithm.name,
6838 GetPublicKeyAlgorithm::Ecdsa(algorithm) => algorithm.name,
6839 GetPublicKeyAlgorithm::Ecdh(algorithm) => algorithm.name,
6840 GetPublicKeyAlgorithm::Ed25519(algorithm) => algorithm.name,
6841 GetPublicKeyAlgorithm::X25519(algorithm) => algorithm.name,
6842 GetPublicKeyAlgorithm::Ed448(algorithm) => algorithm.name,
6843 GetPublicKeyAlgorithm::X448(algorithm) => algorithm.name,
6844 GetPublicKeyAlgorithm::MlKem(algorithm) => algorithm.name,
6845 GetPublicKeyAlgorithm::MlDsa(algorithm) => algorithm.name,
6846 }
6847 }
6848}
6849
6850impl GetPublicKeyAlgorithm {
6851 fn get_public_key(
6852 &self,
6853 cx: &mut js::context::JSContext,
6854 global: &GlobalScope,
6855 key: &CryptoKey,
6856 algorithm: &KeyAlgorithmAndDerivatives,
6857 usages: Vec<KeyUsage>,
6858 ) -> Result<DomRoot<CryptoKey>, Error> {
6859 match self {
6860 GetPublicKeyAlgorithm::RsassaPkcs1v1_5(_algorithm) => {
6861 rsassa_pkcs1_v1_5_operation::get_public_key(cx, global, key, algorithm, usages)
6862 },
6863 GetPublicKeyAlgorithm::RsaPss(_algorithm) => {
6864 rsa_pss_operation::get_public_key(cx, global, key, algorithm, usages)
6865 },
6866 GetPublicKeyAlgorithm::RsaOaep(_algorithm) => {
6867 rsa_oaep_operation::get_public_key(cx, global, key, algorithm, usages)
6868 },
6869 GetPublicKeyAlgorithm::Ecdsa(_algorithm) => {
6870 ecdsa_operation::get_public_key(cx, global, key, algorithm, usages)
6871 },
6872 GetPublicKeyAlgorithm::Ecdh(_algorithm) => {
6873 ecdh_operation::get_public_key(cx, global, key, algorithm, usages)
6874 },
6875 GetPublicKeyAlgorithm::Ed25519(_algorithm) => {
6876 ed25519_operation::get_public_key(cx, global, key, algorithm, usages)
6877 },
6878 GetPublicKeyAlgorithm::X25519(_algorithm) => {
6879 x25519_operation::get_public_key(cx, global, key, algorithm, usages)
6880 },
6881 GetPublicKeyAlgorithm::Ed448(_algorithm) => {
6882 ed448_operation::get_public_key(cx, global, key, algorithm, usages)
6883 },
6884 GetPublicKeyAlgorithm::X448(_algorithm) => {
6885 x448_operation::get_public_key(cx, global, key, algorithm, usages)
6886 },
6887 GetPublicKeyAlgorithm::MlKem(_algorithm) => {
6888 ml_kem_operation::get_public_key(cx, global, key, algorithm, usages)
6889 },
6890 GetPublicKeyAlgorithm::MlDsa(_algorithm) => {
6891 ml_dsa_operation::get_public_key(cx, global, key, algorithm, usages)
6892 },
6893 }
6894 }
6895}